protected function purgeUnconfirmedRegistrations()
 {
     $query = new SQLQuery();
     $conn = DB::getConn();
     $query->select('"EventRegistration"."ID"');
     $query->from('"EventRegistration"');
     $query->innerJoin('CalendarDateTime', '"TimeID" = "DateTime"."ID"', 'DateTime');
     $query->innerJoin('CalendarEvent', '"DateTime"."EventID" = "Event"."ID"', 'Event');
     $query->innerJoin('RegisterableEvent', '"Event"."ID" = "Registerable"."ID"', 'Registerable');
     $query->where('"Registerable"."ConfirmTimeLimit" > 0');
     $query->where('"Status"', 'Unconfirmed');
     $created = $conn->formattedDatetimeClause('"EventRegistration"."Created"', '%U');
     $query->where(sprintf('%s < %s', $created . ' + "Registerable"."ConfirmTimeLimit"', time()));
     if ($ids = $query->execute()->column()) {
         $count = count($ids);
         DB::query(sprintf('UPDATE "EventRegistration" SET "Status" = \'Canceled\' WHERE "ID" IN (%s)', implode(', ', $ids)));
     } else {
         $count = 0;
     }
     echo "{$count} unconfirmed registrations were canceled.\n";
 }
예제 #2
0
 /**
  * Augment the the SQLQuery that is created by the DataQuery
  * @todo Should this all go into VersionedDataQuery?
  */
 function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery)
 {
     $baseTable = ClassInfo::baseDataClass($dataQuery->dataClass());
     switch ($dataQuery->getQueryParam('Versioned.mode')) {
         // Noop
         case '':
             break;
             // Reading a specific data from the archive
         // Reading a specific data from the archive
         case 'archive':
             $date = $dataQuery->getQueryParam('Versioned.date');
             foreach ($query->from as $table => $dummy) {
                 $query->renameTable($table, $table . '_versions');
                 $query->replaceText("\"{$table}\".\"ID\"", "\"{$table}\".\"RecordID\"");
                 // Add all <basetable>_versions columns
                 foreach (self::$db_for_versions_table as $name => $type) {
                     $query->select[] = sprintf('"%s_versions"."%s"', $baseTable, $name);
                 }
                 $query->select[] = sprintf('"%s_versions"."%s" AS "ID"', $baseTable, 'RecordID');
                 if ($table != $baseTable) {
                     $query->from[$table] .= " AND \"{$table}_versions\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
                 }
             }
             // Link to the version archived on that date
             $archiveTable = $this->requireArchiveTempTable($baseTable, $date);
             $query->from[$archiveTable] = "INNER JOIN \"{$archiveTable}\"\n\t\t\t\tON \"{$archiveTable}\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\" \n\t\t\t\tAND \"{$archiveTable}\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
             break;
             // Reading a specific stage (Stage or Live)
         // Reading a specific stage (Stage or Live)
         case 'stage':
             $stage = $dataQuery->getQueryParam('Versioned.stage');
             if ($stage && $stage != $this->defaultStage) {
                 foreach ($query->from as $table => $dummy) {
                     // Only rewrite table names that are actually part of the subclass tree
                     // This helps prevent rewriting of other tables that get joined in, in
                     // particular, many_many tables
                     if (class_exists($table) && ($table == $this->owner->class || is_subclass_of($table, $this->owner->class) || is_subclass_of($this->owner->class, $table))) {
                         $query->renameTable($table, $table . '_' . $stage);
                     }
                 }
             }
             break;
             // Return all version instances
         // Return all version instances
         case 'all_versions':
         case 'latest_versions':
             foreach ($query->from as $alias => $join) {
                 if ($alias != $baseTable) {
                     $query->setJoinFilter($alias, "\"{$alias}\".\"RecordID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"{$alias}\".\"Version\" = \"{$baseTable}_versions\".\"Version\"");
                 }
                 $query->renameTable($alias, $alias . '_versions');
             }
             // Add all <basetable>_versions columns
             foreach (self::$db_for_versions_table as $name => $type) {
                 $query->selectMore(sprintf('"%s_versions"."%s"', $baseTable, $name));
             }
             $query->selectMore(sprintf('"%s_versions"."%s" AS "ID"', $baseTable, 'RecordID'));
             // latest_version has one more step
             // Return latest version instances, regardless of whether they are on a particular stage
             // This provides "show all, including deleted" functonality
             if ($dataQuery->getQueryParam('Versioned.mode') == 'latest_versions') {
                 $archiveTable = self::requireArchiveTempTable($baseTable);
                 $query->innerJoin($archiveTable, "\"{$archiveTable}\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"{$archiveTable}\".\"Version\" = \"{$baseTable}_versions\".\"Version\"");
             }
             break;
         default:
             throw new InvalidArgumentException("Bad value for query parameter Versioned.mode: " . $dataQuery->getQueryParam('Versioned.mode'));
     }
 }
