/** * @dataProvider additionProvider */ public function testHasPropertyAnnotation($a) { $objAnnotations = new class_reflection(new B()); $this->assertTrue($objAnnotations->hasPropertyAnnotation("propertyB1", "@propertyTest")); $this->assertTrue(!$objAnnotations->hasPropertyAnnotation("propertyB1", "@property2Test")); $objAnnotations = new class_reflection(new A()); $this->assertTrue($objAnnotations->hasPropertyAnnotation("propertyA1", "@propertyTest")); }
/** * searches an annotation (e.g. @version) in the doccomment of a passed property and validates * the existence of this annotation * * @param string $strPropertyName * @param string $strAnnotation * @return bool */ public function hasPropertyAnnotation($strPropertyName, $strAnnotation) { if (isset($this->arrCurrentCache[self::$STR_HASPROPERTY_CACHE][$strPropertyName . "_" . $strAnnotation])) { return $this->arrCurrentCache[self::$STR_HASPROPERTY_CACHE][$strPropertyName . "_" . $strAnnotation]; } try { $objReflectionMethod = $this->objReflectionClass->getProperty($strPropertyName); $bitReturn = false !== $this->searchFirstAnnotationInDoc($objReflectionMethod->getDocComment(), $strAnnotation); } catch (ReflectionException $objEx) { //not found in current class, maybe a base-class is existing? $objBaseClass = $this->objReflectionClass->getParentClass(); if ($objBaseClass !== false) { $objBaseAnnotations = new class_reflection($objBaseClass->getName()); $bitReturn = $objBaseAnnotations->hasPropertyAnnotation($strPropertyName, $strAnnotation); } } $this->arrCurrentCache[self::$STR_HASPROPERTY_CACHE][$strPropertyName . "_" . $strAnnotation] = $bitReturn; self::$bitCacheSaveRequired = true; return $bitReturn; }
/** * Crreates an object of type '$strClassType'. * Only properties which are annotated with @var will be considered * * @param string $strClassType - the name of the class as a string * @param string $strParentId - the parent id of the object to be created * @param array $arrExcludeFillProperty - array of poperty names which will not be set * @param array $arrPropertyValues - assoziative array which has as key the property name and as value the to be set for the property * @param boolean $bitAutofillProperties - if true all properties which have annotation @tablecolumn will be filled with random values * * @return class_model */ protected function createObject($strClassType, $strParentId, array $arrExcludeFillProperty = array(), array $arrPropertyValues = array(), $bitAutofillProperties = true) { //get properties with an tablecolumn annotation $objObject = new $strClassType(); $objReflection = new class_reflection($strClassType); $arrProperties = $objReflection->getPropertiesWithAnnotation(class_orm_base::STR_ANNOTATION_TABLECOLUMN); $arrProperties = array_merge($objReflection->getPropertiesWithAnnotation(class_orm_base::STR_ANNOTATION_OBJECTLIST), $arrProperties); //exclude class_root properties $objRootReflection = new class_reflection("class_root"); $arrExcludeFillProperty = array_merge($arrExcludeFillProperty, array_keys($objRootReflection->getPropertiesWithAnnotation(class_orm_base::STR_ANNOTATION_TABLECOLUMN))); foreach ($arrProperties as $strPropName => $strValue) { //Exclude properties to be set if (in_array($strPropName, $arrExcludeFillProperty)) { continue; } //Set properties from array $arrPropertyValues if (array_key_exists($strPropName, $arrPropertyValues)) { $strSetterMethod = $objReflection->getSetter($strPropName); if ($strSetterMethod !== null) { $objValue = $arrPropertyValues[$strPropName]; $objObject->{$strSetterMethod}($objValue); continue; } } //check if the property is annotated with @tablecolumn if ($bitAutofillProperties) { if ($objReflection->hasPropertyAnnotation($strPropName, class_orm_base::STR_ANNOTATION_TABLECOLUMN)) { $strSetterMethod = $objReflection->getSetter($strPropName); if ($strSetterMethod !== null) { //determine the field type $strDataType = $objReflection->getAnnotationValueForProperty($strPropName, "@var"); $strFieldType = $objReflection->getAnnotationValueForProperty($strPropName, "@fieldType"); $objMethodValue = null; if ($strDataType == "string") { if ($strFieldType == "text" || $strFieldType == "textarea") { $objMethodValue = $strPropName . "_" . $objObject->getStrSystemid(); if (uniStrlen($objMethodValue) > 10) { $objMethodValue = uniStrTrim($objMethodValue, 10, ""); } } } else { if ($strDataType == "int" || $strDataType == "numeric") { if ($strFieldType != "dropdown") { $objMethodValue = 1; } } else { if ($strDataType == "class_date") { $objMethodValue = new class_date(); } else { if ($strDataType == "bool") { $objMethodValue = false; } else { continue; //continue with foreach } } } } $objObject->{$strSetterMethod}($objMethodValue); } } } } //save it $objObject->updateObjectToDb($strParentId); return $objObject; }
/** * Triggers the update sequence for assignment properties * @return bool */ private function updateAssignments() { $bitReturn = true; $objReflection = new class_reflection($this->getObjObject()); //get the mapped properties $arrProperties = $objReflection->getPropertiesWithAnnotation(class_orm_base::STR_ANNOTATION_OBJECTLIST, class_reflection_enum::PARAMS()); foreach ($arrProperties as $strPropertyName => $arrValues) { $objCfg = class_orm_assignment_config::getConfigForProperty($this->getObjObject(), $strPropertyName); //try to load the orm config of the arrayObject - if given $strGetter = $objReflection->getGetter($strPropertyName); $arrValues = null; if ($strGetter !== null) { $arrValues = call_user_func(array($this->getObjObject(), $strGetter)); } $objAssignmentDeleteHandling = $this->getIntCombinedLogicalDeletionConfig(); if ($arrValues != null && $arrValues instanceof class_orm_assignment_array) { $objAssignmentDeleteHandling = $arrValues->getObjDeletedHandling(); } //try to restore the object-set from the database using the same config as when initializing the object $objOldHandling = $this->getIntCombinedLogicalDeletionConfig(); $this->setObjHandleLogicalDeleted($objAssignmentDeleteHandling); $arrAssignmentsFromObject = $this->getAssignmentValuesFromObject($strPropertyName, $objCfg->getArrTypeFilter()); $arrAssignmentsFromDatabase = $this->getAssignmentsFromDatabase($strPropertyName); $this->setObjHandleLogicalDeleted($objOldHandling); //if the delete handling was set to excluded when loading the assignment, the logically deleted nodes should be merged with the values from db if ($objAssignmentDeleteHandling->equals(class_orm_deletedhandling_enum::EXCLUDED())) { $this->setObjHandleLogicalDeleted(class_orm_deletedhandling_enum::EXCLUSIVE()); $arrDeletedIds = $this->getAssignmentsFromDatabase($strPropertyName); $this->setObjHandleLogicalDeleted($objOldHandling); foreach ($arrDeletedIds as $strOneId) { if (!in_array($strOneId, $arrAssignmentsFromDatabase)) { $arrAssignmentsFromDatabase[] = $strOneId; } if (!in_array($strOneId, $arrAssignmentsFromObject)) { $arrAssignmentsFromObject[] = $strOneId; } } } sort($arrAssignmentsFromObject); sort($arrAssignmentsFromDatabase); //only do s.th. if the array differs $arrNewAssignments = array_diff($arrAssignmentsFromObject, $arrAssignmentsFromDatabase); $arrDeletedAssignments = array_diff($arrAssignmentsFromDatabase, $arrAssignmentsFromObject); //skip in case there's nothing to do if (count($arrNewAssignments) == 0 && count($arrDeletedAssignments) == 0) { continue; } $objDB = class_carrier::getInstance()->getObjDB(); $arrInserts = array(); foreach ($arrAssignmentsFromObject as $strOneTargetId) { $arrInserts[] = array($this->getObjObject()->getSystemid(), $strOneTargetId); } $bitReturn = $bitReturn && $objDB->_pQuery("DELETE FROM " . $objDB->encloseTableName(_dbprefix_ . $objCfg->getStrTableName()) . " WHERE " . $objDB->encloseColumnName($objCfg->getStrSourceColumn()) . " = ?", array($this->getObjObject()->getSystemid())); $bitReturn = $bitReturn && $objDB->multiInsert($objCfg->getStrTableName(), array($objCfg->getStrSourceColumn(), $objCfg->getStrTargetColumn()), $arrInserts); $bitReturn = $bitReturn && class_core_eventdispatcher::getInstance()->notifyGenericListeners(class_system_eventidentifier::EVENT_SYSTEM_OBJECTASSIGNMENTSUPDATED, array(array_values($arrNewAssignments), array_values($arrDeletedAssignments), array_values($arrAssignmentsFromObject), $this->getObjObject(), $strPropertyName)); if ($objReflection->hasPropertyAnnotation($strPropertyName, class_module_system_changelog::ANNOTATION_PROPERTY_VERSIONABLE)) { $objChanges = new class_module_system_changelog(); $objChanges->setOldValueForSystemidAndProperty($this->getObjObject()->getSystemid(), $strPropertyName, implode(",", $arrAssignmentsFromDatabase)); } } return $bitReturn; }
/** * @param string $strClass * * @return array * @throws class_orm_exception * @throws class_exception */ private function collectTableDefinitions($strClass) { $objReflection = new class_reflection($strClass); $arrTargetTables = $objReflection->getAnnotationValuesFromClass(self::STR_ANNOTATION_TARGETTABLE); $arrTxSafe = $objReflection->getAnnotationValuesFromClass(self::STR_ANNOTATION_TARGETTABLETXSAFE); /** @var class_orm_schemamanager_table[] $arrCreateTables */ $arrCreateTables = array(); foreach ($arrTargetTables as $strValue) { $arrTable = explode(".", $strValue); if (count($arrTable) != 2) { throw new class_orm_exception("Target table for " . $strClass . " is not in table.primaryColumn format", class_orm_exception::$level_ERROR); } $objTable = new class_orm_schemamanager_table($arrTable[0]); if (count($arrTxSafe) == 1) { $objTable->setBitTxSafe($arrTxSafe[0] == "false" ? false : true); } $objTable->addRow(new class_orm_schemamanager_row($arrTable[1], class_db_datatypes::STR_TYPE_CHAR20, false, true)); $arrCreateTables[$arrTable[0]] = $objTable; } //merge them with the list of mapped columns $arrProperties = $objReflection->getPropertiesWithAnnotation(self::STR_ANNOTATION_TABLECOLUMN); foreach ($arrProperties as $strProperty => $strTableColumn) { //fetch the target data-type $strTargetDataType = $objReflection->getAnnotationValueForProperty($strProperty, self::STR_ANNOTATION_TABLECOLUMNDATATYPE); if ($strTargetDataType == null) { $strTargetDataType = class_db_datatypes::STR_TYPE_CHAR254; } if (!in_array($strTargetDataType, self::$arrColumnDataTypes)) { throw new class_orm_exception("Datatype " . $strTargetDataType . " is unknown (" . $strProperty . "@" . $strClass . ")", class_orm_exception::$level_ERROR); } $arrColumn = explode(".", $strTableColumn); if (count($arrColumn) != 2 && count($arrTargetTables) > 1) { throw new class_orm_exception("Syntax for tableColumn annotation at property " . $strProperty . "@" . $strClass . " not in format table.columnName", class_exception::$level_ERROR); } if (count($arrColumn) == 1 && count($arrTargetTables) == 1) { //copy the column name, table is the current one $arrTable = explode(".", $arrTargetTables[0]); $arrColumn[1] = $arrColumn[0]; $arrColumn[0] = $arrTable[0]; } $objRow = new class_orm_schemamanager_row($arrColumn[1], $strTargetDataType); if ($objReflection->hasPropertyAnnotation($strProperty, class_orm_base::STR_ANNOTATION_TABLECOLUMNINDEX)) { $objRow->setBitIndex(true); } if ($objReflection->hasPropertyAnnotation($strProperty, class_orm_base::STR_ANNOTATION_TABLECOLUMNPRIMARYKEY)) { $objRow->setBitPrimaryKey(true); } if (isset($arrCreateTables[$arrColumn[0]])) { $objTable = $arrCreateTables[$arrColumn[0]]; $objTable->addRow($objRow); } } return $arrCreateTables; }