/**
  * Manipulates the SQL query
  *
  * @param SQLQuery &$query Query to manipulate
  * 
  * @return void
  *
  * @author Sebastian Diel <*****@*****.**>
  * @since 04.05.2012
  */
 public function augmentSQL(SQLQuery &$query)
 {
     if (!$query->isJoinedTo($this->getLanguageClassName()) && !$query->getDelete()) {
         $silvercartDefaultLocale = SilvercartConfig::Locale();
         $query->addLeftJoin($this->getLanguageClassName(), sprintf("(\"%s\".\"ID\" = \"%s\".\"%s\")", $this->getBaseClassName(), $this->getLanguageClassName(), $this->getRelationFieldName()));
         $addToWhere = '';
         if ($this->getBaseLanguageClassName() != $this->getLanguageClassName()) {
             $query->addLeftJoin($this->getBaseLanguageClassName(), sprintf("(\"%s\".\"ID\" = \"%s\".\"ID\")", $this->getLanguageClassName(), $this->getBaseLanguageClassName()));
             $addToWhere = sprintf("AND \"%s\".\"ID\" = \"%s\".\"ID\"", $this->getBaseLanguageClassName(), $this->getLanguageClassName());
         }
         if (SilvercartConfig::useDefaultLanguageAsFallback() && Translatable::get_current_locale() != $silvercartDefaultLocale && !empty($silvercartDefaultLocale)) {
             $query->addWhere(sprintf("\"%s\".\"Locale\" = IFNULL((%s), (%s)) %s", $this->getBaseLanguageClassName(), $this->getLocaleDependantSelect(Translatable::get_current_locale()), $this->getLocaleDependantSelect($silvercartDefaultLocale), $addToWhere));
         } elseif (!empty($silvercartDefaultLocale)) {
             $query->addWhere(sprintf("\"%s\".\"Locale\" = '%s' %s", $this->getBaseLanguageClassName(), Translatable::get_current_locale(), $addToWhere));
         }
     }
 }
예제 #2
0
 /**
  * Traverse the relationship fields, and add the table
  * mappings to the query object state. This has to be called
  * in any overloaded {@link SearchFilter->apply()} methods manually.
  * 
  * @param String|array $relation The array/dot-syntax relation to follow
  * @return The model class of the related item
  */
 public function applyRelation($relation)
 {
     // NO-OP
     if (!$relation) {
         return $this->dataClass;
     }
     if (is_string($relation)) {
         $relation = explode(".", $relation);
     }
     $modelClass = $this->dataClass;
     foreach ($relation as $rel) {
         $model = singleton($modelClass);
         if ($component = $model->has_one($rel)) {
             if (!$this->query->isJoinedTo($component)) {
                 $foreignKey = $rel;
                 $realModelClass = ClassInfo::table_for_object_field($modelClass, "{$foreignKey}ID");
                 $this->query->addLeftJoin($component, "\"{$component}\".\"ID\" = \"{$realModelClass}\".\"{$foreignKey}ID\"");
                 /**
                  * add join clause to the component's ancestry classes so that the search filter could search on
                  * its ancestor fields.
                  */
                 $ancestry = ClassInfo::ancestry($component, true);
                 if (!empty($ancestry)) {
                     $ancestry = array_reverse($ancestry);
                     foreach ($ancestry as $ancestor) {
                         if ($ancestor != $component) {
                             $this->query->addInnerJoin($ancestor, "\"{$component}\".\"ID\" = \"{$ancestor}\".\"ID\"");
                         }
                     }
                 }
             }
             $modelClass = $component;
         } elseif ($component = $model->has_many($rel)) {
             if (!$this->query->isJoinedTo($component)) {
                 $ancestry = $model->getClassAncestry();
                 $foreignKey = $model->getRemoteJoinField($rel);
                 $this->query->addLeftJoin($component, "\"{$component}\".\"{$foreignKey}\" = \"{$ancestry[0]}\".\"ID\"");
                 /**
                  * add join clause to the component's ancestry classes so that the search filter could search on
                  * its ancestor fields.
                  */
                 $ancestry = ClassInfo::ancestry($component, true);
                 if (!empty($ancestry)) {
                     $ancestry = array_reverse($ancestry);
                     foreach ($ancestry as $ancestor) {
                         if ($ancestor != $component) {
                             $this->query->addInnerJoin($ancestor, "\"{$component}\".\"ID\" = \"{$ancestor}\".\"ID\"");
                         }
                     }
                 }
             }
             $modelClass = $component;
         } elseif ($component = $model->many_many($rel)) {
             list($parentClass, $componentClass, $parentField, $componentField, $relationTable) = $component;
             $parentBaseClass = ClassInfo::baseDataClass($parentClass);
             $componentBaseClass = ClassInfo::baseDataClass($componentClass);
             $this->query->addInnerJoin($relationTable, "\"{$relationTable}\".\"{$parentField}\" = \"{$parentBaseClass}\".\"ID\"");
             $this->query->addLeftJoin($componentBaseClass, "\"{$relationTable}\".\"{$componentField}\" = \"{$componentBaseClass}\".\"ID\"");
             if (ClassInfo::hasTable($componentClass)) {
                 $this->query->addLeftJoin($componentClass, "\"{$relationTable}\".\"{$componentField}\" = \"{$componentClass}\".\"ID\"");
             }
             $modelClass = $componentClass;
         }
     }
     return $modelClass;
 }
