Example #1
0
 /**
  * Custom finder for map the ntofications.
  *
  * @param \Cake\ORM\Query $query The query finder.
  * @param array $options The options passed in the query builder.
  *
  * @return \Cake\ORM\Query
  */
 public function findMap(Query $query, array $options)
 {
     return $query->formatResults(function ($notifications) use($options) {
         return $notifications->map(function ($notification) use($options) {
             $notification->data = unserialize($notification->data);
             switch ($notification->type) {
                 case 'conversation.reply':
                     $username = $notification->data['sender']->username;
                     $conversationTitle = Text::truncate($notification->data['conversation']->title, 50, ['ellipsis' => '...', 'exact' => false]);
                     //Check if the creator of the conversation is the current user.
                     if ($notification->data['conversation']->user_id === $options['session']->read('Auth.User.id')) {
                         $notification->text = __('<strong>{0}</strong> has replied in your conversation <strong>{1}</strong>.', h($username), h($conversationTitle));
                     } else {
                         $notification->text = __('<strong>{0}</strong> has replied in the conversation <strong>{1}</strong>.', h($username), h($conversationTitle));
                     }
                     $notification->link = Router::url(['controller' => 'conversations', 'action' => 'go', $notification->data['conversation']->last_message_id, 'prefix' => false]);
                     break;
                 case 'bot':
                     $notification->text = __('Welcome on <strong>{0}</strong>! You can now post your first comment in the blog.', \Cake\Core\Configure::read('Site.name'));
                     $notification->link = Router::url(['controller' => 'blog', 'action' => 'index', 'prefix' => false]);
                     $notification->icon = $notification->data['icon'];
                     break;
                 case 'badge':
                     $notification->text = __('You have unlock the badge "{0}".', $notification->data['badge']->name);
                     $notification->link = Router::url(['_name' => 'users-profile', 'id' => $notification->data['user']->id, 'slug' => $notification->data['user']->username, '#' => 'badges', 'prefix' => false]);
                     break;
             }
             return $notification;
         });
     });
 }
 public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
 {
     if (!array_key_exists('getRelated', $options) || !$options['getRelated']) {
         //Jen pokud se mají related stahovat
         return true;
     }
     $attachedTables = $this->_InRelatedIndexBehavior->getTablesWithBehaviorNames();
     /** @var \Cake\ORM\Table $attachedTable */
     foreach ($attachedTables as $tableName) {
         $modelName = Inflector::camelize($tableName);
         $query->contain(['Related' . $modelName => []]);
     }
     $query->formatResults(function ($results) {
         return $results->map(function ($row) {
             $temp = $row->toArray();
             $related = [];
             foreach ($temp as $key => $item) {
                 if (preg_match('/related-.*/', $key)) {
                     foreach ($row->{$key} as $id => $similar) {
                         $table_name = explode('-', $key);
                         $row->{$key}[$id]->table_name = end($table_name);
                     }
                     $related = array_merge($related, $row->{$key});
                     unset($row->{$key});
                 }
             }
             $row->related = $related;
             return $row;
         });
     });
     return true;
 }
 /**
  * Decode the fields on after find
  *
  * @param \Cake\Event\Event $event
  * @param \Cake\ORM\Query $query
  * @return void
  */
 public function beforeFind(Event $event, Query $query)
 {
     $query->formatResults(function (ResultSetInterface $results) {
         return $results->map(function ($row) {
             $this->processItems($row, 'output');
             return $row;
         });
     });
 }
Example #4
0
 /**
  * beforeFind, starts a timer for a find operation.
  *
  * @param \Cake\Event\Event $event The beforeFind event
  * @param \Cake\ORM\Query $query Query
  * @return bool true
  */
 public function beforeFind(Event $event, $query)
 {
     $alias = $event->subject()->alias();
     DebugTimer::start($alias . '_find', $alias . '->find()');
     return $query->formatResults(function ($results) use($alias) {
         DebugTimer::stop($alias . '_find');
         return $results;
     });
 }
 public function beforeFind(Event $event, Query $query)
 {
     $query->formatResults(function ($results) {
         return $results->map(function ($row) {
             if (!$row instanceof Entity) {
                 return $row;
             }
             $this->transformState($row);
             return $row;
         });
     });
 }
