locate() public static method

Libraries::locate('models', 'File'); Order of precedence is usually based on the order in which the library was registered (via Libraries::add()), unless the library was registered with the 'defer' option set to true. All libraries with the 'defer' option set will be searched in registration-order **after** searching all libraries **without** 'defer' set. This means that in the above example, if an app and a plugin both have a model named File, then the model from the app will be returned first, assuming the app was registered first (and assuming the default settings). If $name is not specified, locate() returns an array with all classes of the specified type which can be found. By default, locate() searches all registered libraries. Libraries::locate('models'); For example, the above will return an array of all model classes in all registered plugins and libraries (including the app itself). To learn more about adding and modifying the class paths used with locate(), see the documentation for the paths() method.
See also: lithium\core\Libraries::paths()
See also: lithium\core\Libraries::add()
See also: lithium\core\Libraries::_locateDeferred()
public static locate ( string $type, string $name = null, array $options = [] ) : mixed
$type string The type of class to search for. Typically follows the name of the directory in which the class is stored, i.e. `'models'`, `'controllers'` or `'adapter'`. Some classes types, such as adapters, will require a greater degree of specificity when looking up the desired class. In this case, the dot syntax is used, as in this example when looking up cache adapters: `'adapter.storage.cache'`, or this example, when looking up authentication adapters: `'adapter.security.auth'`.
$name string The base name (without namespace) of the class you wish to locate. If unspecified, `locate()` will attempt to find all classes of the type specified in `$type`. If you only wish to search for classes within a single plugin or library, you may use the dot syntax to prefix the class name with the library name, i.e. `'app.Post'`, which will only look for a `Post` model within the app itself.
$options array The options to use when searching and returning class names. - `'type'` _string_: Defaults to `'class'`. If set to `'file'`, returns file names instead of class names. - `'library'` _string_: When specified, only the given library/plugin name will be searched.
return mixed If `$name` is specified, returns the name of the first class found that matches `$name` and `$type`, or returns `null` if no matching classes were found in any registered library. If `$name` is not specified, returns an array of all classes found which match `$type`.
Beispiel #1
0
 /**
  * Read the configuration or access the connections you have set up.
  *
  * Usage:
  * {{{
  * // Gets the names of all available configurations
  * $configurations = Connections::get();
  *
  * // Gets the configuration array for the connection named 'db'
  * $config = Connections::get('db', array('config' => true));
  *
  * // Gets the instance of the connection object, configured with the settings defined for
  * // this object in Connections::add()
  * $dbConnection = Connections::get('db');
  *
  * // Gets the connection object, but only if it has already been built.
  * // Otherwise returns null.
  * $dbConnection = Connections::get('db', array('autoCreate' => false));
  * }}}
  *
  * @param string $name The name of the connection to get, as defined in the first parameter of
  *        `add()`, when the connection was initially created.
  * @param array $options Options to use when returning the connection:
  *        - `'autoCreate'`: If `false`, the connection object is only returned if it has
  *          already been instantiated by a previous call.
  *        - `'config'`: If `true`, returns an array representing the connection's internal
  *          configuration, instead of the connection itself.
  * @return mixed A configured instance of the connection, or an array of the configuration used.
  */
 public static function get($name = null, array $options = array())
 {
     static $mockAdapter;
     $defaults = array('config' => false, 'autoCreate' => true);
     $options += $defaults;
     if ($name === false) {
         if (!$mockAdapter) {
             $class = Libraries::locate('data.source', 'Mock');
             $mockAdapter = new $class();
         }
         return $mockAdapter;
     }
     if (!$name) {
         return array_keys(static::$_configurations);
     }
     if (!isset(static::$_configurations[$name])) {
         return null;
     }
     if ($options['config']) {
         return static::_config($name);
     }
     $settings = static::$_configurations[$name];
     if (!isset($settings[0]['object'])) {
         if (!$options['autoCreate']) {
             return null;
         }
     }
     return static::adapter($name);
 }
