Exemplo n.º 1
0
 /**
  * Default constructor.
  *
  * @param string $endpoint_name
  *   Name of the endpoint. This is the path for the server, for e.g. "rest".
  */
 public function __construct($endpoint_name)
 {
     module_load_include('inc', 'services', 'includes/services.runtime');
     $this->endpoint_name = $endpoint_name;
     $endpoint = services_endpoint_load($this->endpoint_name);
     $server = $endpoint->server;
     services_set_server_info_from_array(array('module' => $server, 'endpoint' => $this->endpoint_name, 'endpoint_path' => $endpoint->path, 'debug' => $endpoint->debug, 'settings' => $endpoint->server_settings));
     $this->endpoint_path = services_get_server_info('endpoint_path', 'services/rest');
     $services_rest_server_factory = variable_get('services_rest_server_factory_class', 'ServicesRESTServerFactory');
     $this->rest_server_factory = new $services_rest_server_factory(array('endpoint_path' => $this->endpoint_path));
 }
Exemplo n.º 2
0
/**
 * Acts on requests to the server defined in hook_server_info().
 *
 * This is the main entry point to your server implementation.
 * Need to get some more description about the best way to implement
 * servers.
 */
function hook_server()
{
    $endpoint_path = services_get_server_info('endpoint_path', 'services/rest');
    $canonical_path = trim(drupal_substr($_GET['q'], drupal_strlen($endpoint_path)), '/');
    $canonical_path = explode('/', $_GET['q']);
    $endpoint_path_count = count(explode('/', $endpoint_path));
    for ($x = 0; $x < $endpoint_path_count; $x++) {
        array_shift($canonical_path);
    }
    $canonical_path = implode('/', $canonical_path);
    if (empty($canonical_path)) {
        return '';
    }
    //Handle server based on $canonical_path
}
 /**
  * Retrieves information about the current user
  *
  * @param object $info ["data"]
  *
  * @return object
  *
  * @Access(callback='user_access', args={'access content'}, appendArgs=false)
  */
 public static function roleUpdate($info)
 {
     $return = array('error' => TRUE);
     // Extract the info we need from post data
     $uid = $info->euid;
     $consumer = services_get_server_info('oauth_consumer');
     // Get site ID
     $result = db_query("SELECT * FROM {conglomerate_source} WHERE oauth_consumer='%s' LIMIT 1", $consumer->key);
     if ($result !== FALSE) {
         $site = db_fetch_object($result);
         $sid = $site->nid;
     }
     if ($result !== FALSE && $info->roles != NULL) {
         // Delete old roles (if any) to avoid duplicates
         db_query("DELETE FROM {conglomerate_user_roles} WHERE uid=%d AND sid=%d", $uid, $sid);
         // If no roles were sent it means user is deleted. And also, the for loop won't be run.
         foreach ($info->roles as $role) {
             db_query("INSERT INTO {conglomerate_user_roles} VALUES(%d, '%s', %d)", $uid, $role, $sid);
         }
         $return = array('error' => FALSE);
     }
     return (object) $return;
 }
 /**
  * Helper function that maps incoming data to the proper node attributes
  *
  * @param object $node
  * @param object $data
  * @return object
  */
 private static function nodeWrite($node, $data)
 {
     $oauth_consumer = services_get_server_info('oauth_consumer');
     $source = conglomerate_source_from_consumer($oauth_consumer);
     $attr = array('title' => array('required' => TRUE), 'text' => array('to' => 'body', 'required' => TRUE), 'position' => array('to' => 'simple_geo_position', 'required' => TRUE), 'tags' => array('required' => FALSE, 'adapt' => 'adaptTags'), 'metadata' => array('required' => FALSE, 'to' => 'conglomerate_metadata'), 'picture' => array('required' => FALSE, 'adapt' => 'adaptPicture'), 'large_picture' => array('required' => FALSE, 'adapt' => 'adaptLargePicture'), 'url' => array('required' => TRUE, 'adapt' => 'adaptUrl'), 'fulltext' => array('required' => FALSE, 'adapt' => 'adaptFulltext'), 'type' => array('required' => TRUE), 'language' => array('required' => TRUE), 'comments' => array('required' => FALSE));
     switch ($data->type) {
         case 'event':
             $attr['starts'] = array('adapt' => 'adaptStartTime', 'required' => TRUE);
             break;
         case 'subpage':
             $attr['searchable'] = array('adapt' => 'adaptSearchable', 'required' => TRUE);
             break;
     }
     drupal_alter('conglomerate_node_write_attributes', $attr, $data, $source);
     // Transfer attributes from data
     foreach ($attr as $name => $info) {
         if (isset($data->{$name})) {
             $to = $name;
             if (!empty($info['to'])) {
                 $to = $info['to'];
             }
             $node->{$to} = $data->{$name};
             if (isset($info['adapt'])) {
                 call_user_func('ConglomerateContentResource::' . $info['adapt'], $node);
             }
         } else {
             if ($info['required']) {
                 return services_error("Missing attribute {$name}", 406);
             }
         }
     }
     // Add information about the conglomerate source
     $node->conglomerate_source = $source->sid;
     $the_language = $node->language;
     node_save($node);
     // Workaround to preserve language. TODO: Must find out what is happening to the language.
     if (!$node->language) {
         db_query("UPDATE {node} SET language='%s' WHERE nid = %d", array(':language' => $the_language, ':nid' => $node->nid));
     }
     return (object) array('nid' => $node->nid, 'uri' => services_resource_uri(array('conglomerate-content', $node->nid)), 'url' => url('node/' . $node->nid, array('absolute' => TRUE)));
 }
 public function handle()
 {
     //A method is required, no matter what
     if (empty($this->method_name)) {
         $this->error(JSONRPC_ERROR_REQUEST, t("The received JSON not a valid JSON-RPC Request"));
     }
     $endpoint = services_get_server_info('endpoint');
     //Find the method
     $this->method = services_controller_get($this->method_name, $endpoint);
     $args = array();
     if (!isset($this->method)) {
         // No method found is a fatal error
         $this->error(JSONRPC_ERROR_PROCEDURE_NOT_FOUND, t("Invalid method @method", array('@method' => $request)));
     }
     //If needed, check if parameters can be omitted
     $arg_count = count($this->method['args']);
     if (!isset($this->params)) {
         for ($i = 0; $i < $arg_count; $i++) {
             $arg = $this->method['#args'][$i];
             if (!$arg['optional']) {
                 if (empty($this->params)) {
                     // We have required parameter, but we don't have any.
                     if (is_array($this->params)) {
                         // The request has probably been parsed correctly if params is an array,
                         // just tell the client that we're missing parameters.
                         $this->error(JSONRPC_ERROR_PARAMS, t("No parameters received, the method '@method' has required parameters.", array('@method' => $this->method_name)));
                     } else {
                         // If params isn't an array we probably have a syntax error in the json.
                         // Tell the client that there was a error while parsing the json.
                         // TODO: parse errors should be caught earlier
                         $this->error(JSONRPC_ERROR_PARSE, t("No parameters received, the likely reason is malformed json, the method '@method' has required parameters.", array('@method' => $this->method_name)));
                     }
                 }
             }
         }
     }
     // Map parameters to arguments, the 1.1 draft is more generous than the 2.0 proposal when
     // it comes to parameter passing. 1.1-d allows mixed positional and named parameters while
     // 2.0-p forces the client to choose between the two.
     //
     // 2.0 proposal on parameters: http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal#parameters-positional-and-named
     // 1.1 draft on parameters: http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#NamedPositionalParameters
     if ($this->array_is_assoc($this->params)) {
         $this->args = array();
         //Create a assoc array to look up indexes for parameter names
         $arg_dict = array();
         for ($i = 0; $i < $arg_count; $i++) {
             $arg = $this->method['args'][$i];
             $arg_dict[$arg['name']] = $i;
         }
         foreach ($this->params as $key => $value) {
             if ($this->major_version == 1 && preg_match('/^\\d+$/', $key)) {
                 //A positional argument (only allowed in v1.1 calls)
                 if ($key >= $arg_count) {
                     //Index outside bounds
                     $this->error(JSONRPC_ERROR_PARAMS, t("Positional parameter with a position outside the bounds (index: @index) received", array('@index' => $key)));
                 } else {
                     $this->args[intval($key)] = $value;
                 }
             } else {
                 //Associative key
                 if (!isset($arg_dict[$key])) {
                     //Unknown parameter
                     $this->error(JSONRPC_ERROR_PARAMS, t("Unknown named parameter '@name' received", array('@name' => $key)));
                 } else {
                     $this->args[$arg_dict[$key]] = $value;
                 }
             }
         }
     } else {
         //Non associative arrays can be mapped directly
         $param_count = count($this->params);
         if ($param_count > $arg_count) {
             $this->error(JSONRPC_ERROR_PARAMS, t("Too many arguments received, the method '@method' only takes '@num' argument(s)", array('@method' => $this->method_name, '@num' => $arg_count)));
         }
         $this->args = $this->params;
     }
     //Validate arguments
     for ($i = 0; $i < $arg_count; $i++) {
         $val = $this->args[$i];
         $arg = $this->method['args'][$i];
         if (isset($val)) {
             //If we have data
             if ($arg['type'] == 'struct' && is_array($val) && $this->array_is_assoc($val)) {
                 $this->args[$i] = $val = (object) $val;
             }
             //Only array-type parameters accepts arrays
             if (is_array($val) && $arg['type'] != 'array' && !($this->is_assoc($val) && $arg['type'] == 'struct')) {
                 $this->error_wrong_type($arg, 'array');
             } else {
                 if (($arg['type'] == 'int' || $arg['type'] == 'float') && !is_numeric($val)) {
                     $this->error_wrong_type($arg, 'string');
                 }
             }
         } else {
             if (!$arg['optional']) {
                 //Trigger error if a required parameter is missing
                 $this->error(JSONRPC_ERROR_PARAMS, t("Argument '@name' is required but was not received", array('@name' => $arg['name'])));
             }
         }
     }
     // We are returning JSON, so tell the browser.
     drupal_set_header('Content-Type: application/json; charset=utf-8');
     // Services assumes parameter positions to match the method callback's
     // function signature so we need to sort arguments by position (key)
     // before passing them to the method callback. The best solution here would
     // be to pad optional parameters using a #default key in the hook_service
     // method definitions instead of requiring all parameters to be present, as
     // we do now.
     // For reference: http://drupal.org/node/715044
     ksort($this->args);
     //Call service method
     try {
         $result = services_controller_execute($this->method, $this->args);
         return $this->result($result);
     } catch (ServicesException $e) {
         $this->error(JSONRPC_ERROR_INTERNAL_ERROR, $e->getMessage(), $e->getData());
     } catch (Exception $e) {
         $this->error(JSONRPC_ERROR_INTERNAL_ERROR, $e->getMessage());
     }
 }