Example #6
0
 public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
 {
     if (!$query->hydrate()) {
         return;
     }
     $query->formatResults(function ($results) {
         return $results->map(function ($row) {
             $type = $row[$this->config('typeField')];
             $entityClass = $this->_typeMap[$type]['entityClass'];
             return new $entityClass($row->forCopy(), ['markNew' => $row->isNew(), 'markClean' => true, 'guard' => false, 'source' => $this->_typeMap[$type]['alias']]);
         });
     });
 }
Example #7
0
 /**
  * Locks all the rows returned by the query.
  * This finder requires the `lockingUser` key in options and optionally the
  * `lockingSession`.
  *
  * @param Query $quert The Query to modify
  * @param array|ArrayObject $options The options containing the `lockingUser` key
  * @return Query
  */
 public function findAutoLock(Query $query, $options)
 {
     $by = Hash::get($options, 'lockingUser');
     $session = Hash::get($options, 'lockingSession');
     return $query->formatResults(function ($results) use($by, $session) {
         $results->filter(function ($r) {
             return $r instanceof LockableInterface;
         })->each(function ($r) use($by, $session) {
             $r->lock($by, $session);
             $this->_table->save($r);
         });
         return $results;
     });
 }
 /**
  * Attaches ContentType information to each content revision.
  *
  * @param \Cake\Event\Event $event The event that was triggered
  * @param \Cake\ORM\Query $query The query object
  * @param \ArrayObject $options Additional options given as an array
  * @param bool $primary Whether this find is a primary query or not
  * @return Query
  */
 public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
 {
     $query->formatResults(function ($results) {
         return $results->map(function ($revision) {
             try {
                 if (isset($revision->data->content_type_id)) {
                     $contentType = TableRegistry::get('Content.ContentTypes')->find()->where(['id' => $revision->data->content_type_id])->first();
                     $revision->data->set('content_type', $contentType);
                 }
             } catch (\Exception $e) {
                 $revision->data->set('content_type', false);
             }
             return $revision;
         });
     });
     return $query;
 }
 /**
  * Attaches comments to each entity on find operation.
  *
  * @param \Cake\Event\Event $event The event that was triggered
  * @param \Cake\ORM\Query $query The query object
  * @param array $options Additional options as an array
  * @param bool $primary Whether is find is a primary query or not
  * @return void
  */
 public function beforeFind(Event $event, $query, $options, $primary)
 {
     if ($this->_enabled && $query->count() > 0) {
         $pk = $this->_table->primaryKey();
         $tableAlias = Inflector::underscore($this->_table->alias());
         $query->contain(['Comments' => function ($query) {
             return $query->find('threaded')->contain(['Users'])->order($this->config('order'));
         }]);
         if ($this->config('count') || isset($options['comments_count']) && $options['comments_count'] === true) {
             $query->formatResults(function ($results) use($pk, $tableAlias) {
                 return $results->map(function ($entity) use($pk, $tableAlias) {
                     $entityId = $entity->{$pk};
                     $count = TableRegistry::get('Comment.Comments')->find()->where(['entity_id' => $entityId, 'table_alias' => $tableAlias])->count();
                     $entity->set('comments_count', $count);
                     return $entity;
                 });
             });
         }
     }
 }