Beispiel #2
0
 /**
  * Get all test cases. By default, does not include function or integration tests.
  *
  * @param string $options
  * @return array
  */
 public static function all(array $options = array())
 {
     $defaults = array('library' => true, 'filter' => '/cases/', 'exclude' => '/mock/', 'recursive' => true);
     $options += $defaults;
     $classes = Libraries::locate('tests', null, $options);
     return $classes;
 }
Beispiel #3
0
 /**
  * Magic method to make Controller callable.
  *
  * @see lithium\action\Dispatcher::_callable()
  * @param object $request A \lithium\action\Request object.
  * @param array $dispatchParams Array of params after being parsed by router.
  * @param array $options Some basic options for this controller.
  * @return string
  */
 public function __invoke($request, $dispatchParams, array $options = array())
 {
     $dispatchParamsDefaults = array('args' => array());
     $dispatchParams += $dispatchParamsDefaults;
     $defaults = array('reporter' => 'html', 'format' => 'html');
     $options += (array) $request->query + $defaults;
     $params = compact('request', 'dispatchParams', 'options');
     set_time_limit(0);
     return $this->_filter(__METHOD__, $params, function ($self, $params) {
         $request = $params['request'];
         $options = $params['options'];
         $params = $params['dispatchParams'];
         $group = join('\\', (array) $params['args']);
         if ($group === "all") {
             $group = Group::all();
             $options['title'] = 'All Tests';
         }
         $report = Dispatcher::run($group, $options);
         $filters = Libraries::locate('test.filter');
         $menu = Libraries::locate('tests', null, array('filter' => '/cases|integration|functional/', 'exclude' => '/mocks/'));
         sort($menu);
         $result = compact('request', 'report', 'filters', 'menu');
         return $report->render('layout', $result);
     });
 }
 protected function _init()
 {
     parent::_init();
     $class = Libraries::locate('socket.util', $this->_classes['socket']);
     if (is_string($class)) {
         $this->_connection = new $class($this->_config);
     }
 }
 /**
  * Grab a the `layout.html.php` template and return output
  *
  * @param string $template name of the template (eg: layout)
  * @param string $data array from `_data()` method
  * @return string
  */
 protected function _render($template, $data)
 {
     $template = Libraries::locate('test.reporter.template', $template, array('filter' => false, 'type' => 'file', 'suffix' => '.html.php'));
     extract($data);
     ob_start();
     include $template;
     return ob_get_clean();
 }
Beispiel #6
0
 /**
  * Finds the test case for the corresponding class name.
  *
  * @param string $class A fully-namespaced class reference for which to find a test case.
  * @return string Returns the class name of a test case for `$class`, or `null` if none exists.
  */
 public static function get($class)
 {
     $parts = explode('\\', $class);
     $library = array_shift($parts);
     $name = array_pop($parts);
     $type = 'tests.cases.' . implode('.', $parts);
     return Libraries::locate($type, $name, compact('library'));
 }
Beispiel #7
0
 /**
  * Exercise initialization.
  *
  * @return void
  */
 public function _init()
 {
     parent::_init();
     Libraries::paths(array('exercises' => '{:library}\\extensions\\exercises\\{:name}'));
     $exercises = Libraries::locate('exercises');
     foreach ($exercises as $exercise) {
         $this->_exercises[$this->exerciseName($exercise)] = $exercise;
     }
 }
Beispiel #8
0
	public static function apply($model, array $behaviors) {
		foreach ($behaviors as $name => $config) {
			if (is_string($config)) {
				$name = $config;
				$config = array();
			}
			if ($class = Libraries::locate('behavior', $name)) {
				$class::bind($model, $config);
			}
		}
	}
Beispiel #9
0
 /**
  * Get all tests
  *
  * @param string $options
  * @return array
  */
 public static function all($options = array())
 {
     $defaults = array('transform' => false, 'library' => true);
     $options += $defaults;
     $m = '/\\\\tests\\\\cases\\\\(.+)Test$/';
     $transform = function ($class) use($m) {
         return preg_replace($m, '\\\\\\1', $class);
     };
     $classes = Libraries::locate('tests', null, $options + array('filter' => '/cases|integration|functional/', 'recursive' => true));
     return $options['transform'] ? array_map($transform, $classes) : $classes;
 }
