/**
  * For lazy loaded fields requiring extra sql manipulation, ie versioning.
  *
  * @param SQLSelect $query
  * @param DataQuery $dataQuery
  * @param DataObject $dataObject
  */
 public function augmentLoadLazyFields(SQLSelect &$query, DataQuery &$dataQuery = null, $dataObject)
 {
     // The VersionedMode local variable ensures that this decorator only applies to
     // queries that have originated from the Versioned object, and have the Versioned
     // metadata set on the query object. This prevents regular queries from
     // accidentally querying the *_versions tables.
     $versionedMode = $dataObject->getSourceQueryParam('Versioned.mode');
     $modesToAllowVersioning = array('all_versions', 'latest_versions', 'archive', 'version');
     if (!empty($dataObject->Version) && (!empty($versionedMode) && in_array($versionedMode, $modesToAllowVersioning))) {
         // This will ensure that augmentSQL will select only the same version as the owner,
         // regardless of how this object was initially selected
         $versionColumn = $this->owner->getSchema()->sqlColumnForField($this->owner, 'Version');
         $dataQuery->where([$versionColumn => $dataObject->Version]);
         $dataQuery->setQueryParam('Versioned.mode', 'all_versions');
     }
 }
 /**
  * Loads all the stub fields that an initial lazy load didn't load fully.
  *
  * @param string $class Class to load the values from. Others are joined as required.
  * Not specifying a tableClass will load all lazy fields from all tables.
  * @return bool Flag if lazy loading succeeded
  */
 protected function loadLazyFields($class = null)
 {
     if (!$this->isInDB() || !is_numeric($this->ID)) {
         return false;
     }
     if (!$class) {
         $loaded = array();
         foreach ($this->record as $key => $value) {
             if (strlen($key) > 5 && substr($key, -5) == '_Lazy' && !array_key_exists($value, $loaded)) {
                 $this->loadLazyFields($value);
                 $loaded[$value] = $value;
             }
         }
         return false;
     }
     $dataQuery = new DataQuery($class);
     // Reset query parameter context to that of this DataObject
     if ($params = $this->getSourceQueryParams()) {
         foreach ($params as $key => $value) {
             $dataQuery->setQueryParam($key, $value);
         }
     }
     // Limit query to the current record, unless it has the Versioned extension,
     // in which case it requires special handling through augmentLoadLazyFields()
     $schema = static::getSchema();
     $baseIDColumn = $schema->sqlColumnForField($this, 'ID');
     $dataQuery->where([$baseIDColumn => $this->record['ID']])->limit(1);
     $columns = array();
     // Add SQL for fields, both simple & multi-value
     // TODO: This is copy & pasted from buildSQL(), it could be moved into a method
     $databaseFields = $schema->databaseFields($class, false);
     foreach ($databaseFields as $k => $v) {
         if (!isset($this->record[$k]) || $this->record[$k] === null) {
             $columns[] = $k;
         }
     }
     if ($columns) {
         $query = $dataQuery->query();
         $this->extend('augmentLoadLazyFields', $query, $dataQuery, $this);
         $this->extend('augmentSQL', $query, $dataQuery);
         $dataQuery->setQueriedColumns($columns);
         $newData = $dataQuery->execute()->record();
         // Load the data into record
         if ($newData) {
             foreach ($newData as $k => $v) {
                 if (in_array($k, $columns)) {
                     $this->record[$k] = $v;
                     $this->original[$k] = $v;
                     unset($this->record[$k . '_Lazy']);
                 }
             }
             // No data means that the query returned nothing; assign 'null' to all the requested fields
         } else {
             foreach ($columns as $k) {
                 $this->record[$k] = null;
                 $this->original[$k] = null;
                 unset($this->record[$k . '_Lazy']);
             }
         }
     }
     return true;
 }
 /**
  * Invoked after getFinalisedQuery()
  *
  * @param DataQuery $dataQuery
  * @param array $queriedColumns
  * @param SQLSelect $sqlQuery
  */
 public function afterGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns = [], SQLSelect $sqlQuery)
 {
     // Inject final replacement after manipulation has been performed on the base dataquery
     $joinTableSQL = $dataQuery->getQueryParam('Foreign.JoinTableSQL');
     if ($joinTableSQL) {
         $sqlQuery->replaceText('SELECT $$_SUBQUERY_$$', $joinTableSQL);
         $dataQuery->setQueryParam('Foreign.JoinTableSQL', null);
     }
 }