Example #10
0
 /**
  * Custom finder to retrieve decrypted values.
  *
  * @param \Cake\ORM\Query $query Query.
  * @param array $options Options.
  * @return \Cake\ORM\Query
  */
 public function findDecrypted(Query $query, array $options)
 {
     $options += ['fields' => []];
     $mapper = function ($row) use($options) {
         $driver = $this->_table->connection()->driver();
         foreach ($this->config('fields') as $field => $type) {
             if ($options['fields'] && !in_array($field, (array) $options['fields']) || !$row->has($field)) {
                 continue;
             }
             $cipher = $row->get($field);
             $plain = $this->decrypt($cipher);
             $row->set($field, Type::build($type)->toPHP($plain, $driver));
         }
         return $row;
     };
     $formatter = function ($results) use($mapper) {
         return $results->map($mapper);
     };
     return $query->formatResults($formatter);
 }
 /**
  * Decrypt values after retrieving from DB
  * @param Event $event Event object
  * @param Query $query Query object
  * @param ArrayObject $options Query options array
  * @param type $primary Root/associated query
  * @return void
  */
 public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
 {
     $fields = $this->config('fields');
     $driver = $this->_table->connection()->driver();
     $formatter = function (\Cake\Collection\CollectionInterface $results) use($fields, $driver) {
         return $results->each(function ($entity) use($fields, $driver) {
             if ($entity instanceof \Cake\Datasource\EntityInterface) {
                 foreach ($fields as $field => $type) {
                     if ($entity->has($field)) {
                         $value = $entity->get($field);
                         $decryptedValue = $this->decrypt($value);
                         // Convert DB values to PHP values after decrypting them
                         $entity->set($field, Type::build($type)->toPHP($decryptedValue, $driver));
                         $entity->clean();
                     }
                 }
             }
         });
     };
     $query->formatResults($formatter);
 }
Example #12
0
 /**
  * Adds a formatter function to the passed `$query` if the `$surrogate` query
  * declares any other formatter. Since the `$surrogate` query correspond to
  * the associated target table, the resulting formatter will be the result of
  * applying the surrogate formatters to only the property corresponding to
  * such table.
  *
  * @param \Cake\ORM\Query $query the query that will get the formatter applied to
  * @param \Cake\ORM\Query $surrogate the query having formatters for the associated
  * target table.
  * @param array $options options passed to the method `attachTo`
  * @return void
  */
 protected function _formatAssociationResults($query, $surrogate, $options)
 {
     $formatters = $surrogate->formatResults();
     if (!$formatters || empty($options['propertyPath'])) {
         return;
     }
     $property = $options['propertyPath'];
     $query->formatResults(function ($results) use($formatters, $property) {
         $extracted = $results->extract($property)->compile();
         foreach ($formatters as $callable) {
             $extracted = new ResultSetDecorator($callable($extracted));
         }
         return $results->insert($property, $extracted);
     }, Query::PREPEND);
 }
Example #13
0
 /**
  * Adds a formatter function to the passed `$query` if the `$surrogate` query
  * declares any other formatter. Since the `$surrogate` query correspond to
  * the associated target table, the resulting formatter will be the result of
  * applying the surrogate formatters to only the property corresponding to
  * such table.
  *
  * @param \Cake\ORM\Query $query the query that will get the formatter applied to
  * @param \Cake\ORM\Query $surrogate the query having formatters for the associated
  * target table.
  * @param array $options options passed to the method `attachTo`
  * @return void
  */
 protected function _formatAssociationResults($query, $surrogate, $options)
 {
     $formatters = $surrogate->formatResults();
     if (!$formatters || empty($options['propertyPath'])) {
         return;
     }
     $property = $options['propertyPath'];
     $propertyPath = explode('.', $property);
     $query->formatResults(function ($results) use($formatters, $property, $propertyPath) {
         $extracted = [];
         foreach ($results as $result) {
             foreach ($propertyPath as $propertyPathItem) {
                 if (!isset($result[$propertyPathItem])) {
                     $result = null;
                     break;
                 }
                 $result = $result[$propertyPathItem];
             }
             $extracted[] = $result;
         }
         $extracted = new Collection($extracted);
         foreach ($formatters as $callable) {
             $extracted = new ResultSetDecorator($callable($extracted));
         }
         return $results->insert($property, $extracted);
     }, Query::PREPEND);
 }
 /**
  * Custom finder for hashids field.
  *
  * Options:
  * - hid (required), best to use HashidBehavior::HID constant
  * - noFirst (optional, to leave the query open for adjustments, no first() called)
  *
  * @param \Cake\ORM\Query $query Query.
  * @param array $options Array of options as described above
  * @return \Cake\ORM\Query
  */
 public function findHashed(Query $query, array $options)
 {
     $field = $this->_config['field'];
     if (!$field) {
         return $query;
     }
     $idField = $this->_primaryKey;
     $query->formatResults(function ($results) use($field, $idField) {
         $newResult = [];
         $results->each(function ($row, $key) use($field, $idField, &$newResult) {
             if (!empty($row[$idField])) {
                 $row[$field] = $this->encodeId($row[$idField]);
                 if ($row instanceof Entity) {
                     $row->dirty($field, false);
                 }
                 $newResult[] = $row;
             } elseif (is_string($row)) {
                 $newResult[$this->encodeId($key)] = $row;
             }
         });
         return new Collection($newResult);
     });
     if (!empty($options[static::HID])) {
         $id = $this->decodeHashid($options[static::HID]);
         $query->where([$idField => $id]);
     }
     $first = $this->_config['findFirst'] === true ? 'first' : $this->_config['findFirst'];
     if (!$first || !empty($options['noFirst'])) {
         return $query;
     }
     return $query->first();
 }