예제 #3
0
 /**
  * Traverse the relationship fields, and add the table
  * mappings to the query object state.
  * 
  * @todo try to make this implicitly triggered so it doesn't have to be manually called in child filters
  * @param SQLQuery $query
  * @return SQLQuery
  */
 function applyRelation($query)
 {
     if (is_array($this->relation)) {
         foreach ($this->relation as $rel) {
             $model = singleton($this->model);
             if ($component = $model->has_one($rel)) {
                 if (!$query->isJoinedTo($component)) {
                     $foreignKey = $model->getReverseAssociation($component);
                     $query->leftJoin($component, "`{$component}`.`ID` = `{$this->model}`.`{$foreignKey}ID`");
                 }
                 $this->model = $component;
             } elseif ($component = $model->has_many($rel)) {
                 if (!$query->isJoinedTo($component)) {
                     $ancestry = $model->getClassAncestry();
                     $foreignKey = $model->getComponentJoinField($rel);
                     $query->leftJoin($component, "`{$component}`.`{$foreignKey}` = `{$ancestry[0]}`.`ID`");
                 }
                 $this->model = $component;
             } elseif ($component = $model->many_many($rel)) {
                 list($parentClass, $componentClass, $parentField, $componentField, $relationTable) = $component;
                 $parentBaseClass = ClassInfo::baseDataClass($parentClass);
                 $componentBaseClass = ClassInfo::baseDataClass($componentClass);
                 $query->innerJoin($relationTable, "`{$relationTable}`.`{$parentField}` = `{$parentBaseClass}`.`ID`");
                 $query->leftJoin($componentClass, "`{$relationTable}`.`{$componentField}` = `{$componentClass}`.`ID`");
                 $this->model = $componentClass;
                 // Experimental support for user-defined relationships via a "(relName)Query" method
                 // This will likely be dropped in 2.4 for a system that makes use of Lazy Data Lists.
             } elseif ($model->hasMethod($rel . 'Query')) {
                 // Get the query representing the join - it should have "$ID" in the filter
                 $newQuery = $model->{"{$rel}Query"}();
                 if ($newQuery) {
                     // Get the table to join to
                     $newModel = str_replace('`', '', array_shift($newQuery->from));
                     // Get the filter to use on the join
                     $ancestry = $model->getClassAncestry();
                     $newFilter = "(" . str_replace('$ID', "`{$ancestry[0]}`.`ID`", implode(") AND (", $newQuery->where)) . ")";
                     $query->leftJoin($newModel, $newFilter);
                     $this->model = $newModel;
                 } else {
                     $this->name = "NULL";
                     return;
                 }
             }
         }
     }
     return $query;
 }
 /**
  * Traverse the relationship fields, and add the table
  * mappings to the query object state. This has to be called
  * in any overloaded {@link SearchFilter->apply()} methods manually.
  * 
  * @todo try to make this implicitly triggered so it doesn't have to be manually called in child filters
  * @param SQLQuery $query
  * @return SQLQuery
  */
 function applyRelation($query)
 {
     if (is_array($this->relation)) {
         foreach ($this->relation as $rel) {
             $model = singleton($this->model);
             if ($component = $model->has_one($rel)) {
                 if (!$query->isJoinedTo($component)) {
                     $foreignKey = $model->getReverseAssociation($component);
                     $query->leftJoin($component, "\"{$component}\".\"ID\" = \"{$this->model}\".\"{$foreignKey}ID\"");
                     /**
                      * add join clause to the component's ancestry classes so that the search filter could search on its 
                      * ancester fields.
                      */
                     $ancestry = ClassInfo::ancestry($component, true);
                     if (!empty($ancestry)) {
                         $ancestry = array_reverse($ancestry);
                         foreach ($ancestry as $ancestor) {
                             if ($ancestor != $component) {
                                 $query->innerJoin($ancestor, "\"{$component}\".\"ID\" = \"{$ancestor}\".\"ID\"");
                                 $component = $ancestor;
                             }
                         }
                     }
                 }
                 $this->model = $component;
             } elseif ($component = $model->has_many($rel)) {
                 if (!$query->isJoinedTo($component)) {
                     $ancestry = $model->getClassAncestry();
                     $foreignKey = $model->getRemoteJoinField($rel);
                     $query->leftJoin($component, "\"{$component}\".\"{$foreignKey}\" = \"{$ancestry[0]}\".\"ID\"");
                     /**
                      * add join clause to the component's ancestry classes so that the search filter could search on its 
                      * ancestor fields.
                      */
                     $ancestry = ClassInfo::ancestry($component, true);
                     if (!empty($ancestry)) {
                         $ancestry = array_reverse($ancestry);
                         foreach ($ancestry as $ancestor) {
                             if ($ancestor != $component) {
                                 $query->innerJoin($ancestor, "\"{$component}\".\"ID\" = \"{$ancestor}\".\"ID\"");
                                 $component = $ancestor;
                             }
                         }
                     }
                 }
                 $this->model = $component;
             } elseif ($component = $model->many_many($rel)) {
                 list($parentClass, $componentClass, $parentField, $componentField, $relationTable) = $component;
                 $parentBaseClass = ClassInfo::baseDataClass($parentClass);
                 $componentBaseClass = ClassInfo::baseDataClass($componentClass);
                 $query->innerJoin($relationTable, "\"{$relationTable}\".\"{$parentField}\" = \"{$parentBaseClass}\".\"ID\"");
                 $query->leftJoin($componentBaseClass, "\"{$relationTable}\".\"{$componentField}\" = \"{$componentBaseClass}\".\"ID\"");
                 if (ClassInfo::hasTable($componentClass)) {
                     $query->leftJoin($componentClass, "\"{$relationTable}\".\"{$componentField}\" = \"{$componentClass}\".\"ID\"");
                 }
                 $this->model = $componentClass;
                 // Experimental support for user-defined relationships via a "(relName)Query" method
                 // This will likely be dropped in 2.4 for a system that makes use of Lazy Data Lists.
             } elseif ($model->hasMethod($rel . 'Query')) {
                 // Get the query representing the join - it should have "$ID" in the filter
                 $newQuery = $model->{"{$rel}Query"}();
                 if ($newQuery) {
                     // Get the table to join to
                     //DATABASE ABSTRACTION: I don't think we need this line anymore:
                     $newModel = str_replace('`', '', array_shift($newQuery->from));
                     // Get the filter to use on the join
                     $ancestry = $model->getClassAncestry();
                     $newFilter = "(" . str_replace('$ID', "\"{$ancestry[0]}\".\"ID\"", implode(") AND (", $newQuery->where)) . ")";
                     $query->leftJoin($newModel, $newFilter);
                     $this->model = $newModel;
                 } else {
                     $this->name = "NULL";
                     return;
                 }
             }
         }
     }
     return $query;
 }