/* {{{ MongoCursor->sort
 */
PHP_METHOD(MongoCursor, sort) {
  zval *orderby, *fields;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &fields) == FAILURE) {
    return;
  }
  if (IS_SCALAR_P(fields)) {
    zend_error(E_WARNING, "MongoCursor::sort() expects parameter 1 to be an array or object");
    return;
  }

  MAKE_STD_ZVAL(orderby);
  ZVAL_STRING(orderby, "$orderby", 1);

  MONGO_METHOD2(MongoCursor, addOption, return_value, getThis(), orderby, fields);

  zval_ptr_dtor(&orderby);
}
/* {{{ MongoCursor::fields
 */
PHP_METHOD(MongoCursor, fields) {
  zval *z;
  preiteration_setup;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &z) == FAILURE) {
    return;
  }
  if (IS_SCALAR_P(z)) {
    zend_error(E_WARNING, "MongoCursor::fields() expects parameter 1 to be an array or object");
    return;
  }

  zval_ptr_dtor(&cursor->fields);
  cursor->fields = z;
  zval_add_ref(&z);

  RETURN_ZVAL(getThis(), 1, 0);
}
Exemple #3
0
/* {{{ proto bool MongoDBRef::isRef(mixed ref)
   Checks if $ref has a $ref and $id property/key */
PHP_METHOD(MongoDBRef, isRef)
{
	zval *ref;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &ref) == FAILURE) {
		return;
	}

	if (IS_SCALAR_P(ref)) {
		RETURN_FALSE;
	}

	/* check that $ref and $id fields exists */
	if (zend_hash_exists(HASH_P(ref), "$ref", strlen("$ref") + 1) && zend_hash_exists(HASH_P(ref), "$id", strlen("$id") + 1)) {
		/* good enough */
		RETURN_TRUE;
	}

	RETURN_FALSE;
}
/* {{{ MongoCursor->hint
 */
