Exemplo n.º 1
1
 /**
  * Generates a SQL sub-query for replacing in ORDER BY clause.
  *
  * @param string $column Name of the column being replaced by this sub-query
  * @param string|null $bundle Consider attributes only for a specific bundle
  * @return string SQL sub-query statement
  */
 protected function _subQuery($column, $bundle = null)
 {
     $alias = $this->_table->alias();
     $pk = $this->_table->primaryKey();
     $type = $this->_toolbox->getType($column);
     $subConditions = ['EavAttribute.table_alias' => $this->_table->table(), 'EavValues.entity_id' => "{$alias}.{$pk}", 'EavAttribute.name' => $column];
     if (!empty($bundle)) {
         $subConditions['EavAttribute.bundle'] = $bundle;
     }
     $subQuery = TableRegistry::get('Eav.EavValues')->find()->contain(['EavAttribute'])->select(["EavValues.value_{$type}"])->where($subConditions)->sql();
     return str_replace([':c0', ':c1', ':c2', ':c3'], ['"' . $this->_table->table() . '"', "{$alias}.{$pk}", '"' . $column . '"', '"' . $bundle . '"'], $subQuery);
 }
Exemplo n.º 2
0
 /**
  * Save virtual values after an entity's real values were saved.
  *
  * @param \Cake\Event\Event $event The event that was triggered
  * @param \Cake\Datasource\EntityInterface $entity The entity that was saved
  * @param \ArrayObject $options Additional options given as an array
  * @return bool True always
  */
 public function afterSave(Event $event, EntityInterface $entity, ArrayObject $options)
 {
     $attrsById = [];
     $updatedAttrs = [];
     $valuesTable = TableRegistry::get('Eav.EavValues');
     foreach ($this->_toolbox->attributes() as $name => $attr) {
         if (!$this->_toolbox->propertyExists($entity, $name)) {
             continue;
         }
         $attrsById[$attr->get('id')] = $attr;
     }
     if (empty($attrsById)) {
         return true;
         // nothing to do
     }
     $values = $valuesTable->find()->where(['eav_attribute_id IN' => array_keys($attrsById), 'entity_id' => $this->_toolbox->getEntityId($entity)]);
     foreach ($values as $value) {
         $updatedAttrs[] = $value->get('eav_attribute_id');
         $info = $attrsById[$value->get('eav_attribute_id')];
         $type = $this->_toolbox->getType($info->get('name'));
         $marshaledValue = $this->_toolbox->marshal($entity->get($info->get('name')), $type);
         $value->set("value_{$type}", $marshaledValue);
         $entity->set($info->get('name'), $marshaledValue);
         $valuesTable->save($value);
     }
     foreach ($this->_toolbox->attributes() as $name => $attr) {
         if (!$this->_toolbox->propertyExists($entity, $name)) {
             continue;
         }
         if (!in_array($attr->get('id'), $updatedAttrs)) {
             $type = $this->_toolbox->getType($name);
             $value = $valuesTable->newEntity(['eav_attribute_id' => $attr->get('id'), 'entity_id' => $this->_toolbox->getEntityId($entity)]);
             $marshaledValue = $this->_toolbox->marshal($entity->get($name), $type);
             $value->set("value_{$type}", $marshaledValue);
             $entity->set($name, $marshaledValue);
             $valuesTable->save($value);
         }
     }
     if ($this->config('cacheMap')) {
         $this->updateEavCache($entity);
     }
     return true;
 }
Exemplo n.º 3
0
 /**
  * Analyzes the given unary expression and alters it according.
  *
  * @param \Cake\Database\Expression\UnaryExpression $expression Unary expression
  * @param string $bundle Consider attributes only for a specific bundle
  * @param \Cake\ORM\Query $query The query instance this expression comes from
  * @return \Cake\Database\Expression\UnaryExpression Scoped expression (or not)
  */
 protected function _inspectUnaryExpression(UnaryExpression $expression, $bundle, Query $query)
 {
     $class = new \ReflectionClass($expression);
     $property = $class->getProperty('_value');
     $property->setAccessible(true);
     $value = $property->getValue($expression);
     if ($value instanceof IdentifierExpression) {
         $field = $value->getIdentifier();
         $column = is_string($field) ? $this->_toolbox->columnName($field) : '';
         if (empty($column) || in_array($column, (array) $this->_table->schema()->columns()) || !in_array($column, $this->_toolbox->getAttributeNames($bundle)) || !$this->_toolbox->isSearchable($column)) {
             // nothing to alter
             return $expression;
         }
         $pk = $this->_tablePrimaryKey();
         $driverClass = $this->_driverClass($query);
         switch ($driverClass) {
             case 'sqlite':
                 $concat = implode(' || ', $pk);
                 $field = "({$concat} || '')";
                 break;
             case 'mysql':
             case 'postgres':
             case 'sqlserver':
             default:
                 $concat = implode(', ', $pk);
                 $field = "CONCAT({$concat}, '')";
                 break;
         }
         $attr = $this->_toolbox->attributes($bundle)[$column];
         $type = $this->_toolbox->getType($column);
         $subQuery = TableRegistry::get('Eav.EavValues')->find()->select("EavValues.value_{$type}")->where(['EavValues.entity_id' => $field, 'EavValues.eav_attribute_id' => $attr['id']])->sql();
         $subQuery = str_replace([':c0', ':c1'], [$field, $attr['id']], $subQuery);
         $property->setValue($expression, "({$subQuery})");
     }
     return $expression;
 }