Example #15
0
 /**
  * Results for this finder will be a nested array, and is appropriate if you want
  * to use the parent_id field of your model data to build nested results.
  *
  * Values belonging to a parent row based on their parent_id value will be
  * recursively nested inside the parent row values using the `children` property
  *
  * You can customize what fields are used for nesting results, by default the
  * primary key and the `parent_id` fields are used. If you you wish to change
  * these defaults you need to provide the keys `idField` or `parentField` in
  * `$options`:
  *
  * {{{
  * $table->find('threaded', [
  *	'idField' => 'id',
  *	'parentField' => 'ancestor_id'
  * ]);
  * }}}
  *
  * @param \Cake\ORM\Query $query
  * @param array $options
  * @return \Cake\ORM\Query
  */
 public function findThreaded(Query $query, array $options)
 {
     $options += ['idField' => $this->primaryKey(), 'parentField' => 'parent_id'];
     $options = $this->_setFieldMatchers($options, ['idField', 'parentField']);
     return $query->formatResults(function ($results) use($options) {
         return $results->nest($options['idField'], $options['parentField']);
     });
 }
 /**
  * Formats entities to set hidden fields
  *
  * @param Event $event
  * @param Query $query
  * @return Query
  */
 public function beforeFind(Event $event, Query $query)
 {
     if (!$this->_buildAuthorization()) {
         return $query;
     }
     /**
      * Apply field visibility and accessibility
      */
     $notVisible = $this->_getNotVisibleFields();
     $query->formatResults(function ($results) use($notVisible) {
         return $results->map(function ($row) use($notVisible) {
             if (isset($row) && $row instanceof Entity) {
                 $row->hiddenProperties(array_merge($row->hiddenProperties(), $notVisible));
             }
             return $row;
         });
     });
     /**
      * Apply finders
      */
     $finders = array_diff($this->_getFinders(), $this->_getUnauthorizedFinders());
     foreach ($finders as $finder) {
         $query->find($finder);
     }
     return $query;
 }