Beispiel #10
0
 public function schema()
 {
     $data = Libraries::locate('models');
     $models = new Collection(compact('data'));
     if ($this->request->is('json')) {
         $models->each(function ($model) {
             $schema = is_callable(array($model, 'schema')) ? $model::schema() : array();
             return array($model => $schema ? $schema->fields() : array());
         });
     }
     return compact('models');
 }
 public function run()
 {
     $models = Libraries::locate('models', $this->model);
     if (empty($models)) {
         throw new Exception('Could not locate model: ' . $this->model);
     }
     if (!is_array($models)) {
         $models = array($models);
     }
     $counters = array('models' => 0, 'indexes' => 0);
     foreach ($models as $model) {
         $model = str_replace("\\\\", "\\", $model);
         if (property_exists($model, '_indexes')) {
             $indexes = $model::$_indexes;
             if (empty($indexes)) {
                 continue;
             }
             $db = $model::connection();
             if (!is_a($db, 'lithium\\data\\source\\MongoDb')) {
                 throw new Exception('This command works only with MongoDB');
             }
             $db->connect();
             $collection = $db->connection->{$model::meta('source')};
             $counters['models']++;
             $this->out('{:heading}Ensuring indexes for model: ' . $model . '{:end}');
             foreach ($indexes as $name => $index) {
                 if (empty($index['keys'])) {
                     $this->error(' * No keys defined for index: ' . $name);
                     continue;
                 }
                 $keys = $index['keys'];
                 unset($index['keys']);
                 if (!isset($index['name'])) {
                     $index['name'] = $name;
                 }
                 $options = $index + $this->defaults;
                 try {
                     $collection->ensureIndex($keys, $options);
                 } catch (Exception $e) {
                     $this->error(' * Failed: {:command}' . $name . '{:end} with: ' . $e->getMessage());
                     continue;
                 }
                 $counters['indexes']++;
                 $this->out(' * Ensured: {:command}' . $name . '{:end}');
             }
         }
     }
     $this->out('');
     $this->header('{:heading}Done! Ensured a total of ' . $counters['indexes'] . ' indexes on ' . $counters['models'] . ' models{:end}');
 }
Beispiel #12
0
 /**
  * Auto run the help command
  *
  * @param string $name COMMAND to get help
  * @return void
  */
 public function run($name = null)
 {
     if (!$name) {
         $this->out('COMMANDS', 'heading1', 2);
         $commands = Libraries::locate('command', null, array('recursive' => false));
         foreach ($commands as $command) {
             $info = Inspector::info($command);
             $name = strtolower(Inflector::slug($info['shortName']));
             $this->out($this->_pad($name), 'heading2');
             $this->out($this->_pad($info['description']), 2);
         }
         $message = 'See `{:command}li3 help COMMAND{:end}`';
         $message .= ' for more information on a specific command.';
         $this->out($message, 2);
         return true;
     }
     $name = Inflector::classify($name);
     if (!($class = Libraries::locate('command', $name))) {
         $this->error("{$name} not found");
         return false;
     }
     if (strpos($name, '\\') !== false) {
         $name = join('', array_slice(explode("\\", $name), -1));
     }
     $name = strtolower(Inflector::slug($name));
     $methods = $this->_methods($class);
     $properties = $this->_properties($class);
     $this->out('USAGE', 'heading1');
     $this->out($this->_pad(sprintf("{:command}li3 %s{:end}{:option}%s{:end} [ARGS]", $name ?: 'COMMAND', array_reduce($properties, function ($a, $b) {
         return "{$a} {$b['usage']}";
     }))));
     $info = Inspector::info($class);
     if (!empty($info['description'])) {
         $this->nl();
         $this->out('DESCRIPTION');
         $this->out($this->_pad(strtok($info['description'], "\n"), 1));
         $this->nl();
     }
     if ($properties || $methods) {
         $this->out('OPTIONS', 'heading2');
     }
     if ($properties) {
         $this->_render($properties);
     }
     if ($methods) {
         $this->_render($methods);
     }
     return true;
 }