PHP_METHOD(MongoCursor, hint) {
  zval *zfields, *query;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  if (cursor->started_iterating) {
    zend_throw_exception(mongo_ce_CursorException, "cannot modify cursor after beginning iteration.", 0 TSRMLS_CC);
    return;
  }

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zfields) == FAILURE ||
      IS_SCALAR_P(zfields)) {
    return;
  }

  query = cursor->query;
  zval_add_ref(&zfields);
  add_assoc_zval(query, "$hint", zfields);

  RETURN_ZVAL(getThis(), 1, 0);
}
Exemple #5
0
PHP_METHOD(MongoDB, command) {
  zval limit, *temp, *cmd, *cursor, *ns, *options = 0;
  mongo_db *db;
  mongo_link *link;
  char *cmd_ns;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &cmd, &options) == FAILURE) {
    return;
  }
  if (IS_SCALAR_P(cmd)) {
    zend_error(E_WARNING, "MongoDB::command() expects parameter 1 to be an array or object");
    return;
  }

  PHP_MONGO_GET_DB(getThis());

  // create db.$cmd
  MAKE_STD_ZVAL(ns);
  cmd_ns = get_cmd_ns(Z_STRVAL_P(db->name), Z_STRLEN_P(db->name));
  ZVAL_STRING(ns, cmd_ns, 0);

  // create cursor
  MAKE_STD_ZVAL(cursor);
  object_init_ex(cursor, mongo_ce_Cursor);
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  MONGO_METHOD3(MongoCursor, __construct, temp, cursor, db->link, ns, cmd);

  zval_ptr_dtor(&ns);
  zval_ptr_dtor(&temp);
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  // limit
  Z_TYPE(limit) = IS_LONG;
  Z_LVAL(limit) = -1;
  MONGO_METHOD1(MongoCursor, limit, temp, cursor, &limit);

  zval_ptr_dtor(&temp);

  if (options) {
    zval **timeout;
    if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout) == SUCCESS) {
      MAKE_STD_ZVAL(temp);
      ZVAL_NULL(temp);
      MONGO_METHOD1(MongoCursor, timeout, temp, cursor, *timeout);
      zval_ptr_dtor(&temp);
    }
  }

  // make sure commands aren't be sent to slaves
  PHP_MONGO_GET_LINK(db->link);
  if (link->rs) {
    zval slave_okay;
    Z_TYPE(slave_okay) = IS_BOOL;
    Z_LVAL(slave_okay) = 0;

    MAKE_STD_ZVAL(temp);
    ZVAL_NULL(temp);
    MONGO_METHOD1(MongoCursor, slaveOkay, temp, cursor, &slave_okay);
    zval_ptr_dtor(&temp);
  }

  // query
  MONGO_METHOD(MongoCursor, getNext, return_value, cursor);
  clear_exception(return_value TSRMLS_CC);

  zend_objects_store_del_ref(cursor TSRMLS_CC);
  zval_ptr_dtor(&cursor);
}
Exemple #6
0
static void php_mongo_enumerate_collections(INTERNAL_FUNCTION_PARAMETERS, int full_collection)
{
	zend_bool system_col = 0;
	zval *nss, *collection, *cursor, *list, *next;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &system_col) == FAILURE) {
		return;
	}

  // select db.system.namespaces collection
  MAKE_STD_ZVAL(nss);
  ZVAL_STRING(nss, "system.namespaces", 1);

  MAKE_STD_ZVAL(collection);
  MONGO_METHOD1(MongoDB, selectCollection, collection, getThis(), nss);

  // list to return
  MAKE_STD_ZVAL(list);
  array_init(list);

  // do find
  MAKE_STD_ZVAL(cursor);
  MONGO_METHOD(MongoCollection, find, cursor, collection);

  // populate list
  MAKE_STD_ZVAL(next);
  MONGO_METHOD(MongoCursor, getNext, next, cursor);
  while (!IS_SCALAR_P(next)) {
    zval *c, *zname;
    zval **collection;
    char *name, *first_dot, *system;

    // check that the ns is valid and not an index (contains $)
    if (zend_hash_find(HASH_P(next), "name", 5, (void**)&collection) == FAILURE ||
        strchr(Z_STRVAL_PP(collection), '$')) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    first_dot = strchr(Z_STRVAL_PP(collection), '.');
    system = strstr(Z_STRVAL_PP(collection), ".system.");
    // check that this isn't a system ns
    if (!system_col && (system && first_dot == system) ||
      (name = strchr(Z_STRVAL_PP(collection), '.')) == 0) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    // take a substring after the first "."
    name++;

    // "foo." was allowed in earlier versions
    if (name == '\0') {
      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

	if (full_collection) {
		MAKE_STD_ZVAL(c);
		ZVAL_NULL(c);

		MAKE_STD_ZVAL(zname);
		ZVAL_NULL(zname);

		// name must be copied because it is a substring of
		// a string that will be garbage collected in a sec
		ZVAL_STRING(zname, name, 1);
		MONGO_METHOD1(MongoDB, selectCollection, c, getThis(), zname);

		add_next_index_zval(list, c);

		zval_ptr_dtor(&zname);
	} else {
		add_next_index_string(list, name, 1);
	}
    zval_ptr_dtor(&next);
    MAKE_STD_ZVAL(next);

    MONGO_METHOD(MongoCursor, getNext, next, cursor);
  }

  zval_ptr_dtor(&next);
  zval_ptr_dtor(&nss);
  zval_ptr_dtor(&cursor);
  zval_ptr_dtor(&collection);

  RETURN_ZVAL(list, 0, 1);
}
Exemple #7
0
/* {{{ MongoDBRef::get()
 */
