merge() public static méthode

This method can be thought of as a hybrid between PHP's array_merge() and array_merge_recursive(). The difference to the two is that if an array key contains another array then the function behaves recursive (unlike array_merge()) but does not do if for keys containing strings (unlike array_merge_recursive()). Please note: This function will work with an unlimited amount of arguments and typecasts non-array parameters into arrays.
public static merge ( array $array1, array $array2 ) : array
$array1 array The base array.
$array2 array The array to be merged on top of the base array.
Résultat array Merged array of all passed params.
Exemple #1
0
 /**
  * Sets up the adapter with the configuration assigned by the `Session` class.
  *
  * @param array $config Available configuration options for this adapter:
  *				- `'config'` _string_: The name of the model that this adapter should use.
  */
 public function __construct(array $config = array())
 {
     $this->config = Set::merge($this->config, $config);
     if (empty($this->config['model']) || !class_exists($this->config['model'])) {
         throw new ConfigException("No valid model \"{$this->config['model']}\" available to use for Session interaction");
     } elseif (empty($this->config['entityManager']) && (!method_exists($this->config['model'], 'getEntityManager') || !is_callable($this->config['model'] . '::getEntityManager'))) {
         throw new ConfigException("The session model {$this->config['model']} must define a getEntityManager() static method, or you must set the entityManager session config variable");
     }
     $reflection = new \ReflectionClass($this->config['model']);
     if (!$reflection->implementsInterface('li3_doctrine2\\models\\ISession')) {
         throw new ConfigException("The model {$this->config['model']} must implement ISession");
     }
     $this->entityManager = $this->config['entityManager'] ?: call_user_func($this->config['model'] . '::getEntityManager');
     if (!isset($this->entityManager) || !$this->entityManager instanceof EntityManager) {
         throw new ConfigException('Not a valid entity manager');
     }
     $this->repository = $this->entityManager->getRepository($this->config['model']);
     foreach ($this->config['ini'] as $key => $config) {
         if (isset($this->config['ini'][$key]) && ini_set("session.{$key}", $this->config['ini'][$key]) === false) {
             throw new ConfigException("Could not initialize the session variable {$key}");
         }
     }
     session_set_save_handler(array(&$this, '_open'), array(&$this, '_close'), array(&$this, '_read'), array(&$this, '_write'), array(&$this, '_destroy'), array(&$this, '_gc'));
     register_shutdown_function('session_write_close');
     if ($this->config['start']) {
         $this->_startup();
     }
 }
Exemple #2
0
 /**
  *
  */
 public function __construct($config = array())
 {
     $defaults = array('proxy' => array('auto' => true, 'path' => LITHIUM_APP_PATH . '/resources/tmp/cache/Doctrine/Proxies', 'namespace' => 'Doctrine\\Proxies'), 'useModelDriver' => true, 'mapping' => array('class' => null, 'path' => LITHIUM_APP_PATH . '/models'), 'configuration' => null, 'eventManager' => null, 'utf-8' => true);
     $config = Set::merge($defaults, $config);
     $configuration = $config['configuration'] ?: new Configuration();
     $eventManager = $config['eventManager'] ?: new EventManager();
     $configuration->setProxyDir($config['proxy']['path']);
     $configuration->setProxyNamespace($config['proxy']['namespace']);
     $configuration->setAutoGenerateProxyClasses($config['proxy']['auto']);
     $configuration->setMetadataCacheImpl(new ArrayCache());
     // Annotation Driver
     $driver = $configuration->newDefaultAnnotationDriver(array(LITHIUM_APP_PATH . '/models'));
     $configuration->setMetadataDriverImpl($driver);
     // TODO: Not sure if this is required or not!
     // if (!$config['useModelDriver']) {
     // 	$configuration->setMetadataDriverImpl(new ModelDriver());
     // }
     $configuration->setSqlLogger(new SqlLogger());
     $mapping = array('adapter' => 'driver', 'login' => 'user', 'database' => 'dbname');
     foreach ($mapping as $source => $dest) {
         if (isset($config[$source]) && !isset($config[$dest])) {
             $config[$dest] = $config[$source];
             unset($config[$source]);
         }
     }
     $this->_em = EntityManager::create($config, $configuration, $eventManager);
     $this->_sm = $this->_em->getConnection()->getSchemaManager();
     if ($this->_em->getConnection()->getDriver() instanceof Driver\PDOMySql\Driver && $config['utf-8']) {
         $this->_em->getEventManager()->addEventSubscriber(new MysqlSessionInit('utf8', 'utf8_unicode_ci'));
     }
     parent::__construct($config);
 }
 public function testArrayConfiguration()
 {
     $result = Configurations::create(Set::merge($this->_default, array('type' => 'array', 'value' => 'foo=bar')));
     $this->assertEqual(array('foo' => 'bar'), $result->val());
     $this->assertEqual('bar', $result->val('foo'));
     $result = Configurations::create(Set::merge($this->_default, array('type' => 'array', 'value' => "foo.bar=baz\nfoo.baz=bar")));
     $this->assertEqual(array('foo' => array('bar' => 'baz', 'baz' => 'bar')), $result->val());
     $this->assertEqual(array('bar' => 'baz', 'baz' => 'bar'), $result->val('foo'));
     $this->assertEqual('baz', $result->val('foo.bar'));
 }
Exemple #4
0
 /**
  * Object constructor.
  * Instantiates the Memcached object, adds appropriate servers to the pool,
  * and configures any optional settings passed.
  *
  * @see lithium\storage\Cache::config()
  * @param array $config Configuration parameters for this cache adapter.
  *        These settings are indexed by name and queryable
  *        through `Cache::config('name')`.
  * @return void
  */
 public function __construct(array $config = array())
 {
     $defaults = array('prefix' => '', 'expiry' => '+1 hour', 'servers' => array(array('127.0.0.1', 11211, 100)));
     if (is_null(static::$connection)) {
         static::$connection = new \Memcached();
     }
     $configuration = Set::merge($defaults, $config);
     parent::__construct($configuration);
     static::$connection->addServers($this->_config['servers']);
 }
Exemple #5
0
 /**
  * Create `RecaptchaOptions` javascript object if you have additional options configured
  * @param array $options `'key' => 'value'` pairs to be converted to javascript
  * object as `RecaptchaOptions`
  * @see https://developers.google.com/recaptcha/docs/customization
  * @return null|string Return null if you don't have additional options
  * or script with `RecaptchaOptions` object
  */
 protected function _recaptchaOptions(array $options = array())
 {
     $defaults = Libraries::get('li3_recaptcha', 'options');
     if ($defaults) {
         $options = Set::merge($defaults, $options);
     }
     if (empty($options)) {
         return null;
     }
     $script = '<script type="text/javascript">';
     $script .= 'var RecaptchaOptions = ' . json_encode($options) . ';';
     $script .= '</script>';
     return $script;
 }