Example #17
0
 /**
  * Results for this finder will be a nested array, and is appropriate if you want
  * to use the parent_id field of your model data to build nested results.
  *
  * Values belonging to a parent row based on their parent_id value will be
  * recursively nested inside the parent row values using the `children` property
  *
  * You can customize what fields are used for nesting results, by default the
  * primary key and the `parent_id` fields are used. If you wish to change
  * these defaults you need to provide the keys `keyField` or `parentField` in
  * `$options`:
  *
  * ```
  * $table->find('threaded', [
  *  'keyField' => 'id',
  *  'parentField' => 'ancestor_id'
  * ]);
  * ```
  *
  * @param \Cake\ORM\Query $query The query to find with
  * @param array $options The options to find with
  * @return \Cake\ORM\Query The query builder
  */
 public function findThreaded(Query $query, array $options)
 {
     $options += ['keyField' => $this->primaryKey(), 'parentField' => 'parent_id'];
     if (isset($options['idField'])) {
         $options['keyField'] = $options['idField'];
         unset($options['idField']);
         trigger_error('Option "idField" is deprecated, use "keyField" instead.', E_USER_WARNING);
     }
     $options = $this->_setFieldMatchers($options, ['keyField', 'parentField']);
     return $query->formatResults(function ($results) use($options) {
         return $results->nest($options['keyField'], $options['parentField']);
     });
 }
 /**
  * Here we set default values for serializable columns.
  *
  * This method triggers the `<TableAlias>.<columnName>.defaultValues` event, for
  * example "Plugins.settings.defaultValues" for the "settings" columns of the
  * "Plugins" table. Event listeners should catch this event and provides the
  * desired values.
  *
  * ### Options:
  *
  * - flatten: Flattens serialized information into plain entity properties, for
  *   example `settings:some_option` => `value`, where `settings` is the
  *   serialized column and `some_option` a key of the serialized array value.
  *   Valid only for column that stores array values. Example:
  *
  *   Consider the following entity:
  *
  *   ```php
  *   object(Cake\Datasource\EntityInterface) {
  *       'settings' => [
  *           'option_1' => 'Lorem ipsum',
  *           'option_2' => [1, 2, 3, 4],
  *           'option_3' => object,
  *       ],
  *   }
  *   ```
  *
  *   Once `settings` column is flattened the entity will look as follow:
  *
  *   ```php
  *   object(Cake\Datasource\EntityInterface) {
  *       'settings' => [
  *           'option_1' => 'Lorem ipsum',
  *           'option_2' => [1, 2, 3, 4],
  *           'option_3' => object,
  *       ],
  *       'settings:option_1' => 'Lorem ipsum',
  *       'settings:option_2' => [1, 2, 3, 4],
  *       'settings:option_3' => object,
  *   }
  *   ```
  *
  * @param \Cake\Event\Event $event The event that was triggered
  * @param \Cake\ORM\Query $query Query object
  * @param \ArrayObject $options Additional options as an array
  * @param bool $primary Whether is find is a primary query or not
  * @return void
  */
 public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
 {
     $query->formatResults(function ($results) use($options) {
         return $results->map(function ($entity) use($options) {
             if (!$entity instanceof EntityInterface) {
                 return $entity;
             }
             foreach ($this->config('columns') as $column) {
                 if ($entity->has($column)) {
                     $eventName = $this->_table->alias() . ".{$column}.defaultValues";
                     $defaultValue = $this->_table->dispatchEvent($eventName, compact('entity'))->result;
                     $currentValue = $entity->get($column);
                     $newValue = $currentValue;
                     if (is_array($currentValue) && is_array($defaultValue)) {
                         $newValue = Hash::merge($defaultValue, $currentValue);
                     } elseif (is_string($currentValue) && $currentValue === '') {
                         $newValue = $defaultValue;
                     } elseif (empty($currentValue) && !empty($defaultValue)) {
                         $newValue = $defaultValue;
                     }
                     $entity->set($column, $newValue);
                     if (!empty($options['flatten']) && is_array($entity->get($column))) {
                         foreach ($entity->get($column) as $key => $value) {
                             $entity->set("{$column}:{$key}", $value);
                         }
                     }
                 }
             }
             return $entity;
         });
     });
 }
Example #19
0
 /**
  * Custom finder that obfuscates primary keys in returned result set.
  *
  * @param \Cake\ORM\Query $query Query.
  * @param array $options Options.
  * @return \Cake\ORM\Query
  */
 public function findObfuscate(Query $query, array $options)
 {
     $query->applyOptions(['obfuscate' => true]);
     $query->formatResults(function ($results) {
         return $results->map(function ($row) {
             $pk = $this->_table->primaryKey();
             $row[$pk] = $this->obfuscate($row[$pk]);
             return $row;
         });
     });
     return $query;
 }
