/** * returns rendered content * * @param string $content input content * @param string $data field to retrieve from configuration * @param array $options an array with additional options * @return string content as given * @filter */ public function get($content, $data = null, array $options = array()) { $defaults = array('default' => array(), 'flat' => false); $options += $defaults; $params = compact('content', 'data', 'options'); return $this->_filter(__METHOD__, $params, function ($self, $params) { extract($params); try { $config = NeonFormatter::decode($content); } catch (NeonException $e) { return $options['default']; } catch (Exception $e) { return $options['default']; } if (!empty($data) && is_scalar($data)) { if (array_key_exists($data, (array) $config)) { return $config[$data]; } } if ($data) { $data = '/' . str_replace('.', '/', $data) . '/.'; $result = current(Set::extract((array) $config, $data)); return !empty($result) ? $result : null; } return $options['flat'] ? Set::flatten($config) : $config; }); }
/** * Renders a group of navigations defined as Configurations. * * A Configuration with a type ´navigation´ must follow this naming conventions: * nav.{name of navigation group}.{name of navigation} * e.g. nav.sidebar.main, nav.sidebar.mailplugin, ... * * $this->Navigation->group('sidebar') will render all Configurations with a slug starting with * ´nav.sidebar.´ that are of type `navigation`. In addition it renders all navigations based * on files from all loaded libraries, that have files at {:library}/data/nav/{:name}.foo.neon * * @param string $name part of a navigation slug * @param array $options additional options: * - `pattern`: pattern of slug to search configurations of, defaults to `nav.{:name}.` * - `seperator`: glue-character to implode all navigations together with * - `db`: set to false to avoid database-based rendering of navigations (configurations) * - `files`: set to false to avoid file-based rendering of navigations * @return string all navigations */ public function group($name, array $options = array()) { $defaults = array('pattern' => 'nav.{:name}.', 'seperator' => "\n", 'files' => true, 'db' => true); $options += $defaults; $search = String::insert($options['pattern'], compact('name')); $result = array(); if ($options['db']) { $configs = Configurations::search($search); if ($configs) { foreach ($configs as $nav) { $result[] = $this->render($nav); } } } if (!$options['files']) { return implode($options['seperator'], $result); } $conditions = array('slug' => $name); $files = Neon::find(array('source' => 'nav', 'key' => 'slug'), 'all', compact('conditions')); if ($files) { foreach ($files as $file => $nav) { $caption = Inflector::humanize(str_replace(sprintf('%s.', $name), '', $file)); $result[] = $this->render($nav, compact('caption')); } } return implode($options['seperator'], $result); }
/** * allows for data-retrieval of entities via file-based access * * In case you want to provide default file-data without inserting them into the database, you * would need to create files based on model-name in a path like that * `{:library}/data/{:class}/{:id}.neon` or `{:library}/data/{:class}/{:slug}.neon` * * In that case, an entity requested by id or slug would be loaded from file instead. Please pay * attention, though that not all options are implemented, such as extended conditions, order, * limit or page. This is meant to enable basic loading of id- or slug-based entity lookups. * * @see radium\util\Neon::file() * @see radium\util\File::contents() * @param string $type The find type, which is looked up in `Model::$_finders`. By default it * accepts `all`, `first`, `list` and `count`, * @param array $options Options for the query. By default, accepts: * - `conditions`: The conditional query elements, e.g. * `'conditions' => array('published' => true)` * - `fields`: The fields that should be retrieved. When set to `null`, defaults to * all fields. * - `order`: The order in which the data will be returned, e.g. `'order' => 'ASC'`. * - `limit`: The maximum number of records to return. * - `page`: For pagination of data. * @return mixed */ public static function find($type, array $options = array()) { $result = parent::find($type, $options); $neon = static::meta('neon'); if ($neon && (!$result || !count($result))) { return Neon::find(get_called_class(), $type, $options); } return $result; }
/** * Loads entities and records from file-based structure * * Trys to implement a similar method to load datasets not from database, but rather from * a file that holds all relevant model data and is laid into the filesystem of each library. * This allows for easy default-data to be loaded without using a database as backend. * * Put your files into `{:library}\data\{:class}\{:name}.neon` and let the content be found * with loading just the id or slug of that file. * * Attention: This feature is considered experimental and should be used with care. It might * not work as expected. Also, not all features are implemented. * * If nothing is found, it just returns null or an empty array to ensure a falsey value. * * @param string|array $model fully namespaced model class, e.g. `radium\models\Contents` * can also be an array, in which case `key` and `source` must be given * according to the internal structure of `Model::meta()`. * @param string $type The find type, which is looked up in `Model::$_finders`. By default it * accepts `all`, `first`, `list` and `count`. Later two are not implement, yet. * @param array $options Options for the query. By default, accepts: * - `conditions`: The conditional query elements, e.g. * `'conditions' => array('published' => true)` * - `fields`: The fields that should be retrieved. When set to `null`, defaults to * all fields. * - `order`: The order in which the data will be returned, e.g. `'order' => 'ASC'`. * - `limit`: The maximum number of records to return. * - `page`: For pagination of data. * @return mixed returns null or an empty array if nothing is found * If `$type` is `first` returns null or the correct entity with given data * If `$type` is `all` returns null or a DocumentSet object with loaded entities */ public static function find($model, $type, array $options = array()) { $defaults = array('conditions' => null, 'fields' => null); $options += $defaults; $paths = self::$_paths; Libraries::paths($paths); $meta = is_array($model) ? $model : $model::meta(); $locate = sprintf('neons.%s', $meta['source']); $data = Libraries::locate($locate, null, array('namespaces' => true)); $files = new Collection(compact('data')); unset($data); $files->each(function ($file) { return str_replace('\\', '/', $file) . 'neon'; }); extract($options); if (isset($conditions['slug'])) { $field = 'slug'; } if (isset($conditions[$meta['key']])) { $field = $meta['key']; } if (!isset($field)) { $field = 'all'; // var_dump($field); // return array(); } $value = $conditions[$field]; switch (true) { case is_string($value): $pattern = sprintf('/%s/', $value); break; case isset($value['like']): $pattern = $value['like']; break; } if (isset($pattern)) { $filter = function ($file) use($pattern) { return (bool) preg_match($pattern, $file); }; } if (isset($filter)) { $files = $files->find($filter); } if (isset($order)) { // TODO: add sort } if ($type == 'count') { return count($files); } if ($type == 'list') { // TODO: implement me } if ($type == 'first' && count($files)) { $data = self::file($files->first()); $data[$field] = $value; if ($model === 'radium\\models\\Configurations') { $data['value'] = Neon::encode($data['value']); } return $model::create($data); } // we found one (!) file with name 'all.neon', this is the entire set if ($type == 'all' && count($files) == 1 && substr($files->first(), -strlen('all.neon')) === 'all.neon') { $rows = self::file($files->first()); $data = array(); foreach ($rows as $row) { $data[] = $model::create($row); } if (is_array($model)) { return new Collection(compact('data')); } $model = $meta['class']; return new DocumentSet(compact('data', 'model')); } if ($type == 'all' && count($files)) { $data = array(); foreach ($files as $file) { $current = self::file($file); if (is_array($model)) { $filename = File::name($file); $data[$filename] = $current; continue; } if ($model === 'radium\\models\\Configurations') { $current['value'] = Neon::encode($current['value']); } $data[] = $model::create($current); } if (is_array($model)) { return new Collection(compact('data')); } $model = $meta['class']; return new DocumentSet(compact('data', 'model')); } return false; }