Exemple #6
0
 /**
  * Pulls request data from superglobals.
  *
  * @return void
  */
 protected function _init()
 {
     parent::_init();
     $mobile = array('iPhone', 'MIDP', 'AvantGo', 'BlackBerry', 'J2ME', 'Opera Mini', 'DoCoMo', 'NetFront', 'Nokia', 'PalmOS', 'PalmSource', 'portalmmm', 'Plucker', 'ReqwirelessWeb', 'iPod', 'SonyEricsson', 'Symbian', 'UP\\.Browser', 'Windows CE', 'Xiino', 'Android');
     if (!empty($this->_config['detectors']['mobile'][1])) {
         $mobile = array_merge($mobile, (array) $this->_config['detectors']['mobile'][1]);
     }
     $this->_detectors['mobile'][1] = $mobile;
     $this->_env += (array) $_SERVER + (array) $_ENV + array('REQUEST_METHOD' => 'GET');
     $envs = array('isapi' => 'IIS', 'cgi' => 'CGI', 'cgi-fcgi' => 'CGI');
     $this->_env['PLATFORM'] = isset($envs[PHP_SAPI]) ? $envs[PHP_SAPI] : null;
     $this->_base = isset($this->_base) ? $this->_base : $this->_base();
     $this->url = '/';
     if (isset($this->_config['url'])) {
         $this->url = rtrim($this->_config['url'], '/');
     } elseif (!empty($_GET['url'])) {
         $this->url = rtrim($_GET['url'], '/');
         unset($_GET['url']);
     }
     if (!empty($this->_config['query'])) {
         $this->query = $this->_config['query'];
     }
     if (isset($_GET)) {
         $this->query += $_GET;
     }
     if (!empty($this->_config['data'])) {
         $this->data = $this->_config['data'];
     } elseif (isset($_POST)) {
         $this->data += $_POST;
     }
     if (isset($this->data['_method'])) {
         $this->_env['HTTP_X_HTTP_METHOD_OVERRIDE'] = strtoupper($this->data['_method']);
         unset($this->data['_method']);
     }
     if (!empty($this->_env['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
         $this->_env['REQUEST_METHOD'] = $this->_env['HTTP_X_HTTP_METHOD_OVERRIDE'];
     }
     $method = strtoupper($this->_env['REQUEST_METHOD']);
     if (($method == 'POST' || $method == 'PUT') && !$this->data) {
         if (($type = $this->type()) && $type !== 'html') {
             $this->_stream = $this->_stream ?: fopen('php://input', 'r');
             $media = $this->_classes['media'];
             $this->data = (array) $media::decode($type, stream_get_contents($this->_stream));
             fclose($this->_stream);
         }
     }
     if (isset($_FILES) && $_FILES) {
         $result = array();
         $normalize = function ($key, $value) use($result, &$normalize) {
             foreach ($value as $param => $content) {
                 foreach ($content as $num => $val) {
                     if (is_numeric($num)) {
                         $result[$key][$num][$param] = $val;
                         continue;
                     }
                     if (is_array($val)) {
                         foreach ($val as $next => $one) {
                             $result[$key][$num][$next][$param] = $one;
                         }
                         continue;
                     }
                     $result[$key][$num][$param] = $val;
                 }
             }
             return $result;
         };
         foreach ($_FILES as $key => $value) {
             if (isset($value['name'])) {
                 if (is_string($value['name'])) {
                     $result[$key] = $value;
                     continue;
                 }
                 if (is_array($value['name'])) {
                     $result += $normalize($key, $value);
                 }
             }
         }
         $this->data = Set::merge((array) $this->data, $result);
     }
 }
Exemple #7
0
 /**
  * Instantiates a new record or document object, initialized with any data passed in. For
  * example:
  *
  * {{{
  * $post = Posts::create(array('title' => 'New post'));
  * echo $post->title; // echoes 'New post'
  * $success = $post->save();
  * }}}
  *
  * Note that while this method creates a new object, there is no effect on the database until
  * the `save()` method is called.
  *
  * In addition, this method can be used to simulate loading a pre-existing object from the
  * database, without actually querying the database:
  *
  * {{{
  * $post = Posts::create(array('id' => $id, 'moreData' => 'foo'), array('exists' => true));
  * $post->title = 'New title';
  * $success = $post->save();
  * }}}
  *
  * This will create an update query against the object with an ID matching `$id`. Also note that
  * only the `title` field will be updated.
  *
  * @param array $data Any data that this object should be populated with initially.
  * @param array $options Options to be passed to item.
  * @return object Returns a new, _un-saved_ record or document object. In addition to the values
  *         passed to `$data`, the object will also contain any values assigned to the
  *         `'default'` key of each field defined in `$_schema`.
  * @filter
  */
 public static function create(array $data = array(), array $options = array())
 {
     return static::_filter(__FUNCTION__, compact('data', 'options'), function ($self, $params) {
         $data = Set::merge(Set::expand($self::schema()->defaults()), $params['data']);
         return $self::connection()->item($self, $data, $params['options']);
     });
 }
Exemple #8
0
	public function testMerge() {
		$result = Set::merge(array('foo'), array());
		$this->assertIdentical($result, array('foo'));

		$result = Set::merge((array) 'foo', (array) 'bar');
		$this->assertIdentical($result, array('foo', 'bar'));

		$result = Set::merge((array) 'foo', array('user' => 'bob', 'no-bar'));
		$this->assertIdentical($result, array('foo', 'user' => 'bob', 'no-bar'));

		$a = array('foo', 'foo2');
		$b = array('bar', 'bar2');
		$this->assertIdentical(Set::merge($a, $b), array('foo', 'foo2', 'bar', 'bar2'));

		$a = array('foo' => 'bar', 'bar' => 'foo');
		$b = array('foo' => 'no-bar', 'bar' => 'no-foo');
		$this->assertIdentical(Set::merge($a, $b), array('foo' => 'no-bar', 'bar' => 'no-foo'));

		$a = array('users' => array('bob', 'jim'));
		$b = array('users' => array('lisa', 'tina'));
		$this->assertIdentical(
			Set::merge($a, $b), array('users' => array('bob', 'jim', 'lisa', 'tina'))
		);

		$a = array('users' => array('jim', 'bob'));
		$b = array('users' => 'none');
		$this->assertIdentical(Set::merge($a, $b), array('users' => 'none'));

		$a = array('users' => array('lisa' => array('id' => 5, 'pw' => 'secret')), 'lithium');
		$b = array('users' => array('lisa' => array('pw' => 'new-pass', 'age' => 23)), 'ice-cream');
		$this->assertIdentical(
			Set::merge($a, $b),
			array(
				'users' => array('lisa' => array('id' => 5, 'pw' => 'new-pass', 'age' => 23)),
				'lithium',
				'ice-cream'
			)
		);

		$c = array(
			'users' => array(
				'lisa' => array('pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')
			),
			'chocolate'
		);
		$expected = array(
			'users' => array(
				'lisa' => array(
					'id' => 5, 'pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog'
				)
			),
			'lithium',
			'ice-cream',
			'chocolate'
		);
		$this->assertIdentical($expected, Set::merge(Set::merge($a, $b), $c));

		$this->assertIdentical($expected, Set::merge(Set::merge($a, $b), Set::merge(array(), $c)));

		$result = Set::merge($a, Set::merge($b, $c));
		$this->assertIdentical($expected, $result);

		$a = array('Tree', 'CounterCache', 'Upload' => array(
			'folder' => 'products', 'fields' => array(
				'image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id'
			)
		));
		$b =  array(
			'Cacheable' => array('enabled' => false),
			'Limit', 'Bindable', 'Validator', 'Transactional'
		);

		$expected = array('Tree', 'CounterCache', 'Upload' => array(
			'folder' => 'products', 'fields' => array(
				'image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id'
			)),
			'Cacheable' => array('enabled' => false),
			'Limit',
			'Bindable',
			'Validator',
			'Transactional'
		);
		$this->assertIdentical(Set::merge($a, $b), $expected);

		$expected = array('Tree' => null, 'CounterCache' => null, 'Upload' => array(
			'folder' => 'products', 'fields' => array(
				'image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id'
			)),
			'Cacheable' => array('enabled' => false),
			'Limit' => null,
			'Bindable' => null,
			'Validator' => null,
			'Transactional' => null
		);
		$this->assertIdentical(Set::normalize(Set::merge($a, $b)), $expected);
	}
Exemple #9
0
 /**
  * Initialize request object, pulling request data from superglobals.
  *
  * Defines an artificial `'PLATFORM'` environment variable as either
  * `'IIS'`, `'CGI'` or `null` to allow checking for the SAPI in a
  * normalized way.
  *
  * @return void
  */
 protected function _init()
 {
     parent::_init();
     $mobile = array('iPhone', 'MIDP', 'AvantGo', 'BlackBerry', 'J2ME', 'Opera Mini', 'DoCoMo', 'NetFront', 'Nokia', 'PalmOS', 'PalmSource', 'portalmmm', 'Plucker', 'ReqwirelessWeb', 'iPod', 'SonyEricsson', 'Symbian', 'UP\\.Browser', 'Windows CE', 'Xiino', 'Android');
     if (!empty($this->_config['detectors']['mobile'][1])) {
         $mobile = array_merge($mobile, (array) $this->_config['detectors']['mobile'][1]);
     }
     $this->_detectors['mobile'][1] = $mobile;
     $defaults = array('REQUEST_METHOD' => 'GET', 'CONTENT_TYPE' => 'text/html');
     $this->_env += (array) $_SERVER + (array) $_ENV + $defaults;
     $envs = array('isapi' => 'IIS', 'cgi' => 'CGI', 'cgi-fcgi' => 'CGI');
     $this->_env['PLATFORM'] = isset($envs[PHP_SAPI]) ? $envs[PHP_SAPI] : null;
     $this->_base = $this->_base();
     $this->url = $this->_url();
     if (!empty($this->_config['query'])) {
         $this->query = $this->_config['query'];
     }
     if (isset($_GET)) {
         $this->query += $_GET;
     }
     if (!empty($this->_config['data'])) {
         $this->data = $this->_config['data'];
     }
     if (isset($_POST)) {
         $this->data += $_POST;
     }
     if (isset($this->data['_method'])) {
         $this->_env['HTTP_X_HTTP_METHOD_OVERRIDE'] = strtoupper($this->data['_method']);
         unset($this->data['_method']);
     }
     if (!empty($this->_env['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
         $this->_env['REQUEST_METHOD'] = $this->_env['HTTP_X_HTTP_METHOD_OVERRIDE'];
     }
     $type = $this->type($this->_env['CONTENT_TYPE']);
     $this->method = $method = strtoupper($this->_env['REQUEST_METHOD']);
     if (!$this->data && ($method == 'POST' || $method == 'PUT')) {
         if ($type !== 'html') {
             $this->_stream = $this->_stream ?: fopen('php://input', 'r');
             $media = $this->_classes['media'];
             $this->data = (array) $media::decode($type, stream_get_contents($this->_stream));
             fclose($this->_stream);
         }
     }
     $this->data = Set::merge((array) $this->data, $this->_parseFiles());
 }
Exemple #10
0
 /**
  * Instantiates a new record or document object, initialized with any data passed in. For
  * example:
  *
  * {{{
  * $post = Posts::create(array("title" => "New post"));
  * echo $post->title; // echoes "New post"
  * $success = $post->save();
  * }}}
  *
  * Note that while this method creates a new object, there is no effect on the database until
  * the `save()` method is called.
  *
  * In addition, this method can be used to simulate loading a pre-existing object from the
  * database, without actually querying the database:
  *
  * {{{
  * $post = Posts::create(array("id" => $id, "moreData" => "foo"), array("exists" => true));
  * $post->title = "New title";
  * $success = $post->save();
  * }}}
  *
  * This will create an update query against the object with an ID matching `$id`. Also note that
  * only the `title` field will be updated.
  *
  * @param array $data Any data that this object should be populated with initially.
  * @param array $options Options to be passed to item.
  * @return object Returns a new, _un-saved_ record or document object. In addition to the values
  *         passed to `$data`, the object will also contain any values assigned to the
  *         `'default'` key of each field defined in `$_schema`.
  * @filter
  */
 public static function create(array $data = array(), array $options = array())
 {
     $self = static::_object();
     $params = compact('data', 'options');
     return static::_filter(__FUNCTION__, $params, function ($self, $params) {
         $data = $params['data'];
         $options = $params['options'];
         $defaults = array();
         foreach ((array) $self::schema() as $field => $config) {
             if (isset($config['default'])) {
                 $defaults[$field] = $config['default'];
             }
         }
         $data = Set::merge(Set::expand($defaults), $data);
         return $self::connection()->item($self, $data, $options);
     });
 }
Exemple #11
0
 protected static function _appendObject($changes, $path, $key, $object)
 {
     $options = array('finalize' => false);
     if ($object->exists()) {
         return Set::merge($changes, static::_update($object->export()));
     }
     $changes['update']["{$path}{$key}"] = static::_create($object->export(), $options);
     return $changes;
 }
Exemple #12
0
	/**
	 * Adds an Access rule. This works much like the Validator class.
	 * All rules should be anonymous functions and will be passed
	 * $request, $resource, and $options which will contain the entire
	 * rule array which contains its own name plus other data that
	 * could be used to determine access.
	 *
	 * @param string $name The rule name.
	 * @param function $rule The closure for the rule, which has to return true or false.
	 */
	public static function add($name, $rule = null) {
		if (!is_array($name)) {
			$name = array($name => $rule);
		}
		self::$_rules = Set::merge(self::$_rules, $name);
	}
 /**
  * The manage method serves as both an index listing of all galleries as well
  * as a management tool for items within the gallery.
  * 
  * If no $id is passed, then an indexed listing of galleries (with links) will appear.
  * Clicking on one of these listed galleries will then return to this method with
  * and $id value present.
  * 
  * When an $id is present, the user will be able to add existing gallery items to 
  * the gallery as well as upload new gallery items to be associated with the gallery.
  * 
  * @param string $id The Page id for the gallery
  * @return
  */
 public function manage($id = null)
 {
     // TODO: Use Minerva's access system (li3_access)
     // Bigger todo: update li3_acess (Nate's changes) and redo Minerva's access system completely.
     $user = Auth::check('minerva_user');
     if ($user['role'] != 'administrator' && $user['role'] != 'content_editor') {
         $this->redirect('/');
         return;
     }
     if (empty($id)) {
         // Default options for pagination, merge with URL parameters
         $defaults = array('page' => 1, 'limit' => 10, 'order' => 'created.desc');
         $params = Set::merge($defaults, $this->request->params);
         if (isset($params['page']) && $params['page'] == 0) {
             $params['page'] = 1;
         }
         list($limit, $page, $order) = array($params['limit'], $params['page'], $params['order']);
         // Never allow a limit of 0
         $limit = $limit < 0 ? 1 : $limit;
         // Only pull back minerva_gallery pages
         $conditions = array('document_type' => 'minerva_gallery');
         // For search queries
         if (isset($this->request->query['q']) && !empty($this->request->query['q'])) {
             $search_schema = Page::searchSchema();
             $search_conditions = array();
             // For each searchable field, adjust the conditions to include a regex
             foreach ($search_schema as $k => $v) {
                 $search_regex = new \MongoRegex('/' . $this->request->query['q'] . '/i');
                 $conditions['$or'][] = array($k => $search_regex);
             }
         }
         // Get the documents and the total
         $documents = Page::find('all', array('conditions' => $conditions, 'limit' => (int) $limit, 'offset' => ((int) $page - 1) * (int) $limit, 'order' => $params['order']));
         $total = Page::find('count', array('conditions' => $conditions));
         $page_number = (int) $page;
         $total_pages = (int) $limit > 0 ? ceil($total / $limit) : 0;
         // Use the manage_index template in this case
         $this->_render['template'] = 'manage_index';
         // Set data for the view template
         $this->set(compact('documents', 'limit', 'page_number', 'total_pages', 'total'));
     } else {
         // Only pull the latest 30 gallery items from the entire system...
         // Because it's reasonable. There could be thousands of items and paging
         // through is an option, but not practical for the design and user experience.
         // 30 of the latest is enough and the user can make a search to find what
         // they are after. The point of this listing of items is to allow the user to
         // associate an existing item in the system with the current gallery.
         // It's not going to be as common as adding brand new items instead.
         // Well, unless the user really goes back to share items across multiple
         // galleries on a regular basis...I don't think it's common, but possible.
         // So showing 30 plus a search is plenty.
         $conditions = array('published' => true, '_galleries' => array('$nin' => array($id)));
         // For search queries for items
         if (isset($this->request->query['q']) && !empty($this->request->query['q'])) {
             $search_schema = Item::searchSchema();
             $search_conditions = array();
             // For each searchable field, adjust the conditions to include a regex
             foreach ($search_schema as $k => $v) {
                 $search_regex = new \MongoRegex('/' . $this->request->query['q'] . '/i');
                 $conditions['$or'][] = array($k => $search_regex);
             }
         }
         // Find the unassociated gallery items
         $items = Item::find('all', array('conditions' => $conditions, 'limit' => 30, 'order' => array('created' => 'desc')));
         // Find all items for the current gallery
         $gallery_items = Item::find('all', array('conditions' => array('_galleries' => $id)));
         // Find the gallery document itself
         $document = Page::find('first', array('conditions' => array('_id' => $id)));
         // Order those gallery items based on the gallery document's gallery_item_order field (if set)
         if (isset($document->gallery_item_order) && !empty($document->gallery_item_order)) {
             // This sort() method is the awesome.
             $ordering = $document->gallery_item_order->data();
             // data() must be called so that the iterator loads up all the documents...
             // Something that has to be fixed I guess. Then data() doesn't need to be called.
             $gallery_items->data();
             $gallery_items->sort(function ($a, $b) use($ordering) {
                 if ($a['_id'] == $b['_id']) {
                     return strcmp($a['_id'], $b['_id']);
                 }
                 $cmpa = array_search($a['_id'], $ordering);
                 $cmpb = array_search($b['_id'], $ordering);
                 return $cmpa > $cmpb ? 1 : -1;
             });
         }
         $this->set(compact('document', 'items', 'gallery_items'));
     }
 }
Exemple #14
0
 /**
  * Strategies used to query related objects, indexed by key.
  */
 protected function _strategies()
 {
     return array(static::LINK_EMBEDDED => function ($object, $relationship) {
         $fieldName = $relationship->fieldName();
         return $object->{$fieldName};
     }, static::LINK_CONTAINED => function ($object, $relationship) {
         $isArray = $relationship->type() === "hasMany";
         return $isArray ? $object->parent()->parent() : $object->parent();
     }, static::LINK_KEY => function ($object, $relationship, $options) {
         $model = $relationship->to();
         if (!($query = $relationship->query($object))) {
             return;
         }
         $method = $relationship->type() === "hasMany" ? 'all' : 'first';
         return $model::$method(Set::merge((array) $query, (array) $options));
     }, static::LINK_KEY_LIST => function ($object, $relationship, $options) {
         $model = $relationship->to();
         $query = $relationship->query($object);
         return $model::all(Set::merge($query, $options));
     });
 }
Exemple #15
0
 /**
  * Maps a type name to a particular content-type (or multiple types) with a set of options, or
  * retrieves information about a type that has been defined.
  *
  * Examples:
  * {{{ embed:lithium\tests\cases\net\http\MediaTest::testMediaTypes(1-2) }}}
  *
  * {{{ embed:lithium\tests\cases\net\http\MediaTest::testMediaTypes(19-23) }}}
  *
  * {{{ embed:lithium\tests\cases\net\http\MediaTest::testMediaTypes(43-44) }}}
  *
  * Alternatively, can be used to detect the type name of a registered content type:
  * {{{
  * Media::type('application/json'); // returns 'json'
  * Media::type('application/javascript'); // returns 'javascript'
  * Media::type('text/javascript'); // also returns 'javascript'
  *
  * Media::type('text/html'); // returns 'html'
  * Media::type('application/xhtml+xml'); // also returns 'html'
  * }}}
  *
  * #### Content negotiation
  *
  * When creating custom media types, specifying which content-type(s) to match isn't always
  * enough. For example, if you wish to serve a different set of templates to mobile web
  * browsers, you'd still want those templates served as HTML. You might add something like this:
  *
  * {{{
  * Media::type('mobile', array('application/xhtml+xml', 'text/html'));
  * }}}
  *
  * However, this would cause _all_ requests for HTML content to be interpreted as
  * `'mobile'`-type requests. Instead, we can use _content negotiation_ to granularly specify how
  * to match a particular type. Content negotiation is the process of examining the HTTP headers
  * provided in the request (including the content-types listed in the `Accept` header, and
  * optionally other things as well, like the `Accept-Language` or `User-Agent` headers), in
  * order to produce the best representation of the requested resource for the client; in other
  * words, the resource that most closely matches what the client is asking for.
  *
  * Content negotiation with media types is made possible through the `'conditions'` key of the
  * `$options` parameter, which contains an array of assertions made against the `Request`
  * object. Each assertion (array key) can be one of three different things:
  *
  * - `'type'` _boolean_: In the default routing, some routes have `{:type}` keys, which are
  *   designed to match file extensions in URLs. These values act as overrides for the HTTP
  *   `Accept` header, allowing different formats to be served with the same content type. For
  *    example, if you're serving [ JSONP](http://en.wikipedia.org/wiki/JSON#JSONP), you'll want
  *    to serve it with the same content-type as JavaScript (since it is JavaScript), but you
  *    probably won't want to use the same template(s) or other settings. Therefore, when serving
  *    JSONP content, you can specify that the extension defined in the type must be present in
  *    the URL:
  *  {{{
  *  Media::type('jsonp', array('text/html'), array(
  *  	// template settings...
  *  	'conditions' => array('type' => true)
  *  ));
  *  }}}
  *  Then, JSONP content will only ever be served when the request URL ends in `.jsonp`.
  *
  * - `'<prefix>:<key>'` _string_: This type of assertion can be used to match against arbitrary
  *   information in the request, including headers (i.e. `'http:user_agent'`), environment
  *   variables (i.e. `'env:home'`), GET and POST data (i.e. `'query:foo'` or `'data:foo'`,
  *   respectively), and the HTTP method (`'http:method'`) of the request. For more information
  *   on possible keys, see `lithium\action\Request::get()`.
  *
  * - `'<detector>'` _boolean_: Uses detector checks added to the `Request` object to make
  *   boolean assertions against the request. For example, if a detector called `'iPhone'` is
  *   attached, you can add `'iPhone' => true` to the `'conditions'` array in order to filter for
  *   iPhone requests only. See `lithium\action\Request::detect()` for more information on adding
  *   detectors.
  *
  * @see lithium\net\http\Media::$_types
  * @see lithium\net\http\Media::$_handlers
  * @see lithium\net\http\Media::negotiate()
  * @see lithium\action\Request::get()
  * @see lithium\action\Request::is()
  * @see lithium\action\Request::detect()
  * @see lithium\util\String::insert()
  * @param string $type A file-extension-style type name, i.e. `'txt'`, `'js'`, or `'atom'`.
  *               Alternatively, a mapped content type, i.e. `'text/html'`,
  *               `'application/atom+xml'`, etc.; in which case, the matching type name (i.e.
  *               '`html'` or `'atom'`) will be returned.
  * @param mixed $content Optional. A string or array containing the content-type(s) that
  *        `$type` should map to.  If `$type` is an array of content-types, the first one listed
  *        should be the "primary" type, and will be used as the `Content-type` header of any
  *        `Response` objects served through this type.
  * @param array $options Optional.  The handling options for this media type. Possible keys are:
  *        - `'view'` _string_: Specifies the view class to use when rendering this content.
  *          Note that no `'view'` class is specified by default.  If you want to
  *          render templates using Lithium's default view class, use
  *          `'lithium\template\View'`
  *        - `'decode'` _mixed_: A (string) function name or (object) closure that handles
  *          decoding or unserializing content from this format.
  *        - `'encode'` _mixed_: A (string) function name or (object) closure that handles
  *          encoding or serializing content into this format.
  *        - `'cast'` _boolean_: Used with `'encode'`. If `true`, all data passed into the
  *          specified encode function is first cast to array structures.
  *        - `'paths'` _array_: Optional key/value pairs mapping paths for
  *          `'template'`, `'layout'`, and `'element'` template files.  Any keys ommitted
  *          will use the default path.  The values should be `String::insert()`-style
  *          paths or an array of `String::insert()`-style paths.  If it is an array,
  *          each path will be tried in the order specified until a template is found.
  *          This is useful for allowing custom templates while falling back on
  *          default templates if no custom template was found.  If you want to
  *          render templates without a layout, use a `false` value for `'layout'`.
  *        - `'conditions'` _array_: Optional key/value pairs used as assertions in content
  *          negotiation. See the above section on **Content Negotiation**.
  * @return mixed If `$content` and `$options` are empty, returns an array with `'content'` and
  *         `'options'` keys, where `'content'` is the content-type(s) that correspond to
  *         `$type` (can be a string or array, if multiple content-types are available), and
  *         `'options'` is the array of options which define how this content-type should be
  *         handled.  If `$content` or `$options` are non-empty, returns `null`.
  */
 public static function type($type, $content = null, array $options = array())
 {
     $defaults = array('view' => false, 'paths' => array('template' => '{:library}/views/{:controller}/{:template}.{:type}.php', 'layout' => '{:library}/views/layouts/{:layout}.{:type}.php', 'element' => '{:library}/views/elements/{:template}.{:type}.php'), 'encode' => false, 'decode' => false, 'cast' => true, 'conditions' => array());
     if ($content === false) {
         unset(static::$_types[$type], static::$_handlers[$type]);
     }
     if (!$content && !$options) {
         if (!($content = static::_types($type))) {
             return;
         }
         if (strpos($type, '/')) {
             return $content;
         }
         if (is_array($content) && isset($content['alias'])) {
             return static::type($content['alias']);
         }
         return compact('content') + array('options' => static::_handlers($type));
     }
     if ($content) {
         static::$_types[$type] = (array) $content;
     }
     static::$_handlers[$type] = $options ? Set::merge($defaults, $options) : array();
 }
Exemple #16
0
 /**
  * Instantiates a new record or document object, initialized with any data passed in. For
  * example:
  *
  * ```
  * $post = Posts::create(array('title' => 'New post'));
  * echo $post->title; // echoes 'New post'
  * $success = $post->save();
  * ```
  *
  * Note that while this method creates a new object, there is no effect on the database until
  * the `save()` method is called.
  *
  * In addition, this method can be used to simulate loading a pre-existing object from the
  * database, without actually querying the database:
  *
  * ```
  * $post = Posts::create(array('id' => $id, 'moreData' => 'foo'), array('exists' => true));
  * $post->title = 'New title';
  * $success = $post->save();
  * ```
  *
  * This will create an update query against the object with an ID matching `$id`. Also note that
  * only the `title` field will be updated.
  *
  * @param array $data Any data that this object should be populated with initially.
  * @param array $options Options to be passed to item.
  * @return object Returns a new, _un-saved_ record or document object. In addition to the values
  *         passed to `$data`, the object will also contain any values assigned to the
  *         `'default'` key of each field defined in `$_schema`.
  * @filter
  */
 public static function create(array $data = array(), array $options = array())
 {
     $defaults = array('defaults' => true, 'class' => 'entity');
     $options += $defaults;
     return static::_filter(__FUNCTION__, compact('data', 'options'), function ($self, $params) {
         $class = $params['options']['class'];
         unset($params['options']['class']);
         if ($class === 'entity' && $params['options']['defaults']) {
             $data = Set::merge(Set::expand($self::schema()->defaults()), $params['data']);
         } else {
             $data = $params['data'];
         }
         $options = array('model' => $self, 'data' => $data) + $params['options'];
         return $self::invokeMethod('_instance', array($class, $options));
     });
 }
 /**
  * Creates a new instance of the Pagination class.
  *
  * Options can be configured by passing them through the $config array.
  *
  * @see app\extensions\helper\Pagination::_init()
  * @param array $config An array of options that can be configured during construction.
  *     They allow for the easy alteration of text used on prev/next links.
  *     Valid options are:
  *
  * @return object An instance of the Pagination class being constructed.
  */
 public function __construct(array $config = [])
 {
     parent::__construct(Set::merge(static::$_defaults, $config));
 }
Exemple #18
0
 /**
  * allows merging of data from context with given data
  *
  * @param array $data additional data to be put into view
  * @param array $options additional options
  *        - `merge`: set to false to disable merging view data with context
  * @return array
  */
 private function _data($data = array(), array $options = array())
 {
     $defaults = array('merge' => true);
     $options += $defaults;
     if ($options['merge'] === false) {
         return $data;
     }
     if (!empty($data)) {
         return Set::merge($this->_context->data(), $data);
     }
     return $this->_context->data();
 }
Exemple #19
0
<?php

use lithium\core\Libraries;
use lithium\core\ConfigException;
use lithium\template\View;
use lithium\net\http\Media;
use lithium\util\Set;
// Define path to plugin and other constants
defined('SMARTY_VERSION') or define('SMARTY_VERSION', '3.1.10');
// Allows us to test different versions without breaking things
defined('LI3_SMARTY_PATH') or define('LI3_SMARTY_PATH', dirname(__DIR__));
defined('LI3_SMARTY_LIB') or define('LI3_SMARTY_LIB', dirname(__DIR__) . "/libraries/Smarty/" . SMARTY_VERSION . "/libs/");
Libraries::add('Smarty', array("path" => LI3_SMARTY_LIB, "bootstrap" => "Smarty.class.php"));
$defaults = array('view' => '\\lithium\\template\\View', 'renderer' => '\\li3_smarty\\template\\view\\adapter\\Smarty', 'paths' => array('template' => array(LITHIUM_APP_PATH . '/views/{:controller}/{:template}.{:type}.tpl', '{:library}/views/{:controller}/{:template}.{:type}.tpl'), 'element' => array(LITHIUM_APP_PATH . '/views/elements/{:template}.html.tpl', '{:library}/views/elements/{:template}.html.tpl'), 'layout' => false), 'compile_dir' => LITHIUM_APP_PATH . '/resources/templates_c', 'cache_dir' => LITHIUM_APP_PATH . '/resources/cache', 'template_dir' => array(LITHIUM_APP_PATH . "/views", LITHIUM_APP_PATH . "/views/pages"), 'plugin_dir' => array(LI3_SMARTY_PATH . "/plugins", LITHIUM_APP_PATH . "/extensions/plugins"));
$keys = array_intersect_key($config, $defaults);
foreach ($keys as $key => $val) {
    if (is_array($defaults[$key])) {
        $defaults[$key] = Set::merge($defaults[$key], $config[$key]);
    } else {
        $defaults[$key] = $val;
    }
}
/**
 * Map to the new renderer
 */
Media::type('default', null, $defaults);
Exemple #20
0
 /**
  * Constructor. Instantiates the `Memcached` object, adds appropriate servers to the pool,
  * and configures any optional settings passed (see the `_init()` method). When adding
  * servers, the following formats are valid for the `'host'` key:
  *
  *   - `'127.0.0.1'`
  *      Configure the adapter to connect to one Memcache server on the default port.
  *
  *   - `'127.0.0.1:11222'`
  *      Configure the adapter to connect to one Memcache server on a custom port.
  *
  *   - `array('167.221.1.5:11222' => 200, '167.221.1.6')`
  *      Connect to one server on a custom port with a high selection weight, and
  *      a second server on the default port with the default selection weight.
  *
  * @see lithium\storage\Cache::config()
  * @param array $config Configuration for this cache adapter. These settings are queryable
  *        through `Cache::config('name')`. The available options are as follows:
  *        - `'scope'` _string_: Scope which will prefix keys; per default not set.
  *        - `'expiry'` _mixed_: The default expiration time for cache values, if no value
  *          is otherwise set. Can be either a `strtotime()` compatible tring or TTL in
  *          seconds. To indicate items should not expire use `Cache::PERSIST`. Defaults
  *          to `+1 hour`.
  *        - `'host'` _mixed_: Specifies one or more Memcache servers to connect to, with
  *          optional server selection weights. See above for example values.
  * @return void
  */
 public function __construct(array $config = array())
 {
     $defaults = array('scope' => null, 'expiry' => '+1 hour', 'host' => '127.0.0.1');
     parent::__construct(Set::merge($defaults, $config));
 }
Exemple #21
0
 /**
  * Creates, modifies or switches to an existing environment configuration. To create a new
  * configuration, or to update an existing configuration, pass an environment name and an array
  * that defines its configuration:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(1-1) }}}
  *
  * You can then add to an existing configuration by calling the `set()` method again with the
  * same environment name:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(6-6) }}}
  *
  * The settings for the environment will then be the aggregate of all `set()` calls:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(7-7) }}}
  *
  * By passing an array to `$env`, you can assign the same configuration to multiple
  * environments:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testSetMultipleEnvironments(5-7) }}}
  *
  * The `set()` method can also be called to manually set which environment to operate in:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(5-5) }}}
  *
  * Finally, `set()` can accept a `Request` object, to automatically detect the correct
  * environment.
  *
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testEnvironmentDetection(9-10) }}}
  *
  * For more information on defining custom rules to automatically detect your application's
  * environment, see the documentation for `Environment::is()`.
  *
  * @see lithium\action\Request
  * @see lithium\core\Environment::is()
  * @param mixed $env The name(s) of the environment(s) you wish to create, update or switch to
  *              (string/array), or a `Request` object or `$_SERVER` / `$_ENV` array used to
  *              detect (and switch to) the application's current environment.
  * @param array $config If creating or updating a configuration, accepts an array of settings.
  *              If the environment name specified in `$env` already exists, the values in
  *              `$config` will be recursively merged with any pre-existing settings.
  * @return array If creating or updating a configuration, returns an array of the environment's
  *               settings. If updating an existing configuration, this will be the newly-applied
  *               configuration merged with the pre-existing values. If setting the environment
  *               itself (i.e. `$config` is unspecified), returns `null`.
  */
 public static function set($env, $config = null)
 {
     if ($config === null) {
         if (is_object($env) || is_array($env)) {
             static::$_current = static::_detector()->__invoke($env);
         } elseif (isset(static::$_configurations[$env])) {
             static::$_current = $env;
         }
         return;
     }
     if (is_array($env)) {
         foreach ($env as $name) {
             static::set($name, $config);
         }
         return;
     }
     $env = $env === true ? static::$_current : $env;
     $base = isset(static::$_configurations[$env]) ? static::$_configurations[$env] : array();
     return static::$_configurations[$env] = Set::merge($base, $config);
 }
Exemple #22
0
 /**
  * Handles appending nested objects to document changesets.
  *
  * @param array $changes The full set of changes to be made to the database.
  * @param string $key The key of the field to append, which may be a dot-separated path if the
  *               value is or is contained within a nested object.
  * @param mixed $value The value to append to the changeset. Can be a scalar value, array, a
  *              nested object, or part of a nested object.
  * @param string $change The type of change, as to whether update/remove or rename etc.
  * @return array Returns the value of `$changes`, with any new changed values appended.
  */
 protected static function _append($changes, $key, $value, $change)
 {
     $options = array('finalize' => false);
     if (!is_object($value) || !method_exists($value, 'export')) {
         $changes[$change][$key] = $change == 'update' ? $value : true;
         return $changes;
     }
     if ($value->exists()) {
         if ($change == 'update') {
             $export = $value->export();
             $export['key'] = $key;
             return Set::merge($changes, static::_update($export));
         }
         $children = static::_update($value->export());
         if (!empty($children)) {
             return Set::merge($changes, $children);
         }
         $changes[$change][$key] = true;
         return $changes;
     }
     $changes['update'][$key] = static::_create($value->export(), $options);
     return $changes;
 }
Exemple #23
0
 /**
  * Initialize request object
  *
  * Defines an artificial `'PLATFORM'` environment variable as either `'IIS'`, `'CGI'` or `null`
  * to allow checking for the SAPI in a normalized way.
  */
 protected function _init()
 {
     parent::_init();
     $mobile = array('iPhone', 'MIDP', 'AvantGo', 'BlackBerry', 'J2ME', 'Opera Mini', 'DoCoMo', 'NetFront', 'Nokia', 'PalmOS', 'PalmSource', 'portalmmm', 'Plucker', 'ReqwirelessWeb', 'iPod', 'SonyEricsson', 'Symbian', 'UP\\.Browser', 'Windows CE', 'Xiino', 'Android');
     if (!empty($this->_config['detectors']['mobile'][1])) {
         $mobile = array_merge($mobile, (array) $this->_config['detectors']['mobile'][1]);
     }
     $this->_detectors['mobile'][1] = $mobile;
     $this->data = $this->_config['data'];
     if (isset($this->data['_method'])) {
         $this->_computed['HTTP_X_HTTP_METHOD_OVERRIDE'] = strtoupper($this->data['_method']);
         unset($this->data['_method']);
     }
     $type = $this->type($this->_config['type'] ?: $this->env('CONTENT_TYPE'));
     $this->method = $method = strtoupper($this->env('REQUEST_METHOD'));
     $hasBody = in_array($method, array('POST', 'PUT', 'PATCH'));
     if (!$this->body && $hasBody && $type !== 'html') {
         $this->_stream = $this->_stream ?: fopen('php://input', 'r');
         $this->body = stream_get_contents($this->_stream);
         fclose($this->_stream);
     }
     if (!$this->data && $this->body) {
         $this->data = $this->body(null, array('decode' => true, 'encode' => false));
     }
     $this->body = $this->data;
     $this->data = Set::merge((array) $this->data, $this->_parseFiles());
 }
Exemple #24
0
 /**
  * Allows you to configure a default set of options which are included on a per-method basis,
  * and configure method template overrides.
  *
  * To force all `<label />` elements to have a default `class` attribute value of `"foo"`,
  * simply do the following:
  *
  * {{{
  * $this->form->config(array('label' => array('class' => 'foo')));
  * }}}
  *
  * @param array $config An associative array where the keys are `Form` method names, and the
  *              values are arrays of configuration options to be included in the `$options`
  *              parameter of each method specified.
  * @return array Returns an array containing the currently set per-method configurations, and
  *         an array of the currently set template overrides (in the `'templates'` array key).
  * @see lithium\template\helper\Form::$_templateMap
  */
 public function config($config = array())
 {
     if (empty($config)) {
         return array('templates' => $this->_templateMap) + array_intersect_key($this->_config, array('base' => '', 'text' => '', 'textarea' => ''));
     }
     if (isset($config['templates'])) {
         $this->_templateMap = $config['templates'] + $this->_templateMap;
         unset($config['templates']);
     }
     return ($this->_config = Set::merge($this->_config, $config)) + array('templates' => $this->_templateMap);
 }
Exemple #25
0
 /**
  * Executes a query against a model based on a resource mapping configuration.
  *
  * @param array $options The query configuration for a single resource parameter. Available
  *              options are:
  *              - `'name'` _string_: The name of the resource parameter being queried.
  *              - `'binding'` _string_: The fully-namespaced class name of the model to query
  *                for the resource parameter.
  *              - `'call'` _mixed_: A string indicating the name of the method to call (i.e.
  *                `'find'` or `'first'`), or an array where the first item is the name of the
  *                method to call, and other available keys are `'conditions'` and `'order'`.
  *                See the `find()`/`first()` and `sort()` methods of `data\Collection` for
  *                information on valid values. Defaults to `'first'`.
  *              - `'required'` _boolean_: Boolean indicating whether this resource parameter is
  *                required. If `true`, and returning a single object, that object must
  *                exist. If `true` and returning a collection, that collection must contain
  *                one or more items. Defaults to `true`.
  *              - `'data'` _array_: The keyed array of other resources that have already been
  *                queried and are to be returned as the final result of `all()`. Primarily used
  *                in conjunction with the `'in'` option.
  *              - `'in'` _string_: A key representing a field in an existing resource in
  *                `'data'` that has already been queried. The typical use case is a 
  * @return object Returns the result of a model query, usually either an `Entity` or
  *         `Collection`.
  * @filter
  */
 public static function get($request, array $options = array())
 {
     $defaults = array('name' => null, 'binding' => null, 'call' => 'first', 'required' => true, 'data' => array(), 'params' => null, 'in' => null);
     $options += $defaults;
     $func = __FUNCTION__;
     return static::_filter($func, compact('request', 'options'), function ($self, $params) {
         $options = $params['options'];
         $request = $params['request'];
         if ($options['in']) {
             return $self::queryCollection($options, $query);
         }
         $query = $self::mapQuery($options, $request);
         $options['call'] = Set::merge($query, (array) $options['call']);
         if (!$options['call']['conditions'] && $options['params']) {
             return;
         }
         $options['binding'] = call_user_func($self::handlers('binding'), $request, $options);
         $func = $self::handlers($options['name']) ?: $self::handlers('default');
         if (is_array($func)) {
             $key = isset($options['call'][0]) ? $options['call'][0] : 'all';
             $func = is_string($key) && isset($func[$key]) ? $func[$key] : $func[0];
         }
         return $func($request, $options);
     });
 }
Exemple #26
0
	/**
	 * Adds an Access rule. This works much like the Validator class.
	 * All rules should be anonymous functions and will be passed
	 * $user, $request, and $options which will contain the entire
	 * rule array which contains its own name plus other data that
	 * could be used to determine access.
	 *
	 * @param string $name The rule name.
	 * @param function $rule The closure for the rule, which has to return true or false.
	 */
	public function add($name, $rule = null) {
		$this->_rules = Set::merge($this->_rules, is_array($name) ? $name : array($name => $rule));
	}
Exemple #27
0
 /**
  * Creates, modifies or switches to an existing environment configuration. To create a new
  * configuration, or to update an existing configuration, pass an environment name and an array
  * that defines its configuration:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(1-1) }}}
  *
  * You can then add to an existing configuration by calling the `set()` method again with the
  * same environment name:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(6-6) }}}
  *
  * The settings for the environment will then be the aggregate of all `set()` calls:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(7-7) }}}
  *
  * The `set()` method can also be called to manually set which environment to operate in:
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(5-5) }}}
  *
  * Finally, `set()` can accept a `Request` object, or the `$_SERVER` or `$_ENV` superglobals, to
  * automatically detect the correct environment.
  *
  * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testEnvironmentDetection(9-10) }}}
  *
  * For more information on defining custom rules to automatically detect your application's
  * environment, see the documentation for `Environment::is()`.
  *
  * @see lithium\http\Request
  * @see lithium\core\Environment::is()
  * @param mixed $env The name of the environment you wish to create, update or switch to
  *              (string), or a `Request` object or `$_SERVER` / `$_ENV` array used to detect
  *              (and switch to) the application's current environment.
  * @param array $config If creating or updating a configuration, accepts an array of settings.
  *              If the environment name specified in `$env` already exists, the values in
  *              `$config` will be recursively merged with any pre-existing settings.
  * @return array If creating or updating a configuration, returns an array of the environment's
  *               settings. If updating an existing configuration, this will be the newly-applied
  *               configuration merged with the pre-existing values. If setting the environment
  *               itself (i.e. `$config` is unspecified), returns `null`.
  */
 public static function set($env, $config = null)
 {
     if (is_null($config)) {
         switch (true) {
             case is_object($env) || is_array($env):
                 static::$_current = static::_detector()->__invoke($env);
                 break;
             case isset(static::$_configurations[$env]):
                 static::$_current = $env;
                 break;
         }
         return;
     }
     $env = $env === true ? static::$_current : $env;
     $base = isset(static::$_configurations[$env]) ? static::$_configurations[$env] : array();
     return static::$_configurations[$env] = Set::merge($base, $config);
 }
Exemple #28
0
 /**
  * Adds to or replaces built-in validation rules specified in `Validator::$_rules`.  Any new
  * validation rules created are automatically callable as validation methods.
  *
  * For example:
  * {{{
  * Validator::add('zeroToNine', '/^[0-9]$/');
  * $isValid = Validator::isZeroToNine("5"); // true
  * $isValid = Validator::isZeroToNine("20"); // false
  * }}}
  *
  * Alternatively, the first parameter may be an array of rules expressed as key/value pairs,
  * as in the following:
  * {{{
  * Validator::add(array(
  * 	'zeroToNine' => '/^[0-9]$/',
  * 	'tenToNineteen' => '/^1[0-9]$/',
  * ));
  * }}}
  *
  * In addition to regular expressions, validation rules can also be defined as full anonymous
  * functions:
  * {{{
  * use app\models\Account;
  *
  * Validator::add('accountActive', function($value) {
  * 	$value = is_int($value) ? Account::find($value) : $value;
  * 	return (boolean) $value->is_active;
  * });
  *
  * $testAccount = Account::create(array('is_active' => false));
  * Validator::isAccountActive($testAccount); // returns false
  * }}}
  *
  * These functions can take up to 3 parameters:
  * 	- `$value` _mixed_: This is the actual value to be validated (as in the above example).
  * 	- `$format` _string_: Often, validation rules come in multiple "formats", for example:
  * 	  postal codes, which vary by country or region. Defining multiple formats allows you to
  * 	  retian flexibility in how you validate data. In cases where a user's country of origin
  * 	  is known, the appropriate validation rule may be selected. In cases where it is not
  * 	  known, the value of `$format` may be `'any'`, which should pass if any format matches.
  * 	  In cases where validation rule formats are not mutually exclusive, the value may be
  * 	  `'all'`, in which case all must match.
  * 	- `$options` _array_: This parameter allows a validation rule to implement custom
  * 	  options.
  *
  * @see lithium\util\Validator::$_rules
  * @param mixed $name The name of the validation rule (string), or an array of key/value pairs
  *              of names and rules.
  * @param string $rule If $name is a string, this should be a string regular expression, or a
  *               closure that returns a boolean indicating success. Should be left blank if
  *               `$name` is an array.
  * @param array $options The default options for validating this rule. An option which applies
  *              to all regular expression rules is `'contains'` which, if set to true, allows
  *              validated values to simply _contain_ a match to a rule, rather than exactly
  *              matching it in whole.
  * @return void
  */
 public static function add($name, $rule = null, array $options = array())
 {
     if (!is_array($name)) {
         $name = array($name => $rule);
     }
     static::$_rules = Set::merge(static::$_rules, $name);
     if (!empty($options)) {
         $options = array_combine(array_keys($name), array_fill(0, count($name), $options));
         static::$_options = Set::merge(static::$_options, $options);
     }
 }
 /**
  * Generic index() action that returns a list of paginated documents.
  * The trick here is that $this->calling_class and $this->calling_method will hold a string
  * reference for which extended class called this index() method. We need that in order to
  * get the proper records and access.
 */
 public function index() {
     // get the "_type" ... page_type, user_type, or block_type
     $controller = $this->request->params['controller'];
     $controller_pieces = explode('.', $controller);
     if(count($controller_pieces) > 1) {
         $controller = end($controller_pieces);
     }
     $model = Inflector::classify(Inflector::singularize($controller));
     $modelClass = 'minerva\models\\'.$model;
     $x_type = strtolower($model) . '_type';
     // or set it to "all" if there wasn't a param passed
     $type = ((isset($this->request->params[$x_type])) && (in_array($x_type, $this->library_fields))) ? $this->request->params[$x_type]:'all';
     
     // Default options for pagination, merge with URL parameters
     $defaults = array('page' => 1, 'limit' => 10, 'order' => 'created.desc');
     $params = Set::merge($defaults, $this->request->params);
     if((isset($params['page'])) && ($params['page'] == 0)) {
         $params['page'] = 1;
     }
     list($limit, $page, $order) = array($params['limit'], $params['page'], $params['order']);
     
     // If there's a page/user/block_type passed, add it to the conditions, 'all' will show all pages.
     if($type != 'all') {
         $conditions = array($type => $this->request->params[$type]);
     } else {
         $conditions = array();
     }
     
     // If a search query was provided, search all "searchable" fields (any field in the model's $search_schema property)
     // NOTE: the values within this array for "search" include things like "weight" etc. and are not yet fully implemented...But will become more robust and useful.
     // Possible integration with Solr/Lucene, etc.
     if((isset($this->request->query['q'])) && (!empty($this->request->query['q']))) {
         $search_schema = $modelClass::search_schema();
         // If the "*_type" is set to "all" then we want to get all the model type's schemas, merge them into $schema
         if($type == 'all') {
         foreach(Util::list_types($model, array('exclude_minerva' => true)) as $library) {
             $extendedModelClass = 'minerva\libraries\\' . $library;
             $search_schema += $extendedModelClass::search_schema();
         }
         }
         
         $search_conditions = array();
         // For each searchable field, adjust the conditions to include a regex
         foreach($search_schema as $k => $v) {
         // TODO: possibly factor in the weighting later. also maybe note the "type" to ensure our regex is going to work or if it has to be adjusted (string data types, etc.)
         //var_dump($k);
         $search_regex = new \MongoRegex('/' . $this->request->query['q'] . '/i');
         $conditions['$or'][] = array($k => $search_regex);
         }
         
     }
     
     // Get the documents and the total
     $documents = array();
     if((int)$params['limit'] > 0) {
         $documents = $this->getDocument(array(
             'action' => $this->calling_method,
             'request' => $this->request,
             'find_type' => 'all',
             'conditions' => $conditions,
             'limit' => (int)$params['limit'],
             'offset' => ($params['page'] - 1) * $limit,
             'order' => $params['order']
         ));
     }
     
     // Get some handy numbers
     $total = $modelClass::find('count', array(
         'conditions' => $conditions
     ));
     $page_number = $params['page'];
     $total_pages = ((int)$params['limit'] > 0) ? ceil($total / $params['limit']):0;
     
     // Set data for the view template
     $this->set(compact('documents', 'limit', 'page_number', 'total_pages', 'total'));
 }