Beispiel #13
0
 public function _init()
 {
     parent::_init();
     $this->socket = $this->_instance('socket', array('host' => $this->_config['host'], 'port' => $this->_config['port']));
     foreach (Libraries::locate('command.bot.plugins') as $class) {
         if (method_exists($class, 'poll')) {
             Logger::debug("Registering `poll` method from plugin `{$class}`.");
             $this->_plugins['poll'][] = new $class($this->_config);
         }
         if (method_exists($class, 'process')) {
             Logger::debug("Registering `process` method from plugin `{$class}`.");
             $this->_plugins['process'][] = new $class($this->_config);
         }
     }
 }
Beispiel #14
0
 public static function apply($report, $tests, array $options = array())
 {
     $rules = new Rules();
     $file = Libraries::get('li3_quality', 'path') . '/config/syntax.json';
     $config = json_decode(file_get_contents($file), true) + array('name' => null, 'rules' => array(), 'options' => array());
     foreach ($config['rules'] as $ruleName) {
         $class = Libraries::locate('rules.syntax', $ruleName);
         $rules->add(new $class());
     }
     if ($config['options']) {
         $rules->options($config['options']);
     }
     foreach ($tests->invoke('subject') as $class) {
         $report->collect(__CLASS__, array($class => $rules->apply(new Testable(array('path' => Libraries::path($class))))));
     }
     return $tests;
 }
Beispiel #15
0
 protected function _init()
 {
     parent::_init();
     $config = $this->_config;
     $singularName = $config['name'];
     if ($config['type'] == 'hasMany') {
         $singularName = Inflector::singularize($config['name']);
     }
     if (!$config['to']) {
         $assoc = preg_replace("/\\w+\$/", "", $config['from']) . $singularName;
         $config['to'] = class_exists($assoc) ? $assoc : Libraries::locate('models', $assoc);
     }
     if (!$config['fieldName']) {
         $config['fieldName'] = lcfirst($config['name']);
     }
     $config['keys'] = $this->_keys($config['keys'], $config);
     $this->_config = $config;
 }
Beispiel #16
0
 protected function _init()
 {
     parent::_init();
     foreach (array('loader', 'renderer') as $key) {
         if (is_object($this->_config[$key])) {
             $this->{'_' . $key} = $this->_config[$key];
             continue;
         }
         if (!($class = Libraries::locate('adapter.template.view', $this->_config[$key]))) {
             throw new RuntimeException("Template adapter {$this->_config[$key]} not found");
         }
         $this->{'_' . $key} = new $class(array('view' => $this) + $this->_config);
     }
     $h = function ($data) use(&$h) {
         return is_array($data) ? array_map($h, $data) : htmlspecialchars((string) $data);
     };
     $this->outputFilters += compact('h') + $this->_config['outputFilters'];
 }
Beispiel #17
0
 public function testLocateWithTestAppLibrary()
 {
     $testApp = Libraries::get(true, 'resources') . '/tmp/tests/test_app';
     mkdir($testApp, 0777, true);
     Libraries::add('test_app', array('path' => $testApp));
     mkdir($testApp . '/tests/cases/models', 0777, true);
     file_put_contents($testApp . '/tests/cases/models/UserTest.php', "<?php namespace test_app\\tests\\cases\\models;\n\n\t\t\tclass UserTest extends \\lithium\\test\\Unit { public function testMe() {\n\t\t\t\t\$this->assertTrue(true);\n\t\t\t}}");
     Libraries::cache(false);
     $expected = array('test_app\\tests\\cases\\models\\UserTest');
     $result = (array) Libraries::locate("tests", null, array('library' => 'test_app'));
     $this->assertEqual($expected, $result);
     $this->_cleanUp();
 }