예제 #3
0
 public function testInnerJoin()
 {
     $query = new SQLQuery();
     $query->from('MyTable');
     $query->innerJoin('MyOtherTable', 'MyOtherTable.ID = 2');
     $query->leftJoin('MyLastTable', 'MyOtherTable.ID = MyLastTable.ID');
     $this->assertEquals('SELECT * FROM MyTable ' . 'INNER JOIN "MyOtherTable" AS "MyOtherTable" ON MyOtherTable.ID = 2 ' . 'LEFT JOIN "MyLastTable" AS "MyLastTable" ON MyOtherTable.ID = MyLastTable.ID', $query->sql());
     $query = new SQLQuery();
     $query->from('MyTable');
     $query->innerJoin('MyOtherTable', 'MyOtherTable.ID = 2', 'table1');
     $query->leftJoin('MyLastTable', 'MyOtherTable.ID = MyLastTable.ID', 'table2');
     $this->assertEquals('SELECT * FROM MyTable ' . 'INNER JOIN "MyOtherTable" AS "table1" ON MyOtherTable.ID = 2 ' . 'LEFT JOIN "MyLastTable" AS "table2" ON MyOtherTable.ID = MyLastTable.ID', $query->sql());
 }
예제 #4
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;
 }
예제 #5
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 $relation The array/dot-syntax relation to follow
	 * @return The model class of the related item
	 */
	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 = $model->getReverseAssociation($component);
    				$this->query->leftJoin($component, "\"$component\".\"ID\" = \"{$modelClass}\".\"{$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){
    							$this->query->innerJoin($ancestor, "\"$component\".\"ID\" = \"$ancestor\".\"ID\"");
    							$component=$ancestor;
    						}
    					}
    				}
    			}
    			$modelClass = $component;

    		} elseif ($component = $model->has_many($rel)) {
    			if(!$this->query->isJoinedTo($component)) {
    			 	$ancestry = $model->getClassAncestry();
    				$foreignKey = $model->getRemoteJoinField($rel);
    				$this->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){
    							$this->query->innerJoin($ancestor, "\"$component\".\"ID\" = \"$ancestor\".\"ID\"");
    							$component=$ancestor;
    						}
    					}
    				}
    			}
    			$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->innerJoin($relationTable, "\"$relationTable\".\"$parentField\" = \"$parentBaseClass\".\"ID\"");
    			$this->query->leftJoin($componentBaseClass, "\"$relationTable\".\"$componentField\" = \"$componentBaseClass\".\"ID\"");
    			if(ClassInfo::hasTable($componentClass)) {
    				$this->query->leftJoin($componentClass, "\"$relationTable\".\"$componentField\" = \"$componentClass\".\"ID\"");
    			}
    			$modelClass = $componentClass;

    		}
		}
		
		return $modelClass;
	}
 /**
  * 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;
 }