A modest collection of PHP libraries used at SparkFun.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

470 lines
11 KiB

<?php
namespace SparkLib;
use \MongoDBI as Mongo;
use \SparkLib\Iterator;
/**
* Class that creates a nice interface for accessing Mongo
*/
class MongoFinder extends Iterator {
protected $_mongo;
protected $_mongoCursor;
protected $_collection;
protected $_class;
protected $_query;
protected $_where = [];
protected $_sort = [];
protected $_row;
protected $_whereWaiting = false;
protected $_sortWaiting = false;
protected $_paramsChanged = false;
protected $_resultCount;
/**
* Create new instance and store the collection name to be used in find()
*
* @param string $collection - mongo collection in which search happens
* @param string $class - class in which to wrap mongo instance
*
* @return MongoFinder
*/
public function __construct($collection, $class) {
$this->_mongo = Mongo::getInstance();
$this->_collection = $collection;
$this->_class = $class;
return $this;
}
/**
* checks to see if you called either sortBy('something') or where('something')
* without calling asc()/desc() or eq()/is() respectively
*
* @return void
*/
protected function _checkWaiting() {
if ($this->_whereWaiting !== false)
throw new \Exception('Mongo WHERE waiting completion');
if ($this->_sortWaiting !== false)
throw new \Exception('Mongo SORT waiting completion');
}
/**
* adds parameter to where array that will be used in find()
*
* @param string $key - the key in the mongodb for which you want to search
*
* @return MongoFinder
*/
public function where($key) {
$this->_checkWaiting();
$this->_where[$key] = true;
$this->_whereWaiting = $key;
$this->_paramsChanged = true;
return $this;
}
/**
* adds parameter to where array that will be used in find()
*
* @param mixed $value - the value of the $key previously set in where()
* @param string $comparison (optional) comparison to make between $key and $value
*
* @return MongoFinder
*/
public function is($value, $comparison = false) {
if (! $this->_where[$this->_whereWaiting])
throw new \Exception('Mongo WHERE not called');
if (! $comparison) {
$comparison = '=';
}
switch($comparison) {
case '=':
$this->_where[$this->_whereWaiting] = $value;
break;
case '>':
$this->_where[$this->_whereWaiting] = [ '$gt' => $value ];
break;
case '>=':
$this->_where[$this->_whereWaiting] = [ '$gte' => $value ];
break;
case '<':
$this->_where[$this->_whereWaiting] = [ '$lt' => $value ];
break;
case '<=':
$this->_where[$this->_whereWaiting] = [ '$lte' => $value ];
break;
case 'in':
$this->_where[$this->_whereWaiting] = [ '$in' => $value ];
break;
}
$this->_paramsChanged = true;
$this->_whereWaiting = false;
return $this;
}
/**
* adds parameter to where array that will be used in find()
*
* @param string $regex - the regex to match the against $key previously set in where()
* @param string $flags - optional, regex search flags
*
* @return MongoFinder
*/
public function isLike($regex, $flags = '') {
if (! $this->_where[$this->_whereWaiting])
throw new \Exception('Mongo WHERE not called');
$this->_where[$this->_whereWaiting] = [ '$regex' => "$regex", '$options' => "$flags" ];
$this->_paramsChanged = true;
$this->_whereWaiting = false;
return $this;
}
/**
* adds parameter to where array that will be used in find() use for values
* you DO NOT want to be true
*
* example:
* where('cat_attitude')->not('angry'); // cat_attitude != angry
* where('cat_weight')->not(20, '>'); // ! cat_weight > 20
*
* @param mixed $value - the value of the $key previously set in where()
* @param string $comparison (optional) comparison to make between $key and $value
*
* @return MongoFinder
*/
public function isNot($value, $comparison = false) {
if (! $this->_where[$this->_whereWaiting])
throw new \Exception('Mongo WHERE not called');
if(! $comparison) {
$comparison = '=';
}
switch($comparison) {
case '=':
if (is_array($value))
$this->_where[$this->_whereWaiting] = [ '$not' => $value ];
else
$this->_where[$this->_whereWaiting] = [ '$not' => new MongoRegex('/^' . $value . '$/') ];
break;
case '>':
$this->_where[$this->_whereWaiting] = [ '$not' => [ '$gt' => $value ] ];
break;
case '>=':
$this->_where[$this->_whereWaiting] = [ '$not' => [ '$gte' => $value ] ];
break;
case '<':
$this->_where[$this->_whereWaiting] = [ '$not' => [ '$lt' => $value ] ];
break;
case '<=':
$this->_where[$this->_whereWaiting] = [ '$not' => [ '$lte' => $value ] ];
break;
}
$this->_paramsChanged = true;
$this->_whereWaiting = false;
return $this;
}
/**
* alias for is($value, '=')
*
* @param mixed $value value you're checking against $key set in where()
*
* @return MongoFinder
*/
public function eq($value) {
$this->_paramsChanged = true;
return $this->is($value, '=');
}
/**
* alias for is($value, 'in')
*
* @param mixed $value value you're checking against $key set in where()
*
* @return MongoFinder
*/
public function in($value) {
if(! is_array($value))
return $this;
$this->_paramsChanged = true;
return $this->is($value, 'in');
}
/**
* alias for is($value, [ '$exists' => false ])
*
* @return MongoFinder
*/
public function isNull() {
$this->_paramsChanged = true;
return $this->is([ '$exists' => false ], '=');
}
/**
* alias for is($value, [ '$exists' => true ])
*
* @return MongoFinder
*/
public function isNotNull() {
$this->_paramsChanged = true;
return $this->is([ '$exists' => true ], '=');
}
/**
* how to sort results of search
*
* @param mixed $order - if it's an array format: [ $sortKey => 1 ] if it
* is a string then format: sortkey
*
* @return MongoFinder
*/
public function orderBy($order) {
$this->_checkWaiting();
if (is_array($order)) {
foreach($order as $k => $v) {
switch($v) {
case 1:
case -1:
$this->_sort[$k] = $v;
break;
case 'ASC':
case 'asc':
$this->_sort[$k] = -1;
break;
case 'DESC':
case 'desc':
$this->_sort[$k] = 1;
break;
}
}
} else {
$this->_sort[$order] = true;
$this->_sortWaiting = $order;
}
$this->_paramsChanged = true;
return $this;
}
/**
* sort by asc, should be proceeded with a call to sort()
*
* @return MongoFinder
*/
public function asc() {
if (! $this->_sort[$this->_sortWaiting])
throw new \Exception('Mongo SORT not called');
$this->_sort[$this->_sortWaiting] = -1;
$this->_sortWaiting = false;
$this->_paramsChanged = true;
return $this;
}
/**
* sort by desc, should be proceeded with a call to sort()
*
* @return MongoFinder
*/
public function desc() {
if (! $this->_sort[$this->_sortWaiting])
throw new \Exception('Mongo SORT not called');
$this->_sort[$this->_sortWaiting] = 1;
$this->_sortWaiting = false;
$this->_paramsChanged = true;
return $this;
}
/**
* Moves internal pointer forward once
*
* @return MongoFinder
*/
public function next() {
$this->_checkWaiting();
if (! isset($this->_mongoCursor) || $this->_paramsChanged)
$this->find();
$this->_mongoCursor->next();
return $this;
}
/**
* Moves internal pointer forward by $int
*
* @param int $int - number of times to skip the internal pointer
*
* @return MongoFinder
*/
public function skip($int) {
$this->_checkWaiting();
if (! isset($this->_mongoCursor) || $this->_paramsChanged)
$this->find();
$this->_mongoCursor->skip($int);
return $this;
}
/**
* Moves internal pointer to beginning
*
* @return MongoFinder
*/
public function rewind() {
$this->_checkWaiting();
if (! isset($this->_mongoCursor) || $this->_paramsChanged)
$this->find();
$this->_mongoCursor->rewind();
return $this;
}
/**
* alias for getNext
*
* @return \Spark\$collection-wrapped Mongo thing
*/
public function getOne() {
return $this->getNext();
}
/**
* Returns the current result and iterates the pointer
*
* @return \Spark\$collection-wrapped mongo-thing
*/
public function getNext () {
$this->_checkWaiting();
if (! isset($this->_mongoCursor) || $this->_paramsChanged)
$this->find();
$result = $this->current();
if (false !== $result)
$this->next();
return $result;
}
/**
* Returns the current result at pointer
*
* @return \Spark\$collection-wrapped mongo-thing
*/
public function current() {
$this->_checkWaiting();
if (! isset($this->_mongoCursor) || $this->_paramsChanged)
$this->find();
if (! $this->_mongoCursor->current())
return false;
return new $this->_class($this->_mongoCursor->current());
}
/**
* get a count of the result ste
*
* @return int
*/
public function count() {
if (! isset($this->_mongoCursor) || $this->_paramsChanged) {
$this->find();
$this->_resultCount = null;
}
if (! isset($this->_resultCount))
$this->_resultCount = $this->_mongoCursor->count();
return $this->_resultCount;
}
/**
* Actually does the search on mongo and iterates the pointer so it's on a result
*
* @return MongoFinder
*/
public function find() {
$this->_checkWaiting();
$collection = $this->_collection;
$this->_mongoCursor = $this->_mongo->$collection->find($this->_where)->sort($this->_sort);
$this->_mongoCursor->next();
// Reset params so no new find runs
$this->_paramsChanged = false;
return $this;
}
/**
* Resets all query info
*/
public function reset() {
$this->_where = [];
$this->_sort = [];
$this->_whereWaiting = false;
$this->_sortWaiting = false;
$this->_paramsChanged = false;
$this->_resultCount = null;
$this->_row = null;
$this->_query = null;
$this->_mongoCursor = null;
}
/**
* Dumps mongo query as string
*
* @return string
*/
public function getQuery() {
return 'db.' . $this->_collection . '.find(' . json_encode($this->_where) . ').sort(' . json_encode($this->_sort) . ').pretty()';
}
/**
* Makes sure the current result is an instance of the class passed in
*
* @return boolean
*/
public function valid () {
return $this->_mongoCursor->current() instanceof $this->_class;
}
/**
* Returns the mongo id of the mongo entity currently under the pointer
*
* @return string
*/
public function key () {
if (! isset($this->_mongoCursor) || $this->_paramsChanged)
$this->find();
return (string) $this->current()->id();
}
}