PHP_METHOD(MongoDBRef, get)
{
	zval *db, *ref, *collection, *query;
	zval **ns, **id, **dbname;
	zend_bool alloced_db = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz", &db, mongo_ce_DB, &ref) == FAILURE) {
		return;
	}

	if (
		IS_SCALAR_P(ref) ||
		zend_hash_find(HASH_P(ref), "$ref", strlen("$ref") + 1, (void**)&ns) == FAILURE ||
		zend_hash_find(HASH_P(ref), "$id", strlen("$id") + 1, (void**)&id) == FAILURE
	) {
		RETURN_NULL();
	}

	if (Z_TYPE_PP(ns) != IS_STRING) {
		zend_throw_exception(mongo_ce_Exception, "MongoDBRef::get: $ref field must be a string", 10 TSRMLS_CC);
		return;
	}

	/* if this reference contains a db name, we have to switch dbs */
	if (zend_hash_find(HASH_P(ref), "$db", strlen("$db") + 1, (void**)&dbname) == SUCCESS) {
		mongo_db *temp_db = (mongo_db*)zend_object_store_get_object(db TSRMLS_CC);

		/* just to be paranoid, make sure dbname is a string */
		if (Z_TYPE_PP(dbname) != IS_STRING) {
			zend_throw_exception(mongo_ce_Exception, "MongoDBRef::get: $db field must be a string", 11 TSRMLS_CC);
			return;
		}

		/* if the name in the $db field doesn't match the current db, make up
		 * a new db */
		if (strcmp(Z_STRVAL_PP(dbname), Z_STRVAL_P(temp_db->name)) != 0) {
			zval *new_db_z;

			MAKE_STD_ZVAL(new_db_z);
			ZVAL_NULL(new_db_z);

			MONGO_METHOD1(MongoClient, selectDB, new_db_z, temp_db->link, *dbname);

			/* make the new db the current one */
			db = new_db_z;

			/* so we can dtor this later */
			alloced_db = 1;
		}
	}

	/* get the collection */
	MAKE_STD_ZVAL(collection);
	MONGO_METHOD1(MongoDB, selectCollection, collection, db, *ns);

	/* query for the $id */
	MAKE_STD_ZVAL(query);
	array_init(query);
	add_assoc_zval(query, "_id", *id);
	zval_add_ref(id);

	/* return whatever's there */
	MONGO_METHOD1(MongoCollection, findOne, return_value, collection, query);

	/* cleanup */
	zval_ptr_dtor(&collection);
	zval_ptr_dtor(&query);
	if (alloced_db) {
		zval_ptr_dtor(&db);
	}
}
/* {{{ MongoCursor->__construct
 */
