示例#1
0
文件: Read.php 项目: torchline/frest
 /**
  * Insert any data after object is retrieved such as computed aliases and converting
  * sub-resource fields into child objects.
  * 
  * @param FREST\Resource $resource
  * @param array $objects
  * @param array $readSettings
  * @param string $resourceAlias
  * 
  * @throws \FREST\Exception
  * @throws Exception
  */
 protected function parseObjects($resource, &$objects, $readSettings, $resourceAlias = NULL)
 {
     // stores the read Setting that are just an ComputedRead
     $computedReadSettings = array();
     $timerInstance = isset($resourceAlias) ? $resourceAlias . '-parse' : 'parse';
     if (isset($readSettings)) {
         /** @var Setting\Read $readSetting */
         foreach ($readSettings as $readSetting) {
             $this->frest->startTimingForLabel(Type\Timing::POST_PROCESSING, $timerInstance);
             $alias = $readSetting->getAlias();
             $partialSubKey = isset($resourceAlias) ? "{$resourceAlias}.{$alias}" : $alias;
             if ($readSetting instanceof Setting\ComputedRead) {
                 $computedReadSettings[$alias] = $readSetting;
             } else {
                 if ($readSetting instanceof Setting\PluralResourceRead) {
                     /** @var Setting\PluralResourceRead $readSetting */
                     $parameters = $readSetting->getParameters();
                     // overwrite 'fields' parameter if partial syntax found
                     $newFields = $this->generateNewFields($partialSubKey);
                     if (isset($newFields)) {
                         $parameters['fields'] = implode(',', $newFields);
                     }
                     $requiredAliases = $readSetting->getRequiredAliases();
                     $loadedResource = $this->getLoadedResource($readSetting->getResourceName());
                     foreach ($objects as &$object) {
                         $requestParameters = array();
                         foreach ($parameters as $field => $parameter) {
                             if (isset($requiredAliases[$field])) {
                                 $requiredAlias = $requiredAliases[$field];
                                 $requiredAliasValuePlaceholder = $loadedResource->injectValue($requiredAlias);
                                 $parameter = str_replace($requiredAliasValuePlaceholder, $object->{$requiredAlias}, $parameter);
                             }
                             $requestParameters[$field] = $parameter;
                         }
                         $this->frest->stopTimingForLabel(Type\Timing::POST_PROCESSING, $timerInstance);
                         $request = new PluralRead($this->frest, $requestParameters, NULL, $readSetting->getAlias());
                         $request->setWasInternallyLoaded(TRUE);
                         $request->setupWithResource($loadedResource);
                         /** @var Result\PluralRead $result */
                         $result = $request->generateResult();
                         $this->frest->startTimingForLabel(Type\Timing::POST_PROCESSING, $timerInstance);
                         $object->{$alias} = $result->getResourceObjects();
                     }
                 } else {
                     if ($readSetting instanceof Setting\SingularResourceRead) {
                         /** @var Setting\SingularResourceRead $readSetting */
                         $loadedResource = $this->getLoadedResource($readSetting->getResourceName());
                         if (isset($this->partialSubReadSettings[$partialSubKey])) {
                             $subReadSettings = $this->partialSubReadSettings[$partialSubKey];
                             $this->addRequiredReadSettings($loadedResource, $subReadSettings);
                         } else {
                             $subReadSettings = $this->getLoadedResourceReadSettings($loadedResource, $readSetting);
                         }
                         $subObjects = array();
                         // remove table-prefixed properties on object as they should be on a sub-object instead
                         foreach ($objects as &$object) {
                             if (!isset($object->{$alias})) {
                                 $object->{$alias} = new \stdClass();
                                 $subObjects[] =& $object->{$alias};
                             }
                             if (!isset($subReadSettings)) {
                                 continue;
                             }
                             foreach ($subReadSettings as $subReadSetting) {
                                 if ($subReadSetting instanceof Setting\FieldRead) {
                                     /** @var Setting\FieldRead $subReadSetting */
                                     $subAlias = $subReadSetting->getAlias();
                                     $subField = $loadedResource->getFieldForAlias($subAlias);
                                     $subTable = $loadedResource->getTableForField($subField);
                                     $subTableKey = isset($resourceAlias) ? "{$subTable}-{$resourceAlias}-{$alias}" : "{$subTable}-{$alias}";
                                     $subTableAbbrv = $this->getTableAbbreviation($subTableKey);
                                     $subProperty = "{$subTableAbbrv}_{$subAlias}";
                                     $subValue = $object->{$subProperty};
                                     $object->{$alias}->{$subAlias} = $subValue;
                                     unset($object->{$subProperty});
                                 } else {
                                     if ($subReadSetting instanceof Setting\SingularResourceRead) {
                                         // move properties of object that should belong to subObject (only nests once? idk)
                                         $subLoadedResource = $this->getLoadedResource($subReadSetting->getResourceName());
                                         $subReadAlias = $subReadSetting->getAlias();
                                         $partialDeepKey = isset($resourceAlias) ? "{$resourceAlias}.{$alias}.{$subReadAlias}" : "{$alias}.{$subReadAlias}";
                                         if (isset($this->partialSubReadSettings[$partialDeepKey])) {
                                             $deepReadSettings = $this->partialSubReadSettings[$partialDeepKey];
                                             $this->addRequiredReadSettings($subLoadedResource, $deepReadSettings);
                                         } else {
                                             $deepReadSettings = $this->getLoadedResourceReadSettings($subLoadedResource, $subReadSetting);
                                         }
                                         foreach ($deepReadSettings as $deepReadSetting) {
                                             if ($deepReadSetting instanceof Setting\FieldRead) {
                                                 $deepAlias = $deepReadSetting->getAlias();
                                                 $deepField = $subLoadedResource->getFieldForAlias($deepAlias);
                                                 $deepTable = $subLoadedResource->getTableForField($deepField);
                                                 $deepTableKey = "{$deepTable}-{$alias}-{$subReadAlias}";
                                                 $deepTableAbbrv = $this->getTableAbbreviation($deepTableKey);
                                                 $deepProperty = "{$deepTableAbbrv}_{$deepAlias}";
                                                 $deepValue = $object->{$deepProperty};
                                                 $object->{$alias}->{$deepProperty} = $deepValue;
                                                 unset($object->{$deepProperty});
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                         // parse sub-objects as well
                         $subAlias = $readSetting->getAlias();
                         $subResourceAlias = isset($resourceAlias) ? "{$resourceAlias}.{$subAlias}" : $subAlias;
                         $this->parseObjects($loadedResource, $subObjects, $subReadSettings, $subResourceAlias);
                     } else {
                         if ($readSetting instanceof Setting\FieldRead) {
                             /** @var Setting\FieldRead $readSetting */
                             $fieldSetting = $resource->getFieldSettingForAlias($alias);
                             $variableType = $fieldSetting->getVariableType();
                             foreach ($objects as &$object) {
                                 $value = Type\Variable::castValue($object->{$alias}, $variableType);
                                 $filterFunction = $readSetting->getFilterFunction();
                                 if (isset($filterFunction)) {
                                     if (!method_exists($resource, $filterFunction)) {
                                         throw new FREST\Exception(FREST\Exception::FilterFunctionMissing, "Function name: '{$filterFunction}', resource: '{$resource->getName()}'");
                                     }
                                     $value = $resource->{$filterFunction}($value);
                                 }
                                 $object->{$alias} = $value;
                             }
                         }
                     }
                 }
             }
             $this->frest->stopTimingForLabel(Type\Timing::POST_PROCESSING, $timerInstance);
         }
     }
     $this->frest->startTimingForLabel(Type\Timing::POST_PROCESSING, $timerInstance);
     // use first object as reference to see what aliases have been set so far (used for computed aliases below)
     $oldObjects = reset($objects);
     $refObject =& $oldObjects;
     /*
     // generate a list of aliases that have so-far been set on each object (used for computed aliases)
     $aliasesDefinedOnObjects = array();
     $objectVars = get_object_vars($firstObject);
     foreach ($objectVars as $alias=>$value) {
     	if (isset($value)) {
     		$aliasesDefinedOnObjects[$alias] = $alias;
     	}
     }
     */
     // computed aliases
     $lastComputedReadSettingCount = count($computedReadSettings);
     $resourceComputer = NULL;
     if ($lastComputedReadSettingCount > 0) {
         $frestConfig = $this->getFREST()->getConfig();
         $formattedResourceName = ucfirst($resource->getName());
         $resourceDir = $frestConfig->getResourceDirectory();
         $computerClassPath = "{$resourceDir}/{$formattedResourceName}.php";
         $computerClassName = "\\FREST\\Computer\\{$formattedResourceName}";
         /** @noinspection PhpIncludeInspection */
         require_once $computerClassPath;
         if (!class_exists($computerClassName, FALSE)) {
             throw new Exception(Exception::Config, "Class '{$formattedResourceName}' not found in file '{$classPath}'");
         }
         $resourceComputer = new $computerClassName($frestConfig->getContext());
     }
     $failedComputingSettings = FALSE;
     while ($lastComputedReadSettingCount > 0) {
         /** @var Setting\ComputedRead $computedReadSetting */
         foreach ($computedReadSettings as $computedReadSetting) {
             $alias = $computedReadSetting->getAlias();
             // determine if all aliases required for this computed alias have been defined
             // (should only NOT be set if the required alias is also a computed column and
             // hasn't been computed yet)
             $hasAllAliasesRequired = TRUE;
             $requiredAliases = $computedReadSetting->getRequiredAliases();
             foreach ($requiredAliases as $requiredAlias) {
                 $subAliases = NULL;
                 $requiredAliasFromPartial = self::getHandleAndValues($requiredAlias, $subAliases) ?: $requiredAlias;
                 // TODO: error check required alias partial syntax
                 if (!isset($refObject->{$requiredAliasFromPartial})) {
                     $hasAllAliasesRequired = FALSE;
                     break;
                 }
                 if (isset($subAliases)) {
                     foreach ($subAliases as $subAlias) {
                         if (!isset($refObject->{$requiredAliasFromPartial}->{$subAlias})) {
                             $hasAllAliasesRequired = FALSE;
                             break;
                         }
                     }
                 }
                 if (!$hasAllAliasesRequired) {
                     break;
                 }
             }
             // move on to the next computed alias (assuming there is one)
             // we'll compute this alias later once its required/computed alias
             // is determined
             if (!$hasAllAliasesRequired) {
                 continue;
             }
             $function = $computedReadSetting->getFunction();
             if (!method_exists($resourceComputer, $function)) {
                 throw new FREST\Exception(FREST\Exception::ComputationFunctionMissing, "The function '{$function}' is not defined in resource computer '{$resource->getName()}'");
             }
             // keep track of what aliases have been defined for use by other computed aliases
             unset($computedReadSettings[$alias]);
             foreach ($objects as &$object) {
                 $object->{$alias} = $resourceComputer->{$function}($object);
             }
         }
         // if we run through loop and no aliases have been computed, break out of loop and fail
         $currentComputedReadSettingCount = count($computedReadSettings);
         if ($currentComputedReadSettingCount >= $lastComputedReadSettingCount) {
             $failedComputingSettings = TRUE;
             break;
         }
         $lastComputedReadSettingCount = $currentComputedReadSettingCount;
     }
     if ($failedComputingSettings) {
         throw new FREST\Exception(FREST\Exception::Config, 'All computed aliases could not be computed. Check your config and make sure there are no malformed requiredField settings');
     }
     $resourceName = $resource->getName();
     if (isset($readSettings)) {
         foreach ($readSettings as $readSetting) {
             $alias = $readSetting->getAlias();
             // remove property if added only by requirement of other properties
             $subAliasesToRemove = isset($this->requiredAliasesAdded[$resourceName][$alias]) ? $this->requiredAliasesAdded[$resourceName][$alias] : NULL;
             if (isset($subAliasesToRemove)) {
                 if (is_array($subAliasesToRemove)) {
                     foreach ($objects as &$object) {
                         foreach ($subAliasesToRemove as $subAlias) {
                             unset($object->{$alias}->{$subAlias});
                         }
                         $isEmpty = count((array) $object->{$alias}) == 0;
                         if ($isEmpty) {
                             unset($object->{$alias});
                         }
                     }
                 } else {
                     foreach ($objects as &$object) {
                         unset($object->{$alias});
                     }
                 }
             }
         }
     }
     $this->frest->stopTimingForLabel(Type\Timing::POST_PROCESSING, $timerInstance);
 }
示例#2
0
 /**
  * @param FREST\Resource $resource
  * @return array
  * @throws FREST\Exception
  */
 private function generateCreateSpecs($resource)
 {
     $createSpecs = array();
     $createSettings = $resource->getCreateSettings();
     if (isset($this->resourceID)) {
         /** @var Setting\Field $idFieldSetting */
         $idFieldName = $this->resource->getIDField($idFieldSetting);
         $idAlias = $this->resource->getAliasForField($idFieldName);
         $idCreateSpec = new Spec\Create($idAlias, $idFieldName, $this->resourceID, $idFieldSetting->getVariableType());
         $createSpecs[$idAlias] = $idCreateSpec;
     }
     /** @var Setting\Create $createSetting */
     foreach ($createSettings as $createSetting) {
         $alias = $createSetting->getAlias();
         if (isset($this->parameters[$alias])) {
             $value = $this->parameters[$alias];
             $field = $resource->getFieldForAlias($alias);
             $fieldSetting = $resource->getFieldSettingForAlias($alias);
             $variableType = $fieldSetting->getVariableType();
             // Type checking
             $castedValue = Type\Variable::castValue($value, $variableType);
             if (!isset($castedValue)) {
                 $typeString = Type\Variable::getString($variableType);
                 throw new FREST\Exception(FREST\Exception::InvalidType, "Expecting '{$alias}' to be of type '{$typeString}' but received '{$value}'");
             }
             // Condition Func
             $conditionFunction = $createSetting->getConditionFunction();
             if (isset($conditionFunction)) {
                 if (!method_exists($resource, $conditionFunction)) {
                     throw new FREST\Exception(FREST\Exception::ConditionFunctionMissing, "Function name: '{$conditionFunction}', resource: '{$this->resource->getName()}'");
                 }
                 $isValueValid = $resource->{$conditionFunction}($castedValue);
                 if (!$isValueValid) {
                     throw new FREST\Exception(FREST\Exception::InvalidFieldValue, "Field: '{$alias}'");
                 }
             }
             // Filter Func
             $filterFunction = $createSetting->getFilterFunction();
             if (isset($filterFunction)) {
                 if (!method_exists($resource, $filterFunction)) {
                     throw new FREST\Exception(FREST\Exception::FilterFunctionMissing, "Function name: '{$filterFunction}', resource: '{$resource->getName()}'");
                 }
                 $castedValue = $resource->{$filterFunction}($castedValue);
             }
             $createSpec = new Spec\Create($alias, $field, $castedValue, $variableType);
             $createSpecs[$alias] = $createSpec;
         } else {
             if ($createSetting->getRequired()) {
                 // get list of all parameters required but not set
                 $missingParameters = array();
                 /** @var Setting\Create $aCreateSetting */
                 foreach ($createSettings as $aCreateSetting) {
                     $alias = $aCreateSetting->getAlias();
                     if (!isset($this->parameters[$alias]) && $aCreateSetting->getRequired()) {
                         $missingParameters[] = $alias;
                     }
                 }
                 $missingParametersString = implode(', ', $missingParameters);
                 throw new FREST\Exception(FREST\Exception::MissingRequiredParams, "Missing parameters: {$missingParametersString}");
             }
         }
     }
     if (count($createSpecs) > 0) {
         return $createSpecs;
     }
     return NULL;
 }
示例#3
0
 /**
  * @param FREST\Resource $resource
  * @return array
  * @throws FREST\Exception
  */
 private function generateUpdateSpecs($resource)
 {
     $updateSpecs = array();
     $updateSettings = $resource->getUpdateSettings();
     /** @var Setting\Update $updateSetting */
     foreach ($updateSettings as $updateSetting) {
         $alias = $updateSetting->getAlias();
         if (isset($this->parameters[$alias])) {
             $value = $this->parameters[$alias];
             $field = $resource->getFieldForAlias($alias);
             $fieldSetting = $resource->getFieldSettingForAlias($alias);
             $variableType = $fieldSetting->getVariableType();
             // Type checking
             $castedValue = Type\Variable::castValue($value, $variableType);
             if (!isset($castedValue)) {
                 $typeString = Type\Variable::getString($variableType);
                 throw new FREST\Exception(FREST\Exception::InvalidType, "Expecting '{$alias}' to be of type '{$typeString}' but received '{$value}'");
             }
             // Condition Func
             $conditionFunction = $updateSetting->getConditionFunction();
             if (isset($conditionFunction)) {
                 if (!method_exists($resource, $conditionFunction)) {
                     throw new FREST\Exception(FREST\Exception::ConditionFunctionMissing, "Function name: '{$conditionFunction}', resource: '{$resource->getName()}'");
                 }
                 $isValueValid = $resource->{$conditionFunction}($castedValue);
                 if (!$isValueValid) {
                     throw new FREST\Exception(FREST\Exception::InvalidFieldValue, "Field: '{$alias}'");
                 }
             }
             // Filter Func
             $filterFunction = $updateSetting->getFilterFunction();
             if (isset($filterFunction)) {
                 if (!method_exists($resource, $filterFunction)) {
                     throw new FREST\Exception(FREST\Exception::FilterFunctionMissing, "Function name: '{$filterFunction}', resource: '{$resource->getName()}'");
                 }
                 $castedValue = $resource->{$filterFunction}($castedValue);
             }
             $updateSpec = new Spec\Update($alias, $field, $castedValue, $variableType);
             $updateSpecs[$alias] = $updateSpec;
         }
     }
     return $updateSpecs;
 }