Beispiel #18
0
    return $notify('warning', "You're using the application's default home page", "To change this {$template}, edit the file\n\t\t\t<code>views/pages/home.html.php</code>.\n\t\t\tTo change the layout,\n\t\t\t(that is what's wrapping content)\n\t\t\tedit the file <code>views/layouts/default.html.php</code>.");
}, 'dbSupport' => function () use($support) {
    $paths = array('data.source', 'adapter.data.source.database', 'adapter.data.source.http');
    $list = array();
    foreach ($paths as $path) {
        $list = array_merge($list, Libraries::locate($path, null, array('recursive' => false)));
    }
    $list = array_filter($list, function ($class) {
        return method_exists($class, 'enabled');
    });
    $map = array_combine($list, array_map(function ($c) {
        return $c::enabled();
    }, $list));
    return $support('Database support', $map);
}, 'cacheSupport' => function () use($support) {
    $list = Libraries::locate('adapter.storage.cache', null, array('recursive' => false));
    $list = array_filter($list, function ($class) {
        return method_exists($class, 'enabled');
    });
    $map = array_combine($list, array_map(function ($c) {
        return $c::enabled();
    }, $list));
    return $support('Cache support', $map);
}, 'routing' => function () use($support, $self) {
    $routing = $self->html->link('routing', 'http://li3.me/docs/lithium/net/http/Router');
    return $support('Custom routing', "Routes allow you to map custom URLs to your application code. To change the\n\t\t\t{$routing}, edit the file <code>config/routes.php</code>.");
}, 'tests' => function () use($notify, $support, $self) {
    if (Environment::is('production')) {
        $docsLink = $self->html->link('the documentation', 'http://li3.me/docs/lithium/core/Environment::is()');
        return $notify('error', "Can't run tests", "<p>Lithium's default environment detection rules have determined that you are\n\t\t\t\trunning in production mode. Therefore, you will not be able to run tests from the\n\t\t\t\tweb interface. You can do any of the following to remedy this:</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>Run this application locally</li>\n\t\t\t\t\t<li>Run tests from the console, using the <code>li3 test</code> command</li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\tImplementing custom environment detection rules;\n\t\t\t\t\t\tsee {$docsLink} for examples\n\t\t\t\t\t</li>\n\t\t\t\t</ul>");
    }
Beispiel #19
0
 /**
  * Initialization of the session.
  * Sets the session save handlers to this adapters' corresponding methods.
  *
  * @return void
  */
 protected function _init()
 {
     parent::_init();
     if (!$this->_config['model']) {
         $message = "A valid model is required to use the Model session adapter.";
         static::log($message, \Zend_Log::CRIT);
         throw new ConfigException($message);
     }
     foreach ($this->_defaults as $key => $config) {
         if (isset($this->_config[$key])) {
             if (ini_set("session.{$key}", $this->_config[$key]) === false) {
                 static::log("Failed to initialize the session", \Zend_Log::CRIT);
                 throw new ConfigException("Could not initialize the session.");
             }
         }
     }
     $this->_model = Libraries::locate('models', $this->_config['model']);
     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');
     $this->_startup();
 }
Beispiel #20
0
 /**
  * Creates the test report class based on either the passed test case or the
  * passed test group.
  *
  * @see lithium\test\Dispatcher::$_classes
  * @param string $group
  * @param array $options Options array passed from Dispatcher::run(). Should contain
  *        one of 'case' or 'group' keys.
  * @return object Group object constructed with the test case or group passed in $options.
  */
 protected static function _report($group, $options)
 {
     $report = Libraries::locate('test', static::$_classes['report']);
     $class = static::_instance($report, compact('group') + $options);
     return $class;
 }
Beispiel #21
0
 /**
  * Perform library location for an array of paths or a single string-based path.
  *
  * @param string|array $paths Paths that Libraries::locate() will utilize.
  * @param string $name The name of the class to be located.
  * @return string Fully-namespaced path to the class, or null if not found.
  */
 protected static function _locate($paths, $name)
 {
     foreach ((array) $paths as $path) {
         if ($class = Libraries::locate($path, $name)) {
             return $class;
         }
     }
     return null;
 }
Beispiel #22
0
 /**
  * Provide a list of test cases and accept input as case to run.
  *
  * @return void
  */
 protected function _getTests()
 {
     while (empty($this->case) && empty($this->group)) {
         $tests = Libraries::locate('tests', null, array('filter' => '/cases|integration|functional/', 'exclude' => '/mocks/'));
         $tests = str_replace('\\', '.', $tests);
         foreach ($tests as $key => $test) {
             $this->out(++$key . ". " . $test);
         }
         $number = $this->in("Choose a test case. (q to quit)");
         if (isset($tests[--$number])) {
             $this->case = $tests[$number];
         }
         if ($number == 'q') {
             return 0;
         }
     }
     return 1;
 }
Beispiel #23
0
 /**
  * Initializes values configured in the constructor.
  *
  * @return void
  */
 protected function _init()
 {
     parent::_init();
     foreach ($this->_fields as $key => $val) {
         if (is_int($key)) {
             unset($this->_fields[$key]);
             $this->_fields[$val] = $val;
         }
     }
     $this->_model = Libraries::locate('models', $this->_model);
 }
Beispiel #24
0
 public function filters(array $filters = array())
 {
     if ($this->_filters && !$filters) {
         return $this->_filters;
     }
     $filters += (array) $this->_config['filters'];
     $results = array();
     foreach ($filters as $filter => $options) {
         if (!($class = Libraries::locate('test.filter', $filter))) {
             throw new ClassNotFoundException("`{$class}` is not a valid test filter.");
         }
         $options['name'] = strtolower(join('', array_slice(explode("\\", $class), -1)));
         $results[$class] = $options + array('apply' => array(), 'analyze' => array());
     }
     return $this->_filters = $results;
 }
 /**
  * Get an instance of a sub-command
  *
  * @param string $name the name of the sub-command to instantiate
  * @param array $config
  * @return object;
  */
 protected function _instance($name, array $config = array())
 {
     if ($class = Libraries::locate('command.create', Inflector::camelize($name))) {
         $this->request->params['template'] = $this->template;
         return new $class(array('request' => $this->request, 'classes' => $this->_classes));
     }
     return parent::_instance($name, $config);
 }
Beispiel #26
0
 public static function bind($class)
 {
     $class::applyFilter('_callable', function ($self, $params, $chain) {
         $options = $params['options'];
         $name = $params['params']['controller'];
         if ($class = Libraries::locate('resources', $name, $options)) {
             if (strpos($class, 'Controller') === false) {
                 return Libraries::instance(null, $class, $options);
             }
         }
         return $chain->next($self, $params, $chain);
     });
 }
Beispiel #27
0
	/**
	 * Determines Command to use for current request.
	 *
	 * @param string $request
	 * @param string $params
	 * @param string $options
	 * @return class lithium\console\Command
	 * @filter
	 */
	protected static function _callable($request, $params, $options) {
		$params = compact('request', 'params', 'options');
		return static::_filter(__FUNCTION__, $params, function($self, $params) {
			$request = $params['request'];
			$params = $params['params'];
			$name = $params['command'];

			if (!$name) {
				$request->params['args'][0] = $name;
				$name = 'lithium\console\command\Help';
			}
			if (class_exists($class = Libraries::locate('command', $name))) {
				return new $class(compact('request'));
			}
			throw new UnexpectedValueException("Command `{$name}` not found.");
		});
	}
 protected function _init()
 {
     parent::_init();
     $config =& $this->_config;
     $type = $config['type'];
     $name = $type == 'hasOne' ? Inflector::pluralize($config['name']) : $config['name'];
     $config['fieldName'] = $config['fieldName'] ?: lcfirst($name);
     if (!$config['to']) {
         $assoc = preg_replace("/\\w+\$/", "", $config['from']) . $name;
         $config['to'] = Libraries::locate('models', $assoc);
     }
     if (!$config['key'] || !is_array($config['key'])) {
         $config['key'] = $this->_keys($config['key']);
     }
 }
 protected function _readEmbeddedFilter()
 {
     $processRelations = function ($data, $options, $model) use(&$processRelations) {
         if (isset($options['with']) && !empty($options['with'])) {
             $relations = $model::relations();
             if (!empty($relations)) {
                 foreach ($options['with'] as $key => $val) {
                     $relation = null;
                     if (!is_int($key) && isset($relations[$key])) {
                         $relation = $relations[$key]->data();
                         if (!empty($val)) {
                             $relation = array_merge($relation, $val);
                         }
                     } else {
                         if (!empty($val) && isset($relations[$val])) {
                             $relation = $relations[$val]->data();
                         }
                     }
                     if (!empty($relation)) {
                         $relationModel = Libraries::locate('models', $relation['to']);
                         if (!empty($relationModel) && isset($relation['embedded'])) {
                             $embedded_on = $relation['embedded'];
                             if (!empty($embedded_on)) {
                                 $records = method_exists($data, 'map') ? $data : array($data);
                                 foreach ($records as $k => $record) {
                                     $keys = explode('.', $embedded_on);
                                     $ref = $records[$k];
                                     foreach ($keys as $k => $key) {
                                         if (isset($ref->{$key})) {
                                             $ref = $ref->{$key};
                                         } else {
                                             continue 2;
                                         }
                                     }
                                     if (!empty($ref)) {
                                         // TODO : Add support for conditions, fields, order, page, limit
                                         $ref->setModel($relationModel);
                                         // why find? because we need to be able to filter embedded models, everything is protected in li3, so this was the best way
                                         $ref = $relationModel::find('all', array('embeddedData' => $processRelations($ref, $relation, $relationModel)));
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         return $data;
     };
     // filter for relations
     self::applyFilter('read', function ($self, $params, $chain) use($processRelations) {
         $results = $chain->next($self, $params, $chain);
         $queryOptions = $params['options'];
         $model = is_object($params['query']) ? $params['query']->model() : null;
         $results->applyFilter('_populate', function ($self, $params, $chain) use($queryOptions, $processRelations, $model) {
             $item = $chain->next($self, $params, $chain);
             if (!empty($item)) {
                 $item = $processRelations($item, $queryOptions, $model);
             }
             return $item;
         });
         return $results;
     });
 }
 /**
  * Extract an archive into a path. If one param exists, the app.phar.gz template will be used.
  * If both parameters exist, then the first will be the template archive and the second will be
  * the name of the extracted archive
  *
  * `li3 library extract myapp` : uses the command/create/template/app.phar.gz
  * `li3 library extract another_archive myapp`
  * `li3 library extract plugin li3_plugin` : uses the command/create/template/plugin.phar.gz
  *
  * @param string $name if only param, command/create/template/app.phar.gz extracted to $name
  *     otherwise, the template name or full path to extract `from` phar.gz.
  * @param string $result if exists $name is extracted to $result
  * @return boolean
  */
 public function extract($name = 'new', $result = null)
 {
     $from = 'app';
     $to = $name;
     if ($result) {
         $from = $name;
         $to = $result;
     }
     $to = $this->_toPath($to);
     if ($from[0] !== '/') {
         $from = Libraries::locate('command.create.template', $from, array('filter' => false, 'type' => 'file', 'suffix' => '.phar.gz'));
         if (!$from || is_array($from)) {
             return false;
         }
     }
     if (file_exists($from)) {
         $archive = new Phar($from);
         if ($archive->extractTo($to)) {
             $this->out(basename($to) . " created in " . dirname($to) . " from {$from}");
             return true;
         }
     }
     $this->error("Could not extract {$to} from {$from}");
     return false;
 }