Example #20
0
 /**
  * Callback method that listens to the `beforeFind` event in the bound
  * table. It modifies the passed query by eager loading the translated fields
  * and adding a formatter to copy the values into the main table records.
  *
  * @param \Cake\Event\Event $event The beforeFind event that was fired.
  * @param \Cake\ORM\Query $query Query
  * @return void
  */
 public function beforeFind(Event $event, Query $query)
 {
     $locale = $this->locale();
     if ($locale === $this->config('defaultLocale')) {
         return;
     }
     $conditions = function ($q) use($locale) {
         return $q->select(['id', 'content'])->where([$q->repository()->alias() . '.locale' => $locale]);
     };
     $contain = [];
     $fields = $this->_config['fields'];
     $alias = $this->_table->alias();
     foreach ($fields as $field) {
         $contain[$alias . '_' . $field . '_translation'] = $conditions;
     }
     $query->contain($contain);
     $query->formatResults(function ($results) use($locale) {
         return $this->_rowMapper($results, $locale);
     }, $query::PREPEND);
 }
Example #21
0
 /**
  * Test fetching results from a qurey with a two custom formatters
  *
  * @return void
  */
 public function testQueryWithStackedFormatters()
 {
     $table = TableRegistry::get('authors');
     $query = new Query($this->connection, $table);
     $query->select()->formatResults(function ($results) {
         $this->assertInstanceOf('Cake\\ORM\\ResultSet', $results);
         return $results->indexBy('id');
     });
     $query->formatResults(function ($results) {
         return $results->extract('name');
     });
     $expected = [1 => 'mariano', 2 => 'nate', 3 => 'larry', 4 => 'garrett'];
     $this->assertEquals($expected, $query->toArray());
 }
 /**
  * Here we set default values for each view mode if they were not defined before.
  *
  * @param \Cake\Event\Event $event The event that was triggered
  * @param \Cake\ORM\Query $query The query object
  * @param \ArrayObject $options Additional options given as an array
  * @param bool $primary Whether this find is a primary query or not
  * @return void
  */
 public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
 {
     $viewModes = $this->viewModes();
     $query->formatResults(function ($results) use($viewModes) {
         return $results->map(function ($instance) use($viewModes) {
             if (!is_object($instance)) {
                 return $instance;
             }
             foreach ($viewModes as $viewMode) {
                 $instanceViewModes = $instance->view_modes;
                 $viewModeDefaults = array_merge(['label_visibility' => 'above', 'shortcodes' => false, 'hidden' => false, 'ordering' => 0], (array) $instance->defaultViewModeSettings($viewMode));
                 if (!isset($instanceViewModes[$viewMode])) {
                     $instanceViewModes[$viewMode] = [];
                 }
                 $instanceViewModes[$viewMode] = array_merge($viewModeDefaults, $instanceViewModes[$viewMode]);
                 $instance->set('view_modes', $instanceViewModes);
             }
             $settingsDefaults = (array) $instance->defaultSettings();
             if (!empty($settingsDefaults)) {
                 $instanceSettings = $instance->get('settings');
                 foreach ($settingsDefaults as $k => $v) {
                     if (!isset($instanceSettings[$k])) {
                         $instanceSettings[$k] = $v;
                     }
                 }
                 $instance->set('settings', $instanceSettings);
             }
             return $instance;
         });
     });
 }
Example #23
0
 /**
  * Formats query as a flat list where the keys are the primary key for the table
  * and the values are the display field for the table. Values are prefixed to visually
  * indicate relative depth in the tree.
  *
  * ### Options
  *
  * - keyPath: A dot separated path to the field that will be the result array key, or a closure to
  *   return the key from the provided row.
  * - valuePath: A dot separated path to the field that is the array's value, or a closure to
  *   return the value from the provided row.
  * - spacer: A string to be used as prefix for denoting the depth in the tree for each item.
  *
  * @param \Cake\ORM\Query $query The query object to format.
  * @param array $options Array of options as described above.
  * @return \Cake\ORM\Query Augmented query.
  */
 public function formatTreeList(Query $query, array $options = [])
 {
     return $query->formatResults(function ($results) use($options) {
         $options += ['keyPath' => $this->_getPrimaryKey(), 'valuePath' => $this->_table->displayField(), 'spacer' => '_'];
         return $results->listNested()->printer($options['valuePath'], $options['keyPath'], $options['spacer']);
     });
 }
 public function findOfficialLanguageList(Query $query)
 {
     $query->formatResults(function ($results) {
         return $results->combine('name', 'official_language.language');
     });
     return $query->find('withOfficialLanguage');
 }