/** * @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; }
/** * Returns the fitting form generator for the model. The result is cached so that the a model returns always the * same instance * * @param interface_model $objInstance * @return class_admin_formgenerator * @throws class_exception */ public static function createByModel(interface_model $objInstance) { // check whether the form was already generated $objForm = self::getFormForModel($objInstance); if ($objForm !== null) { return $objForm; } // check whether a specific form generator class was specified per annotation $objReflection = new class_reflection($objInstance); $arrValues = $objReflection->getAnnotationValuesFromClass(self::STR_FORMGENERATOR_ANNOTATION); if (!empty($arrValues)) { $strClass = current($arrValues); if (class_exists($strClass)) { $objForm = new $strClass($objInstance->getArrModule("module"), $objInstance); } else { throw new class_exception("Provided form generator class does not exist", class_exception::$level_ERROR); } } else { $objForm = new class_admin_formgenerator($objInstance->getArrModule("module"), $objInstance); } // check whether we have an correct instance if ($objForm instanceof class_admin_formgenerator) { $objForm->generateFieldsFromObject(); return self::$arrForms[self::getKeyByModel($objInstance)] = $objForm; } else { throw new class_exception("Provided form generator must be an instance of class_admin_formgenerator", class_exception::$level_ERROR); } }
/** * @param interface_admin|interface_portal $objViewInstance */ private function runSingleFile($objViewInstance) { $objReflection = new ReflectionClass($objViewInstance); $arrMethods = $objReflection->getMethods(); $objAnnotations = new class_reflection(get_class($objViewInstance)); //collect the autotestable annotations located on class-level foreach ($objAnnotations->getAnnotationValuesFromClass("@autoTestable") as $strValue) { foreach (explode(",", $strValue) as $strOneMethod) { echo "found method " . get_class($objViewInstance) . "@" . $strOneMethod . " marked as class-based @autoTestable, preparing call\n"; echo " calling via action() method\n"; $objViewInstance->action($strOneMethod); } } /** @var ReflectionMethod $objOneMethod */ foreach ($arrMethods as $objOneMethod) { if ($objAnnotations->hasMethodAnnotation($objOneMethod->getName(), "@autoTestable")) { echo "found method " . get_class($objViewInstance) . "@" . $objOneMethod->getName() . " marked as @autoTestable, preparing call\n"; if (uniSubstr($objOneMethod->getName(), 0, 6) == "action" && $objReflection->hasMethod("action")) { echo " calling via action() method\n"; $objViewInstance->action(uniSubstr($objOneMethod->getName(), 6)); } else { echo " direct call"; $objOneMethod->invoke($objViewInstance); } } } }
/** * returns the table used by the element * * @return string */ public function getTable() { $objAnnotations = new class_reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(class_orm_base::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) != 0) { $arrTable = explode(".", $arrTargetTables[0]); return _dbprefix_ . $arrTable[0]; } //legacy code return $this->getArrModule("table"); }
/** * Deletes the current object from the system. * By default, all entries are delete from all tables indicated by the class-doccomment. * If you want to trigger additional deletes, overwrite this method. * The system-record itself is being deleted automatically, too. * * @throws class_exception * @return bool */ public function deleteObject() { if (!validateSystemid($this->getObjObject()->getSystemid()) || !$this->hasTargetTable()) { return true; } $objDB = class_carrier::getInstance()->getObjDB(); $bitReturn = $this->deleteAssignments(); $objAnnotations = new class_reflection($this->getObjObject()); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass("@targetTable"); if (count($arrTargetTables) > 0) { foreach ($arrTargetTables as $strOneTable) { $arrSingleTable = explode(".", $strOneTable); $strQuery = "DELETE FROM " . $objDB->encloseTableName(_dbprefix_ . $arrSingleTable[0]) . "\n WHERE " . $objDB->encloseColumnName($arrSingleTable[1]) . " = ? "; $bitReturn = $bitReturn && $objDB->_pQuery($strQuery, array($this->getObjObject()->getSystemid())); } } return $bitReturn; }
/** * Fetches a list of annotations from the class-doc-comment. * Please be aware that this method returns an array and not only a single line. * Parent classes are evaluated, too. * * @param $strAnnotation * @param class_reflection_enum $objEnum - whether to return annotation values or parameters, default is values * * @return array|string|string[] */ public function getAnnotationValuesFromClass($strAnnotation, class_reflection_enum $objEnum = null) { if ($objEnum == null) { $objEnum = class_reflection_enum::VALUES(); } if (isset($this->arrCurrentCache[self::$STR_CLASS_PROPERTIES_CACHE][$strAnnotation . "_" . $objEnum])) { return $this->arrCurrentCache[self::$STR_CLASS_PROPERTIES_CACHE][$strAnnotation . "_" . $objEnum]; } $strClassDoc = $this->objReflectionClass->getDocComment(); $arrReturn = $this->searchAnnotationInDoc($strClassDoc, $strAnnotation); if (count($arrReturn) == 2) { if ($objEnum->equals(class_reflection_enum::PARAMS())) { $arrReturn = $arrReturn["params"]; } if ($objEnum->equals(class_reflection_enum::VALUES())) { $arrReturn = $arrReturn["values"]; } } //check if there's a base-class -> inheritance $objBaseClass = $this->objReflectionClass->getParentClass(); if ($objBaseClass !== false) { $objBaseAnnotations = new class_reflection($objBaseClass->getName()); $arrReturn = array_merge($arrReturn, $objBaseAnnotations->getAnnotationValuesFromClass($strAnnotation, $objEnum)); } $this->arrCurrentCache[self::$STR_CLASS_PROPERTIES_CACHE][$strAnnotation . "_" . $objEnum] = $arrReturn; self::$bitCacheSaveRequired = true; return $arrReturn; }
/** * @param string $strSystemid */ public function __construct($strSystemid = "") { //Generating all the required objects. For this we use our cool cool carrier-object //take care of loading just the necessary objects $objCarrier = class_carrier::getInstance(); $this->objConfig = $objCarrier->getObjConfig(); $this->objSession = $objCarrier->getObjSession(); $this->objLang = $objCarrier->getObjLang(); $this->objTemplate = $objCarrier->getObjTemplate(); //Setting SystemID if ($strSystemid == "") { $this->setSystemid(class_carrier::getInstance()->getParam("systemid")); } else { $this->setSystemid($strSystemid); } //And keep the action $this->setAction($this->getParam("action")); //in most cases, the list is the default action if no other action was passed if ($this->getAction() == "") { $this->setAction("list"); } //try to load the current module-name and the moduleId by reflection $objReflection = new class_reflection($this); if (!isset($this->arrModule["modul"])) { $arrAnnotationValues = $objReflection->getAnnotationValuesFromClass(self::STR_MODULE_ANNOTATION); if (count($arrAnnotationValues) > 0) { $this->setArrModuleEntry("modul", trim($arrAnnotationValues[0])); } $this->setArrModuleEntry("module", trim($arrAnnotationValues[0])); } if (!isset($this->arrModule["moduleId"])) { $arrAnnotationValues = $objReflection->getAnnotationValuesFromClass(self::STR_MODULEID_ANNOTATION); if (count($arrAnnotationValues) > 0) { $this->setArrModuleEntry("moduleId", constant(trim($arrAnnotationValues[0]))); } } $this->strLangBase = $this->getArrModule("modul"); }
/** * @dataProvider additionProvider */ public function testGetAnnotationValuesFromClassParameter($a) { $objReflection = new class_reflection(new C()); $this->assertTrue($objReflection->hasClassAnnotation("@classTest")); $this->assertTrue($objReflection->hasClassAnnotation("@classParamTest1")); $this->assertTrue($objReflection->hasClassAnnotation("@classParamTest2")); $this->assertTrue($objReflection->hasClassAnnotation("@classParamTest3")); $this->assertTrue($objReflection->hasClassAnnotation("@classParamTest4")); $this->assertTrue($objReflection->hasClassAnnotation("@fieldDDValues")); $arrClassAnnotations = $objReflection->getAnnotationValuesFromClass("@classTest"); $this->assertEquals(5, count($arrClassAnnotations)); $this->assertTrue(in_array("val1", $arrClassAnnotations)); $this->assertTrue(in_array("val2", $arrClassAnnotations)); $this->assertTrue(in_array("val3", $arrClassAnnotations)); $this->assertTrue(in_array("val4", $arrClassAnnotations)); $this->assertTrue(in_array("val5", $arrClassAnnotations)); //Values $arrValues = $objReflection->getAnnotationValuesFromClass("@classParamTest1"); $this->assertCount(1, $arrValues); $this->assertEquals("val1", $arrValues[0]); class_reflection::flushCache(); $arrValues = $objReflection->getAnnotationValuesFromClass("@classParamTest2"); $this->assertCount(2, $arrValues); $this->assertEquals("", $arrValues[0]); $this->assertEquals("", $arrValues[1]); class_reflection::flushCache(); $arrValues = $objReflection->getAnnotationValuesFromClass("@classParamTest3"); $this->assertCount(1, $arrValues); $this->assertEquals("val3", $arrValues[0]); class_reflection::flushCache(); $arrValues = $objReflection->getAnnotationValuesFromClass("@classParamTest4"); $this->assertCount(1, $arrValues); $this->assertEquals("", $arrValues[0]); class_reflection::flushCache(); //Params $arrParams = $objReflection->getAnnotationValuesFromClass("@classParamTest1", class_reflection_enum::PARAMS()); $this->assertCount(1, $arrParams); $this->assertCount(0, $arrParams[0]); class_reflection::flushCache(); $arrParamsAll = $objReflection->getAnnotationValuesFromClass("@classParamTest2", class_reflection_enum::PARAMS()); $this->assertCount(2, $arrParamsAll); //param from tow classes //Class C $arrParams = $arrParamsAll[0]; $this->assertCount(5, $arrParams); $this->assertArrayHasKey("param1", $arrParams); $this->assertArrayHasKey("param2", $arrParams); $this->assertArrayHasKey("param3", $arrParams); $this->assertArrayHasKey("param4", $arrParams); $this->assertArrayHasKey("param5", $arrParams); $this->assertEquals(0, $arrParams["param1"]); $this->assertEquals("abc", $arrParams["param2"]); $this->assertTrue(is_array($arrParams["param3"])); $this->assertEquals("0", $arrParams["param3"][0]); $this->assertEquals("123", $arrParams["param3"][1]); $this->assertEquals("456", $arrParams["param3"][2]); $this->assertEquals(999, $arrParams["param4"]); $this->assertEquals("hans im glück", $arrParams["param5"]); //Class B $arrParams = $arrParamsAll[1]; $this->assertCount(2, $arrParams); $this->assertArrayHasKey("param1", $arrParams); $this->assertArrayHasKey("param2", $arrParams); $this->assertEquals(54, $arrParams["param1"]); $this->assertEquals(12334, $arrParams["param2"]); //Class C $arrParams = $objReflection->getAnnotationValuesFromClass("@classParamTest3", class_reflection_enum::PARAMS()); $arrParams = $arrParams[0]; $this->assertCount(3, $arrParams); $this->assertArrayHasKey("param1", $arrParams); $this->assertArrayHasKey("param2", $arrParams); $this->assertArrayHasKey("param3", $arrParams); $this->assertEquals(0, $arrParams["param1"]); $this->assertEquals("abc", $arrParams["param2"]); $this->assertTrue(is_array($arrParams["param3"])); $this->assertEquals("0", $arrParams["param3"][0]); $this->assertEquals("123", $arrParams["param3"][1]); $this->assertEquals("456", $arrParams["param3"][2]); //Class C $arrParams = $objReflection->getAnnotationValuesFromClass("@classParamTest4", class_reflection_enum::PARAMS()); $arrParams = $arrParams[0]; $this->assertCount(0, $arrParams); }
/** * Called whenever a update-request was fired. * Use this method to synchronize the current object with the database. * Use only updates, inserts are not required to be implemented. * Provides a default implementation based on the current objects column mappings. * Override this method whenever you want to perform additional actions or escaping. * * @throws class_exception * @return bool */ public function updateStateToDb() { if (!validateSystemid($this->getObjObject()->getSystemid()) || !$this->hasTargetTable()) { return true; } //fetch properties with annotations $objReflection = new class_reflection($this->getObjObject()); $arrTargetTables = $objReflection->getAnnotationValuesFromClass(class_orm_base::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) == 0) { //no table mapping found - skip return true; } $bitReturn = true; foreach ($arrTargetTables as $strOneTable) { $arrTableDef = explode(".", $strOneTable); //scan all properties $arrColValues = array(); $arrEscapes = array(); //get the mapped properties $arrProperties = $objReflection->getPropertiesWithAnnotation(class_orm_base::STR_ANNOTATION_TABLECOLUMN); foreach ($arrProperties as $strPropertyName => $strColumn) { //check if there are table annotation available $arrColumnDef = explode(".", $strColumn); //if the column doesn't declare a target table whereas the class defines more then one - skip it. if (count($arrColumnDef) == 1 && count($arrTargetTables) > 1) { throw new class_orm_exception("property " . $strPropertyName . " declares no target table, class " . get_class($this->getObjObject()) . " declares more than one target table.", class_exception::$level_FATALERROR); } //skip if property targets another table if (count($arrColumnDef) == 2 && $arrColumnDef[0] != $arrTableDef[0]) { continue; } if (count($arrColumnDef) == 2) { $strColumn = $arrColumnDef[1]; } //all prerequisites match, start creating query $strGetter = $objReflection->getGetter($strPropertyName); if ($strGetter !== null) { //explicit casts required? could be relevant, depending on the target column type / database system $mixedValue = call_user_func(array($this->getObjObject(), $strGetter)); if ($mixedValue !== null && (uniStrtolower(uniSubstr($strGetter, 0, 6)) == "getint" || uniStrtolower(uniSubstr($strGetter, 0, 6)) == "getbit")) { //different casts on 32bit / 64bit if ($mixedValue > PHP_INT_MAX) { $mixedValue = (double) $mixedValue; } else { $mixedValue = (int) $mixedValue; } } $arrColValues[$strColumn] = $mixedValue; $arrEscapes[] = !$objReflection->hasPropertyAnnotation($strPropertyName, class_orm_base::STR_ANNOTATION_BLOCKESCAPING); } } //update table if (count($arrColValues) > 0) { $bitReturn = $bitReturn && $this->updateSingleTable($arrColValues, $arrEscapes, $arrTableDef[0], $arrTableDef[1]); } } //see, if we should process object lists, too if ($bitReturn) { $bitReturn = $this->updateAssignments(); } if ($this->getObjObject() instanceof interface_versionable) { $objChanges = new class_module_system_changelog(); $objChanges->createLogEntry($this->getObjObject(), class_module_system_changelog::$STR_ACTION_EDIT); } return $bitReturn; }
/** * @xml * @permissions edit * @return string */ protected function actionUpdateObjectProperty() { $strReturn = ""; //get the object to update /** @var $objObject class_module_pages_element */ $objObject = class_objectfactory::getInstance()->getObject($this->getSystemid()); if ($objObject->rightEdit()) { //differ between two modes - page-elements or regular objects if ($objObject instanceof class_module_pages_pageelement) { $strPageSystemid = $objObject->getPrevId(); $objLockmanager = new class_lockmanager($objObject->getSystemid()); if (!$objLockmanager->isLocked()) { $objLockmanager->lockRecord(); } if ($objLockmanager->isLockedByCurrentUser()) { //and finally create the object /** @var class_module_pages_pageelement $objElement */ $strElementClass = str_replace(".php", "", $objObject->getStrClassAdmin()); //and finally create the object /** @var $objElement class_element_admin */ $objElement = new $strElementClass(); $objElement->setSystemid($this->getSystemid()); $arrElementData = $objElement->loadElementData(); //see if we could set the param to the element if ($this->getParam("property") != "") { $strProperty = null; //try to fetch the matching setter $objReflection = new class_reflection($objElement); //try to fetch the property based on the orm annotations $strTargetTable = $objReflection->getAnnotationValuesFromClass(class_orm_base::STR_ANNOTATION_TARGETTABLE); if (count($strTargetTable) > 0) { $strTargetTable = $strTargetTable[0]; } $arrTable = explode(".", $strTargetTable); if (count($arrTable) == 2) { $strTargetTable = $arrTable[0]; } $arrOrmProperty = $objReflection->getPropertiesWithAnnotation(class_orm_base::STR_ANNOTATION_TABLECOLUMN); foreach ($arrOrmProperty as $strCurProperty => $strValue) { if ($strValue == $strTargetTable . "." . $this->getParam("property")) { $strProperty = $strCurProperty; } } if ($strProperty == null) { $strProperty = $this->getParam("property"); } $strSetter = $objReflection->getSetter($strProperty); if ($strSetter != null) { call_user_func(array($objElement, $strSetter), $this->getParam("value")); } else { $arrElementData[$this->getParam("property")] = $this->getParam("value"); $objElement->setArrParamData($arrElementData); } } //pass the data to the element, maybe the element wants to update some data $objElement->doBeforeSaveToDb(); //check, if we could save the data, so the element needn't to //woah, we are soooo great $objElement->updateForeignElement(); //Edit Date of page & unlock $objPage = class_objectfactory::getInstance()->getObject($strPageSystemid); $objPage->updateObjectToDb(); $objLockmanager->unlockRecord(); //allow the element to run actions after saving $objElement->doAfterSaveToDb(); //Loading the data of the corresp site $this->flushCompletePagesCache(); $strReturn = "<message><success>element update succeeded</success></message>"; } } else { //any other object - try to find the matching property and write the value if ($this->getParam("property") == "") { class_response_object::getInstance()->setStrStatusCode(class_http_statuscodes::SC_BADREQUEST); return "<message><error>missing property param</error></message>"; } $objReflection = new class_reflection($objObject); $strSetter = $objReflection->getSetter($this->getParam("property")); if ($strSetter == null) { class_response_object::getInstance()->setStrStatusCode(class_http_statuscodes::SC_BADREQUEST); return "<message><error>setter not found</error></message>"; } call_user_func(array($objObject, $strSetter), $this->getParam("value")); $objObject->updateObjectToDb(); $this->flushCompletePagesCache(); $strReturn = "<message><success>object update succeeded</success></message>"; } } else { class_response_object::getInstance()->setStrStatusCode(class_http_statuscodes::SC_UNAUTHORIZED); $strReturn = "<message><error>" . $this->getLang("ds_gesperrt") . "." . $this->getLang("commons_error_permissions") . "</error></message>"; } return $strReturn; }
/** * Validates the current form. * * @throws class_exception * @return bool */ public function validateForm() { $objLang = class_carrier::getInstance()->getObjLang(); //1. Validate fields foreach ($this->arrFields as $objOneField) { $bitFieldIsEmpty = !is_array($objOneField->getStrValue()) && trim($objOneField->getStrValue()) === "" || is_null($objOneField->getStrValue()) || is_array($objOneField->getStrValue()) && count($objOneField->getStrValue()) == 0; //if it is an array with no entries //mandatory field if ($objOneField->getBitMandatory()) { //if field is mandatory and empty -> validation error if ($bitFieldIsEmpty) { $this->addValidationError($objOneField->getStrEntryName(), $objLang->getLang("commons_validator_field_empty", "system", array($objOneField->getStrLabel()))); } } //if field is not empty -> validate if (!$bitFieldIsEmpty) { if (!$objOneField->validateValue()) { $this->addValidationError($objOneField->getStrEntryName(), $objOneField->getStrValidationErrorMsg()); } } } //2. Validate complete object if ($this->getObjSourceobject() != null) { $objReflection = new class_reflection($this->getObjSourceobject()); $arrObjectValidator = $objReflection->getAnnotationValuesFromClass(self::STR_OBJECTVALIDATOR_ANNOTATION); if (count($arrObjectValidator) == 1) { $strObjectValidator = $arrObjectValidator[0]; if (!class_exists($strObjectValidator)) { throw new class_exception("object validator " . $strObjectValidator . " not existing", class_exception::$level_ERROR); } /** @var class_objectvalidator_base $objValidator */ $objValidator = new $strObjectValidator(); //Keep the reference of the current object $objSourceObjectTemp = $this->getObjSourceobject(); //Create a new instance of the source object and set it as source object in the formgenerator //Each existing field will also reference the new created source object $strClassName = get_class($this->objSourceobject); $this->objSourceobject = new $strClassName($this->objSourceobject->getStrSystemid()); foreach ($this->arrFields as $objOneField) { if ($objOneField->getObjSourceObject() != null) { $objOneField->setObjSourceObject($this->objSourceobject); } } //if we are in new-mode, we should fix the prev-id to the lateron matching one if ($this->getField("mode") != null && $this->getField("mode")->getStrValue() == "new" || class_carrier::getInstance()->getParam("mode") == "new") { $this->objSourceobject->setStrPrevId(class_carrier::getInstance()->getParam("systemid")); } //Update the new source object values from the fields and validate the object $this->updateSourceObject(); $objValidator->validateObject($this->getObjSourceobject()); foreach ($objValidator->getArrValidationMessages() as $strKey => $arrMessages) { if (!is_array($arrMessages)) { throw new class_exception("method validateObject must return an array of format array(\"<messageKey>\" => array())", class_exception::$level_ERROR); } foreach ($arrMessages as $strMessage) { $this->addValidationError($strKey, $strMessage); } } //Set back kept reference to the formgenerator and all it's fields $this->objSourceobject = $objSourceObjectTemp; foreach ($this->arrFields as $objOneField) { if ($objOneField->getObjSourceObject() != null) { $objOneField->setObjSourceObject($objSourceObjectTemp); } } } } return count($this->arrValidationErrors) == 0; }
/** * Saves the current object to the database. Determines, whether the current object has to be inserted * or updated to the database. * In case of an update, the objects' updateStateToDb() method is being called (as required by class_model). * In the case of a new object, a blank record is being created. Therefore, all tables returned by class' doc comment * will be filled with a new record (using the same new systemid as the primary key). * The newly created systemid is being set as the current objects' one and can be used in the afterwards * called updateStateToDb() method to reference the correct rows. * * @param string|bool $strPrevId The prev-id of the records, either to be used for the insert or to be used during the update of the record * @return bool * @since 3.3.0 * @throws class_exception * @see interface_model * * @todo move to class_orm_objectupdate completely */ public function updateObjectToDb($strPrevId = false) { $bitCommit = true; /** @var $this class_root|interface_model */ if (!$this instanceof interface_model) { throw new class_exception("current object must implemented interface_model", class_exception::$level_FATALERROR); } if (!$this->getLockManager()->isAccessibleForCurrentUser()) { $objUser = new class_module_user_user($this->getLockManager()->getLockId()); throw new class_exception("current object is locked by user " . $objUser->getStrDisplayName(), class_exception::$level_ERROR); } if (is_object($strPrevId) && $strPrevId instanceof class_root) { $strPrevId = $strPrevId->getSystemid(); } $this->objDB->transactionBegin(); //current systemid given? if not, create a new record. $bitRecordCreated = false; if (!validateSystemid($this->getSystemid())) { $bitRecordCreated = true; if ($strPrevId === false || $strPrevId === "" || $strPrevId === null) { //try to find the current modules-one if (isset($this->arrModule["modul"])) { $strPrevId = class_module_system_module::getModuleByName($this->getArrModule("modul"), true)->getSystemid(); if (!validateSystemid($strPrevId)) { throw new class_exception("automatic determination of module-id failed ", class_exception::$level_FATALERROR); } } else { throw new class_exception("insert with no previd ", class_exception::$level_FATALERROR); } } if (!validateSystemid($strPrevId) && $strPrevId !== "0") { throw new class_exception("insert with erroneous prev-id ", class_exception::$level_FATALERROR); } //create the new systemrecord //store date-bit temporary $bitDates = $this->bitDatesChanges; $this->createSystemRecord($strPrevId, $this->getStrDisplayName()); $this->bitDatesChanges = $bitDates; if (validateSystemid($this->getStrSystemid())) { //Create the foreign records $objAnnotations = new class_reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass("@targetTable"); if (count($arrTargetTables) > 0) { foreach ($arrTargetTables as $strOneConfig) { $arrSingleTable = explode(".", $strOneConfig); $strQuery = "INSERT INTO " . $this->objDB->encloseTableName(_dbprefix_ . $arrSingleTable[0]) . "\n (" . $this->objDB->encloseColumnName($arrSingleTable[1]) . ") VALUES\n (?) "; if (!$this->objDB->_pQuery($strQuery, array($this->getStrSystemid()))) { $bitCommit = false; } } } if (!$this->onInsertToDb()) { $bitCommit = false; } } else { throw new class_exception("creation of systemrecord failed", class_exception::$level_FATALERROR); } //all updates are done, start the "real" update class_carrier::getInstance()->flushCache(class_carrier::INT_CACHE_TYPE_DBQUERIES); } //new prev-id? if ($strPrevId !== false && $this->getSystemid() != $strPrevId && (validateSystemid($strPrevId) || $strPrevId == "0")) { //validate the new prev id - it is not allowed to set a parent-node as a sub-node of its own child if (!$this->isSystemidChildNode($this->getSystemid(), $strPrevId)) { $this->setStrPrevId($strPrevId); } } //new comment? $this->setStrRecordComment($this->getStrDisplayName()); //Keep old and new status here, status changed event is being fired after record is completely updated (so after updateStateToDb()) $intOldStatus = $this->intOldRecordStatus; $intNewStatus = $this->intRecordStatus; //save back to the database $bitCommit = $bitCommit && $this->updateSystemrecord(); //update ourselves to the database if ($bitCommit && !$this->updateStateToDb()) { $bitCommit = false; } //now fire the status changed event if ($intOldStatus != $intNewStatus && $intOldStatus != -1) { class_core_eventdispatcher::getInstance()->notifyGenericListeners(class_system_eventidentifier::EVENT_SYSTEM_STATUSCHANGED, array($this->getSystemid(), $this, $intOldStatus, $intNewStatus)); } if ($bitCommit) { $this->objDB->transactionCommit(); //unlock the record $this->getLockManager()->unlockRecord(); class_logger::getInstance()->addLogRow("updateObjectToDb() succeeded for systemid " . $this->getSystemid() . " (" . $this->getRecordComment() . ")", class_logger::$levelInfo); } else { $this->objDB->transactionRollback(); class_logger::getInstance()->addLogRow("updateObjectToDb() failed for systemid " . $this->getSystemid() . " (" . $this->getRecordComment() . ")", class_logger::$levelWarning); } //call the recordUpdated-Listeners class_core_eventdispatcher::getInstance()->notifyGenericListeners(class_system_eventidentifier::EVENT_SYSTEM_RECORDUPDATED, array($this, $bitRecordCreated)); class_carrier::getInstance()->flushCache(class_carrier::INT_CACHE_TYPE_DBQUERIES); return $bitCommit; }
/** * Internal helper, generated the query part without the select- and the real where- parts. * * @param string $strTargetClass * * @return string * @throws class_orm_exception */ protected function getQueryBase($strTargetClass = "") { if ($strTargetClass == "") { $strTargetClass = $this->getObjObject(); } $objAnnotations = new class_reflection($strTargetClass); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(class_orm_base::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) == 0) { throw new class_orm_exception("Class " . (is_object($strTargetClass) ? get_class($strTargetClass) : $strTargetClass) . " has no target table", class_exception::$level_ERROR); } $strWhere = ""; $arrTables = array(); foreach ($arrTargetTables as $strOneTable) { $arrOneTable = explode(".", $strOneTable); $strWhere .= "AND system_id=" . $arrOneTable[1] . " "; $arrTables[] = class_carrier::getInstance()->getObjDB()->encloseTableName(_dbprefix_ . $arrOneTable[0]) . " AS " . class_carrier::getInstance()->getObjDB()->encloseTableName($arrOneTable[0]) . ""; } //build the query $strQuery = "FROM " . class_carrier::getInstance()->getObjDB()->encloseTableName(_dbprefix_ . "system_right") . ",\n " . implode(", ", $arrTables) . " ,\n " . class_carrier::getInstance()->getObjDB()->encloseTableName(_dbprefix_ . "system") . " AS system\n LEFT JOIN " . _dbprefix_ . "system_date AS system_date\n ON system_id = system_date_id\n WHERE system_id = right_id\n " . $strWhere . ""; return $strQuery; }
/** * Helper method to resolve the declared action to a real action, so to make list out of listOtherObject. * If possible, the current object-type class (based on the annotation is stored, too. * * @param string $strAutoMatchAction * @param string $strAnnotation * @param string $strActionName * * @return void */ private function autoMatchAction($strAutoMatchAction, $strAnnotation, &$strActionName) { if (uniStrpos($strActionName, $strAutoMatchAction) === 0) { // Set name of current list object $this->setStrCurObjectTypeName(uniStrReplace($strAutoMatchAction, "", $strActionName)); $strActionName = $strAutoMatchAction; $objReflection = new class_reflection($this); $arrAnnotations = $objReflection->getAnnotationValuesFromClass($strAnnotation . $this->getStrCurObjectTypeName()); if (count($arrAnnotations) > 0) { $this->setCurObjectClassName(reset($arrAnnotations)); } else { $this->setCurObjectClassName(null); } } }