_zasobID = (int)$zasobID; $this->_name = ''; $this->_namespace = ''; $this->_rootTableName = ''; $this->_db = 0; // database id zasobu $this->_rootNamespace = ''; $this->_primaryKey = ''; $this->_fields = []; $this->_hasWriteGroupField = false; // TODO: from cache $this->_hasReadGroupField = false; // TODO: from cache $this->_hasOwnerField = false; // TODO: from cache $this->_xsdRestrictions = []; $this->_zasobyInfoFetched = false; } public function getDB() { return $this->_db; } public function getName() { return $this->_name; } public function getNamespace() { return $this->_namespace; } public function getRootNamespace() { return $this->_rootNamespace; } public function getSourceName() { return 'default_db'; } // TODO: ? public function getRootTableName() { return $this->_rootTableName; } public function getPrimaryKeyField() { return $this->_primaryKey; } public function getFieldListByIdZasob() { $this->_fetchInfoFromZasobyIfNeeded(); return $this->getRealFieldListByIdZasob(); } public function getVirtualFieldListByIdZasob() { return []; } public function _fetchInfoFromZasobyIfNeeded() { if (!$this->_zasobyInfoFetched) { $zasobyIds = array_filter( array_map(function ($field) { return (int)$field['idZasob']; }, $this->_fields), function ($id) { return $id > 0; } ); if (!empty($zasobyIds)) { DBG::log("DBG sort fields - ids [".implode(",", $zasobyIds)."]"); $zasobyInfo = DB::getPDO()->fetchAllByKey(" select z.ID, z.DESC_PL, z.OPIS, z.SORT_PRIO from CRM_LISTA_ZASOBOW z where z.ID in(".implode(",", $zasobyIds).") ", 'ID'); DBG::log($zasobyInfo, 'array', "DBG sort fields - zasobyInfo"); $maxSortPrio = 0; array_map(function ($zInfo) use (&$maxSortPrio) { if ($zInfo['SORT_PRIO'] > 0 && $zInfo['SORT_PRIO'] > $maxSortPrio) { $maxSortPrio = $zInfo['SORT_PRIO']; } }, $zasobyInfo); foreach ($this->_fields as $idx => $field) { // $this->_fields[$idx]['name'] = $field['fieldNamespace']; // TODO: BUG query for non existing fields - check if isLocal is used if ($field['idZasob'] > 0 && array_key_exists($field['idZasob'], $zasobyInfo)) { $this->_fields[$idx]['sort_prio'] = $zasobyInfo[ $field['idZasob'] ]['SORT_PRIO']; if (!empty($zasobyInfo[ $field['idZasob'] ]['DESC_PL'])) $this->_fields[$idx]['label'] = $zasobyInfo[ $field['idZasob'] ]['DESC_PL']; if (!empty($zasobyInfo[ $field['idZasob'] ]['OPIS'])) $this->_fields[$idx]['opis'] = $zasobyInfo[ $field['idZasob'] ]['OPIS']; } else { // !$field['idZasob'] => generate sortPrio $this->_fields[$idx]['sort_prio'] = ++$maxSortPrio; } } } $this->_zasobyInfoFetched = true; } usort($this->_fields, array($this, '_sortFieldsCallback')); DBG::log($this->_fields, 'array', "DBG sort fields - sorted \$this->_fields"); } public function _sortFieldsCallback($a, $b) { if ($a['fieldNamespace'] == 'ID') { return -1; } else if ($b['fieldNamespace'] == 'ID') { return 1; } else if ($a['sort_prio'] < $b['sort_prio']) { return -1; } else if ($a['sort_prio'] > $b['sort_prio']) { return 1; } else { return 0; } } public function getXsdTypes() { // @returns [ fieldName => xsdType, ... ] $fields = $this->getFields(); return array_combine( array_map( V::makePick('fieldNamespace'), $fields ), array_map( V::makePick('xsdType'), $fields ) ); } public function getVisibleFieldListByIdZasob() { $this->_fetchInfoFromZasobyIfNeeded(); $fields = $this->getRealFieldListByIdZasob(); $pkField = $this->getPrimaryKeyField(); $cols = array(); foreach ($fields as $kFieldID => $fieldName) { if ($pkField === $fieldName) { $id = $kFieldID; break; } } $cols[$id] = $pkField; // 'ID'; // TODO: why rename primary key field to ID? check JS foreach ($fields as $kFieldID => $fieldName) { if ($pkField === $fieldName) continue; $cols[$kFieldID] = $fieldName; } return $cols; } public function getRealFieldListByIdZasob() { $cols = array(); foreach ($this->getFields() as $field) { if (!$field['isActive']) continue; if (!$field['idZasob']) continue; $cols[ $field['idZasob'] ] = $field['fieldNamespace']; } return $cols; } public function getRealFieldList() { $this->_fetchInfoFromZasobyIfNeeded(); $pkField = $this->getPrimaryKeyField(); $cols = array_merge([ $pkField ], array_filter($this->getLocalFieldList(), function ($fieldName) use ($pkField) { if ($pkField === $fieldName) return false; return true; })); return $cols; } public function getHistItems($id, $params = array()) { DBG::log($params, 'array', "getHistItems({$id}, \$params)"); $sqlPkField = $this->getSqlPrimaryKeyField(); $ret = array(); $sql_tbl = $this->getRootTableName() . "_HIST"; $sql_cols = array_map(function ($fieldName) { return "t.`{$fieldName}`"; }, $this->getRealFieldList()); $sql_cols = implode(", ", $sql_cols); $sql_where = "t.`ID_USERS2`='{$id}'"; $idHist = V::get('ID', 0, $params, 'int'); if ($idHist > 0) { $sql_where .= "\n and t.`ID`='{$idHist}'"; } $paramNotEmptyFlds = V::get('notEmptyFlds', '', $params); if (!empty($paramNotEmptyFlds) && is_array($paramNotEmptyFlds)) { $sqlWhereOr = array(); foreach ($paramNotEmptyFlds as $fldName) { if (array_key_exists($fldName, $this->_cols)) { $sqlWhereOr[] = "t.`{$fldName}`!='N/S;'"; } } if (!empty($sqlWhereOr)) $sql_where .= "\n and (" . implode(" or ", $sqlWhereOr) . ")"; } $histRows = DB::getPDO()->fetchAllByKey(" select {$sql_cols} from {$sql_tbl} as t where {$sql_where} order by ID DESC ", 'ID'); return array_map(function ($row) { $r = (object)$row; $r->_author = $r->A_RECORD_UPDATE_AUTHOR; $r->_created = $r->A_RECORD_UPDATE_DATE; if (!$r->_author || $r->_author == 'N/S;') { $r->_author = $r->A_RECORD_CREATE_AUTHOR; } if (!$r->_created || $r->_created == 'N/S;') { $r->_created = $r->A_RECORD_CREATE_DATE; } return $r; }, $histRows); } public function getFieldIdByName($fieldName) { if (!$fieldName) return null; foreach ($this->getFields() as $field) { if ($fieldName !== $field['name']) continue; if (!$field['idZasob']) continue; return $field['idZasob']; } return null; } public function getFieldType($fieldName) { return null; } // try { // throw new Exception("TODO: AntAclBase::getFieldType({$fieldName})"); // } catch (Exception $e) { // DBG::log($e); // } // $field = $this->_getField($fieldName); // return $field['xsdType']; // } public function getField($idField) { DBG::log($this->getFields(), 'array', "fields"); foreach ($this->getFields() as $field) { if (!$field['isActive']) continue; if (!$field['idZasob']) continue; if ($idField == $field['idZasob']) { return $field; } } return null; } public function getXsdFieldType($fieldName) { $field = $this->_getField($fieldName); return $field['xsdType']; } public function getXsdMaxOccurs($fieldName) { $field = $this->_getField($fieldName); return (int)$field['maxOccurs']; } public function getXsdMinOccurs($fieldName) { $field = $this->_getField($fieldName); return (int)$field['minOccurs']; } public function getAttributesFromZasoby() { return [];// TODO: ... } public function getXsdFieldParam($fieldName, $paramKey) { switch ($paramKey) { case 'enumeration': return $this->getEnumerations($fieldName); } $xsdType = $this->getXsdFieldType($fieldName); $defaultValue = null; if ('enumeration' === $paramKey && 'p5:enum' === $xsdType) $defaultValue = []; if ('maxLength' === $paramKey && 'xsd:string' === $xsdType) $defaultValue = 255; return V::get($paramKey, $defaultValue, $this->getXsdRestrictions($fieldName)); } public function getEnumerations($fieldName) { $restrictions = $this->getXsdRestrictions($fieldName); return V::get('enumeration', [], $restrictions, 'array'); } public function getXsdRestrictions($fieldName) { if (array_key_exists($fieldName, $this->_xsdRestrictions)) return $this->_xsdRestrictions[$fieldName]; $this->_xsdRestrictions[$fieldName] = []; $field = $this->_getField($fieldName); if (!$field['xsdRestrictions']) return []; if (is_string($field['xsdRestrictions']) && '{' === substr($field['xsdRestrictions'], 0, 1)) { $this->_xsdRestrictions[$fieldName] = @json_decode($field['xsdRestrictions'], $assoc = true); } return $this->_xsdRestrictions[$fieldName]; } // public function getXsdFieldParam($fieldName, $paramKey) { // TableAcl // return ($this->_schemaClass) // ? $this->_schemaClass->getFieldParam($fieldName, $paramKey) // : null // ; // } // public function getXsdFieldParam($fieldName, $paramKey) { // SimpleSchema // if (empty($this->_simpleSchema['root'][$fieldName])) return null; // if (empty($this->_simpleSchema['root'][$fieldName]['@@params'])) return null; // if (empty($this->_simpleSchema['root'][$fieldName]['@@params'][$paramKey])) return null; // return $this->_simpleSchema['root'][$fieldName]['@@params'][$paramKey]; // } public function getFieldDefaultValue($fieldName) { // TODO: get dafault value from xsd file - TODO: p5:default attribute // TODO: get from xsd file (acl cache field) // TODO: if not set then: // - 'NULL' for nillable fields // - '0' for xsd:integer, xsd:decimal // - '' else ... return ''; } public function convertObjectFromUserInput($userItem, $type = 'array_by_id', $prefix = 'f') {// TODO: rename / Legacy $item = $this->parseUserItem($userItem, $type = 'array_by_id', $prefix = 'f'); foreach ($item as $fieldName => $value) { $item[$fieldName] = $this->validateAndFixField($fieldName, $value); } DBG::log(['userItem' => $userItem, 'item' => $item], 'array', "after parseUserItem, validateAndFixField"); return $item; } public function parseUserItem($userItem, $type = 'array_by_id', $prefix = 'f') { $item = []; foreach ($this->getFieldListByIdZasob() as $userKey => $fieldName) { if (!array_key_exists("f{$userKey}", $userItem)) continue; $item[$fieldName] = $userItem["f{$userKey}"]; } return $item; } public function validateAndFixField($fieldName, $value) { if (empty($value) && 0 === strlen($value)) {// TODO: fixEmptyValueFromUser return $this->fixFieldEmptyValue($fieldName); } $xsdType = $this->getXsdFieldType($fieldName); switch ($xsdType) { case 'xsd:decimal': return str_replace([',', ' '], ['.', ''], $value); case 'p5:price': return V::convert($value, 'price'); } return $value; } public function fixFieldEmptyValue($fieldName) {// TODO: legacy - TODO: FIX return $this->getFieldDefaultValue($fieldName); // $value = ''; // $xsdType = $this->getXsdFieldType($fieldName); // // $type = $this->getFieldType($fieldName); // TODO: RM // // if (!$type) return ''; // if ('xsd:date' === $xsdType) return $this->getFieldDefaultValue($fieldName); // if ('xsd:integer' === $xsdType) return (int)$this->getFieldDefaultValue($fieldName); // // fix bug when field is unique and is null allowed: change empty string to null // if ($type['null']) { // $value = 'NULL'; // } // // fix bug when field is enum and is set to '0': for php '0' is empty // if (substr($type['type'], 0, 4) == 'enum') {// && $args["f{$fieldID}"] === '0') { // // if (false !== strpos($type['type'], "''")) { // // // enum('', '1','2') // // $value = ''; // // } else if (false !== strpos($type['type'], "'0'")) { // // // enum('0', '1','2') // // $value = '0'; // // } else { // $value = $this->getFieldDefaultValue($fieldName); // // } // } // return $value; } public function isGeomField($fieldName) { $xsdType = $this->getXsdFieldType($fieldName); switch ($xsdType) { case "gml:PolygonPropertyType": case "gml:LineStringPropertyType": case "gml:PointPropertyType": case "p5Type:polygon": case "p5Type:lineString": case "p5Type:point": return true; default: return false; } } public function isEnumerationField($fieldName) { $xsdType = $this->getXsdFieldType($fieldName); if ('p5:enum' === $xsdType) return true; return false; } public function canCreateField($fieldName) { try { $fieldAclInfo = $this->getAclInfo($fieldName); // DBG::log($fieldAclInfo, 'array', "AntAclBase: canReadField({$fieldName})..."); return ($fieldAclInfo['PERM_C'] > 0); } catch (Exception $e) { DBG::log($e); return false; } return false; } public function canReadField($fieldName) { try { if ('A_RECORD_CREATE_DATE' === $fieldName) return true; if ('A_RECORD_CREATE_AUTHOR' === $fieldName) return true; if ('A_RECORD_UPDATE_DATE' === $fieldName) return true; if ('A_RECORD_UPDATE_AUTHOR' === $fieldName) return true; if ($this->getPrimaryKeyField() === $fieldName) return true; $fieldAclInfo = $this->getAclInfo($fieldName); // DBG::log($fieldAclInfo, 'array', "AntAclBase: canReadField({$fieldName})..."); return ($fieldAclInfo['PERM_R'] > 0 || $fieldAclInfo['PERM_V'] > 0 || $fieldAclInfo['PERM_O'] > 0); } catch (Exception $e) { DBG::log($e); return false; } return false; } public function canReadObjectField($fieldName, $object) { try { if ('A_RECORD_CREATE_DATE' === $fieldName) return true; if ('A_RECORD_CREATE_AUTHOR' === $fieldName) return true; if ('A_RECORD_UPDATE_DATE' === $fieldName) return true; if ('A_RECORD_UPDATE_AUTHOR' === $fieldName) return true; if ($this->getPrimaryKeyField() === $fieldName) return true; $fieldAclInfo = $this->getAclInfo($fieldName); // DBG::log([$fieldAclInfo, 'V' => ($fieldAclInfo['PERM_V'] > 0), 'R'=>($fieldAclInfo['PERM_R'] > 0 && $this->canReadRecord($object)), 'O'=>($fieldAclInfo['PERM_O'] > 0 && $this->canReadRecord($object))], 'array', "AntAclBase: canWriteObjectField({$fieldName})..."); if ($fieldAclInfo['PERM_V'] > 0) return true; if ($fieldAclInfo['PERM_R'] > 0 && $this->canReadRecord($object)) return true; if ($fieldAclInfo['PERM_O'] > 0 && $this->canReadRecord($object)) return true; } catch (Exception $e) { DBG::log($e); } return false; } public function canWriteField($fieldName) { try { $fieldAclInfo = $this->getAclInfo($fieldName); // DBG::log($fieldAclInfo, 'array', "AntAclBase: canReadField({$fieldName})..."); if ($fieldAclInfo['PERM_W'] > 0 || $fieldAclInfo['PERM_S'] > 0) return true; } catch (Exception $e) { DBG::log($e); } return false; } public function canWriteObjectField($fieldName, $record) { try { $fieldAclInfo = $this->getAclInfo($fieldName); // DBG::log($fieldAclInfo, 'array', "AntAclBase: canWriteObjectField({$fieldName})..."); DBG::log([$fieldAclInfo, 'S' => $fieldAclInfo['PERM_S'] > 0, 'W'=>$fieldAclInfo['PERM_W'], 'canWrite'=>$this->canWriteRecord($record), $record], 'array', "AntAclBase: canWriteObjectField({$fieldName})..."); if ($fieldAclInfo['PERM_S'] > 0) return true; if ($fieldAclInfo['PERM_W'] > 0 && $this->canWriteRecord($record)) return true; } catch (Exception $e) { DBG::log($e); } return false; } public function getAclInfo($fieldName = null) { static $_aclInfo = []; // [ fieldName => [ id => {idZasob}, perms => 'RWX...' ] // TODO: , sort_prio => {SORT_PRIO}, label => {CELL_LABEL} ] if (!array_key_exists($this->getID(), $_aclInfo)) { $_aclInfo[ $this->getID() ] = []; $fieldsConfig = User::getAcl()->getPermsForTable($this->getID()); // @returns [ permInfo group by ID_CELL ]; permInfo = [ ID_CELL, CELL_NAME, CELL_LABEL, SORT_PRIO, PERM_R, PERM_W, PERM_... ] // DBG::log($fieldsConfig, 'array', "AntAclBase: User::getAcl()->getPermsForTable(".$this->getID().");"); // $this->initFieldsFromConfig($fieldsConfig); $permCols = [ 'PERM_R', 'PERM_W', 'PERM_X', 'PERM_C', 'PERM_S', 'PERM_O', 'PERM_V', 'PERM_E' ]; foreach ($fieldsConfig as $row) { $nameField = $row['CELL_NAME']; $_aclInfo[ $this->getID() ][ $nameField ] = [ 'idZasob' => $row['ID_CELL'], 'label' => $row['CELL_LABEL'], 'sort_prio' => $row['SORT_PRIO'], ]; foreach ($permCols as $colPerm) $_aclInfo[ $this->getID() ][ $nameField ][ $colPerm ] = (int)$row[ $colPerm ]; } } if ($fieldName && !array_key_exists($fieldName, $_aclInfo[ $this->getID() ])) { throw new Exception("Field not exists or missing access '{$fieldName}'"); } return ($fieldName) ? $_aclInfo[ $this->getID() ][ $fieldName ] : $_aclInfo[ $this->getID() ]; } public function hasFieldPerm($fieldID, $perm) { // TODO: legacy $field = $this->getField($fieldID); if (!$field) return false; try { $fieldAclInfo = $this->getAclInfo($fieldName); DBG::log($fieldAclInfo, 'array', "AntAclBase: hasFieldPerm({$fieldName})..."); if (!array_key_exists("PERM_{$perm}", $fieldAclInfo)) return false; return ($fieldAclInfo["PERM_{$perm}"] > 0); } catch (Exception $e) { DBG::log($e); } return false; } public function isAllowed($fieldID, $taskPerm, $record = null) {// TODO: legacy - replace with canWriteField, canReadField, canWriteObjectField, canReadObjectField, canCreateField $field = $this->getField($fieldID); if (!$field) return false; $fieldName = $field['name']; switch ($taskPerm) { case 'C': return $this->canCreateField($fieldName); case 'R': return ($record) ? $this->canReadObjectField($fieldName, $record) : $this->canReadField($fieldName); case 'W': return ($record) ? $this->canWriteObjectField($fieldName, $record) : $this->canWriteField($fieldName); default: throw new Exception("Not Implemented isAllowed perm '{$taskPerm}'"); } $adminFields = array(); $adminFields[] = $this->getPrimaryKeyField(); $adminFields[] = 'A_RECORD_CREATE_DATE'; $adminFields[] = 'A_RECORD_CREATE_AUTHOR'; $adminFields[] = 'A_RECORD_UPDATE_DATE'; $adminFields[] = 'A_RECORD_UPDATE_AUTHOR'; if ($taskPerm == 'R' && in_array($fieldName, $adminFields)) return true; if ($taskPerm == 'W' && in_array($fieldName, $adminFields)) return false; // check perm: allow 'RS', 'WS' - can R/W field even if cant read record // check 'O' - can read field even if cant read field but can read record DBG::log([ 'record' => $record, 'canReadRecord' => $this->canReadRecord($record), 'hasFieldPerm(O) || canWriteRecord'=>'"'.$this->hasFieldPerm($fieldID, 'O').'" || "'.$this->canReadRecord($record).'"', 'hasFieldPerm(S)'=>'"'.$this->hasFieldPerm($fieldID, 'S').'"', 'hasFieldPerm(V)'=>'"'.$this->hasFieldPerm($fieldID, 'V').'"', ], 'array', "isAllowed({$fieldName}[{$fieldID}], {$taskPerm})"); if (!$this->hasFieldPerm($fieldID, $taskPerm)) { if ($taskPerm == 'R' && $this->hasFieldPerm($fieldID, 'V')) { return true; } else if ($taskPerm == 'R' && $record && $this->hasFieldPerm($fieldID, 'O') && ($this->canReadRecord($record) || $this->canWriteRecord($record)) ) { return true;// 'WO' or 'CO' } return false; } // check 'R' - require can read record, or V - Super View if ($taskPerm == 'R') { if ($this->canReadRecord($record) || $this->hasFieldPerm($fieldID, 'V')) { return true; } else { return false; } } // // 'C' and 'W' require colType // $colType = $this->getFieldTypeById($fieldID); // if (!$colType) { // return false; // } if ($taskPerm == 'W') { if ($record) { if(V::get('DBG_ACL', '', $_REQUEST) > 1){echo '(Field: '.$fieldID.', canWriteRecord: ' . $this->canWriteRecord($record) . ' || (hasFieldPerm(S): ' . $this->hasFieldPerm($fieldID, 'S') . ' && hasFieldPerm(W): ' . $this->hasFieldPerm($fieldID, 'W') . '))';} return ($this->canWriteRecord($record) || $this->hasFieldPerm($fieldID, 'S')); } } return true; } public function getFields() { // TODO: conflict return structure with TableAcl if (empty($this->_fields)) { // TODO: fetch fields from DB // Lib::loadClass('SchemaFactory'); // $objectStorage = SchemaFactory::loadDefaultObject('SystemObject'); // $item = $objectStorage->getItem($namespace, [ // 'propertyName' => '*,field' // ]); } $fields = array_filter($this->_fields, function ($field) { return ($field['isActive']); }); return array_map(function ($field) { $field['name'] = $field['fieldNamespace']; return $field; }, $fields); } public function _getField($fieldName) { foreach ($this->getFields() as $field) { if ($fieldName === $field['fieldNamespace']) return $field; } throw new Exception("Field not found '{$this->_namespace}/{$fieldName}'"); } public function getSqlPrimaryKeyField() { return $this->_primaryKey; } public function getSqlFieldName($fieldName) { $field = $this->_getField($fieldName); if ($field['isLocal']) return $field['fieldNamespace']; return $fieldName; // TODO: throw new Exception("Field is not local"); } public function getTotal($params = []) { return $this->buildQuery($params)->getTotal(); } public function getItems($params = []) { return $this->buildQuery($params)->getItems(); } public function getItem($primaryKey, $params = []) { return $this->buildQuery($params)->getItem($primaryKey); } public static function buildInstance($idZasob, $conf = []) { static $_cache; if (!$_cache) $_cache = array(); if (array_key_exists($idZasob, $_cache)) { return $_cache[$idZasob]; } if (empty($conf)) throw new Exception("Brak danych konfiguracyjnych do obiektu ant nr {$idZasob}"); DBG::log($conf, 'array', 'AntAclBase::buildInstance $conf'); $acl = new AntAclBase($idZasob); $acl->_name = $conf['name']; $acl->_rootTableName = $conf['_rootTableName']; $acl->_db = $conf['idDatabase']; $acl->_namespace = $conf['namespace']; $acl->_rootNamespace = str_replace('__x3A__', '/', $conf['nsPrefix']); $acl->_fields = $conf['field']; // TODO: lazyLoading - use getFields() in all functions - TODO: use ACL::getObjectFields $acl->_primaryKey = (!empty($conf['primaryKey'])) ? $conf['primaryKey'] : 'ID'; // $conf['primaryKey']; $acl->_hasWriteGroupField = $conf['hasWriteGroupField']; $acl->_hasReadGroupField = $conf['hasReadGroupField']; $acl->_hasOwnerField = $conf['hasOwnerField']; $_cache[$idZasob] = $acl; return $_cache[$idZasob]; } public function buildQuery($params = array()) { Lib::loadClass('AclQueryFeatures'); return new AclQueryFeatures($this, $params); } public function getInstanceList() { $rootTableName = $this->_rootTableName; return array_map(function ($row) use ($rootTableName) { return $row['name']; }, SchemaFactory::loadDefaultObject('SystemObject')->getItems([ 'propertyName' => 'name', // TODO: SystemObject fix propertyName 'f__rootTableName' => "={$rootTableName}", 'f__type' => "=AntAcl", 'f_isObjectActive' => "=1", ]) ); } public function getLocalFieldList() { return array_map(function ($field) { return $field['fieldNamespace']; }, array_filter($this->getFields(), function ($field) { return ($field['isLocal']); })); } public function isLocalField($fieldName) { return $this->_getField($fieldName)['isLocal']; } public function init($force = false) { } public function isInitialized($force = false) { return true; } public function addItem($itemTodo) { if (is_object($itemTodo)) { $itemTodo = (array)$itemTodo; } else if (!is_array($itemTodo)) { throw new HttpException('Item is not array', 400); } // from convertObjectFromUserInput - fixEmptyValueFromUser $item = array(); $fields = $this->getFieldListByIdZasob(); foreach ($fields as $kID => $vFieldName) { if (!$this->isAllowed($kID, 'C')) { continue; } if (isset($itemTodo[$vFieldName])) { $value = $itemTodo[$vFieldName]; if (empty($value) && strlen($value) == 0) {// fix bug in input type date and value="0000-00-00" $value = $this->fixEmptyValueFromUser($kID); } $item[$vFieldName] = $value; } } {// add DefaultAclGroup if no create perms ('C') $defaultAclGroup = User::getDefaultAclGroup(); if ($defaultAclGroup) { $permFields = array('A_ADM_COMPANY', 'A_CLASSIFIED'); foreach ($permFields as $permFldName) { $permFldId = $this->getFieldIdByName($permFldName); if (0 == $permFldId || !$this->isAllowed($permFldId, 'C')) { $item[$permFldName] = $defaultAclGroup; } } } } DBG::log($item, 'array', "insert \$item"); $idItem = DB::getPDO()->insert($this->getRootTableName(), array_merge($item, [ 'A_RECORD_CREATE_DATE' => 'NOW()', 'A_RECORD_CREATE_AUTHOR' => User::getLogin(), ])); if ($idItem) { DB::getPDO()->insert($this->getRootTableName() . '_HIST', array_merge($item, [ 'ID_USERS2' => $idItem, 'A_RECORD_CREATE_DATE' => 'NOW()', 'A_RECORD_CREATE_AUTHOR' => User::getLogin(), ])); } return $idItem; } public function updateItem($itemPatch) { if (is_object($itemPatch)) { $itemPatch = (array)$itemPatch; } else if (!is_array($itemPatch)) { throw new HttpException('Item patch is not array', 400); } if (empty($itemPatch)) { DBG::log("Item patch is empty - after validation"); // throw new Exception('Item patch is empty'); return 0;// nothing to change } $primaryKeyField = $this->getPrimaryKeyField(); if (empty($itemPatch[$primaryKeyField])) throw new HttpException("Item Primary Key not set!", 400); $primaryKey = $itemPatch[$primaryKeyField]; $itemOld = (array)$this->getItem($primaryKey); if (!$itemOld) throw new HttpException("Item not exists!", 404); if (!$this->canWriteRecord($itemOld) && !$this->hasPermSuperWrite()) throw new HttpException("Brak dostępu do rekordu", 403); // $itemPatch from user input to $validPatch $validPatch = array(); DBG::log($itemPatch, 'array', "Item patch - before validation"); foreach ($this->getFieldListByIdZasob() as $kID => $fieldName) { if (!array_key_exists($fieldName, $itemPatch)) continue; if (!$this->isAllowed($kID, 'W', $itemOld)) continue; // default value for perms 'W' without 'R' is '*****' if (!$this->isAllowed($kID, 'R', $itemOld) && '*****' == $itemPatch[$fieldName]) continue; $value = $itemPatch[$fieldName]; if (empty($itemPatch[$fieldName]) && strlen($itemPatch[$fieldName]) == 0) {// fix bug in input type date and value="0000-00-00" $value = $this->fixFieldEmptyValue($fieldName); } if ($value != $itemOld[$fieldName]) { $validPatch[$fieldName] = $value; } } DBG::log($validPatch, 'array', "Item patch - after validation"); if (empty($validPatch)) { DBG::log("Item patch is empty - after validation"); // throw new Exception('Item patch is empty'); return 0;// nothing to change } DBG::log($validPatch, 'array', "TODO: EDIT valid item patch"); $affected = DB::getPDO()->update($this->getRootTableName(), $primaryKeyField, $primaryKey, array_merge( $validPatch, [ 'A_RECORD_UPDATE_DATE' => 'NOW()', 'A_RECORD_UPDATE_AUTHOR' => User::getLogin(), ] )); if ($affected) { $affected += $this->saveUpdateHist(array_merge( $validPatch, [ 'ID_USERS2' => $primaryKey, 'A_RECORD_UPDATE_DATE' => 'NOW()', 'A_RECORD_UPDATE_AUTHOR' => User::getLogin(), ] )); } return $affected; } public function saveUpdateHist($histPatch) { try { $idHist = DB::getPDO()->insert($this->getRootTableName() . '_HIST', $histPatch); } catch (Exception $e) { DBG::log($e); } } public function hasWriteGroupField() { return $this->_hasWriteGroupField; } public function hasReadGroupField() { return $this->_hasReadGroupField; } public function hasOwnerField() { return $this->_hasOwnerField; } function getSpecialFilters() { $fltrs = array(); $namespace = $this->getNamespace(); $availableBackRefs = array_map(function($instance) { $exNs = explode('/', $instance['namespace']); $label = end($exNs); return [ 'id' => $instance['idInstance'], 'namespace' => $instance['namespace'], 'label' => $label, ]; }, ACL::getBackRefList($namespace)); // [ 'id' => 41, 'namespace' => "default_db/TEST_PERMS/TestPermsAnt", 'label' => "TestPermsAnt" ], DBG::log($availableBackRefs, 'array', "\$availableBackRefs"); $availableChildRefs = []; // TODO: ? show relation to child objects $availableChildRefs = array_map(function($instance) { $exNs = explode('/', $instance['namespace']); $label = end($exNs); return [ 'id' => $instance['idInstance'], 'namespace' => $instance['namespace'], 'label' => $label, ]; }, ACL::getRefList($namespace)); DBG::log($availableChildRefs, 'array', "\$availableChildRefs"); if (!empty($availableBackRefs) || !empty($availableChildRefs)) { $fltrs['Relations'] = (object)[ 'type' => 'RELATIONS', 'icon' => 'glyphicon glyphicon-random', 'label' => 'Relacje', 'availableBackRefs' => $availableBackRefs, 'availableChildRefs' => $availableChildRefs, ]; } return $fltrs; } function parseSpecialFilter($filter, $value) { // @return string | NULL if ('Ref_From_' === substr($filter, 0, strlen('Ref_From_'))) { return $this->parseSpecialFilterRefFrom(substr($filter, strlen('Ref_From_')), $value); } if ('Ref_To_' === substr($filter, 0, strlen('Ref_To_'))) { return $this->parseSpecialFilterRefTo(substr($filter, strlen('Ref_To_')), $value); } throw new Exception("Not Implemented special filter '{$filter}={$value}' "); } function parseSpecialFilterRefFrom($idInstance, $primaryKey) { // @return string | NULL $sqlPkField = $this->getSqlPrimaryKeyField(); $parentNamespace = ACL::getInstanceNamespaceById($idInstance); $refTable = ACL::getRefTable($parentNamespace, Api_WfsNs::toTypeName($this->getNamespace()) ); $sqlParentPk = DB::getPDO()->quote($primaryKey); return " t.{$sqlPkField} in ( select `{$refAlias}`.REMOTE_PRIMARY_KEY from `{$refTable}` `{$refAlias}` where `{$refAlias}`.PRIMARY_KEY = {$sqlParentPk} ) "; } function parseSpecialFilterRefTo($idInstance, $primaryKey) { // @return string | NULL $sqlPkField = $this->getSqlPrimaryKeyField(); $childNamespace = ACL::getInstanceNamespaceById($idInstance); $refTable = ACL::getRefTable($this->getNamespace(), Api_WfsNs::toTypeName($childNamespace) ); $sqlChildRefPk = DB::getPDO()->quote($primaryKey); return " t.{$sqlPkField} in ( select refTable.PRIMARY_KEY from `{$refTable}` refTable where refTable.REMOTE_PRIMARY_KEY = {$sqlChildRefPk} ) "; } }