PHP_METHOD(MongoCursor, __construct) {
  zval *zlink = 0, *zns = 0, *zquery = 0, *zfields = 0, *empty, *timeout;
  zval **data;
  mongo_cursor *cursor;
  mongo_link *link;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|zz", &zlink,
                            mongo_ce_Mongo, &zns, &zquery, &zfields) == FAILURE) {
    return;
  }
  if ((zquery && IS_SCALAR_P(zquery)) || (zfields && IS_SCALAR_P(zfields))) {
    zend_error(E_WARNING, "MongoCursor::__construct() expects parameters 3 and 4 to be arrays or objects");
    return;
  }

  // if query or fields weren't passed, make them default to an empty array
  MAKE_STD_ZVAL(empty);
  object_init(empty);

  // these are both initialized to the same zval, but that's okay because 
  // there's no way to change them without creating a new cursor
  if (!zquery || (Z_TYPE_P(zquery) == IS_ARRAY && zend_hash_num_elements(HASH_P(zquery)) == 0)) {
    zquery = empty;
  }
  if (!zfields) {
    zfields = empty;
  }

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
  // db connection
  cursor->resource = zlink;
  zval_add_ref(&zlink);

  // db connection resource
  PHP_MONGO_GET_LINK(zlink);
  cursor->link = link;

  // change ['x', 'y', 'z'] into {'x' : 1, 'y' : 1, 'z' : 1}
  if (Z_TYPE_P(zfields) == IS_ARRAY) {
    HashPosition pointer;
    zval *fields;

    MAKE_STD_ZVAL(fields);
    array_init(fields);

    // fields to return
    for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zfields), &pointer); 
        zend_hash_get_current_data_ex(Z_ARRVAL_P(zfields), (void**) &data, &pointer) == SUCCESS; 
        zend_hash_move_forward_ex(Z_ARRVAL_P(zfields), &pointer)) {
      int key_type, key_len;
      ulong index;
      char *key;
      
      key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zfields), &key, (uint*)&key_len, &index, NO_DUP, &pointer);

      if (key_type == HASH_KEY_IS_LONG) {
        if (Z_TYPE_PP(data) == IS_STRING) {
          add_assoc_long(fields, Z_STRVAL_PP(data), 1);
        }
        else {
          zval_ptr_dtor(&empty);
          zval_ptr_dtor(&fields);
          zend_throw_exception(mongo_ce_Exception, "field names must be strings", 0 TSRMLS_CC);
          return;
        }
      }
      else {
        add_assoc_zval(fields, key, *data);
        zval_add_ref(data);
      }
    }
    cursor->fields = fields;
  }
  // if it's already an object, we don't have to worry
  else {
    cursor->fields = zfields;
    zval_add_ref(&zfields);
  }

  // ns
  convert_to_string(zns);
  cursor->ns = estrdup(Z_STRVAL_P(zns));

  // query
  cursor->query = zquery;
  zval_add_ref(&zquery);

  // reset iteration pointer, just in case
  MONGO_METHOD(MongoCursor, reset, return_value, getThis());

  cursor->at = 0;
  cursor->num = 0;
  cursor->special = 0;
  cursor->persist = 0;
  
  timeout = zend_read_static_property(mongo_ce_Cursor, "timeout", strlen("timeout"), NOISY TSRMLS_CC);
  cursor->timeout = Z_LVAL_P(timeout);

  cursor->opts = link->slave_okay ? (1 << 2) : 0;
  
  // get rid of extra ref
  zval_ptr_dtor(&empty);
}
Exemple #9
0
PHP_METHOD(MongoDB, listCollections) {
  // select db.system.namespaces collection
  zval *nss, *collection, *cursor, *list, *next;

  MAKE_STD_ZVAL(nss);
  ZVAL_STRING(nss, "system.namespaces", 1);

  MAKE_STD_ZVAL(collection);
  MONGO_METHOD1(MongoDB, selectCollection, collection, getThis(), nss);

  // list to return
  MAKE_STD_ZVAL(list);
  array_init(list);

  // do find
  MAKE_STD_ZVAL(cursor);
  MONGO_METHOD(MongoCollection, find, cursor, collection);

  // populate list
  MAKE_STD_ZVAL(next);
  MONGO_METHOD(MongoCursor, getNext, next, cursor);
  while (!IS_SCALAR_P(next)) {
    zval *c, *zname;
    zval **collection;
    char *name, *first_dot, *system;

    // check that the ns is valid and not an index (contains $)
    if (zend_hash_find(HASH_P(next), "name", 5, (void**)&collection) == FAILURE ||
        strchr(Z_STRVAL_PP(collection), '$')) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    first_dot = strchr(Z_STRVAL_PP(collection), '.');
    system = strstr(Z_STRVAL_PP(collection), ".system.");
    // check that this isn't a system ns
    if ((system && first_dot == system) ||
	(name = strchr(Z_STRVAL_PP(collection), '.')) == 0) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    // take a substring after the first "."
    name++;

    // "foo." was allowed in earlier versions
    if (name == '\0') {
      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    MAKE_STD_ZVAL(c);
    ZVAL_NULL(c);

    MAKE_STD_ZVAL(zname);
    ZVAL_NULL(zname);

    // name must be copied because it is a substring of
    // a string that will be garbage collected in a sec
    ZVAL_STRING(zname, name, 1);
    MONGO_METHOD1(MongoDB, selectCollection, c, getThis(), zname);

    add_next_index_zval(list, c);

    zval_ptr_dtor(&zname);
    zval_ptr_dtor(&next);
    MAKE_STD_ZVAL(next);

    MONGO_METHOD(MongoCursor, getNext, next, cursor);
  }

  zval_ptr_dtor(&next);
  zval_ptr_dtor(&nss);
  zval_ptr_dtor(&cursor);
  zval_ptr_dtor(&collection);

  RETURN_ZVAL(list, 0, 1);
}