DB zasob ID * [name] => Table name * [opis] => Table opis * [fields] => array( * [$fieldID] => array( * [name] => name * [perms] => perms (FORM_TREAT) * [opis] => opis * ) * ) * [types] => array( * [$fieldID] => array( * [type] => type * [null] => bool * [default] => default value * ) * ) * ); */ class TableAcl extends Core_AclBase { public $_rootTableName = null; public $_zasobID = ''; public $_db = ''; public $_name = ''; public $_label = ''; public $_opis = ''; public $_executed_fieldsInit = null; public $_fields = array(); public $_types = array(); public $_virtualFieldsIdList = array(); public $_schemaLoaded = false; public function __construct($zasobID) { $this->_zasobID = $zasobID; } public function getNamespace() { return 'default_db/' . $this->getName(); } public function getRootNamespace() { return 'default_db/' . $this->getName(); } public function getSourceName() { return 'default_db'; } public function getName() { return $this->_name; } public function getRootTableName() { if (empty($this->_name)) return null;// throw new Exception("Table name not defined"); if ($this->_rootTableName) return $this->_rootTableName; if (!$this->_db) return null;// throw new Exception("Database not defined in table {$this->_zasobID}"); if (DB::getPDO($this->_db)->getZasobId() === DB::getPDO()->getZasobId()) { $dbName = DB::getPDO($this->_db)->getDatabaseName(); $this->_rootTableName = DB::getPDO()->fetchValue(" select t.TABLE_NAME from `information_schema`.`TABLES` t where t.TABLE_SCHEMA = '{$dbName}' and t.TABLE_NAME LIKE '{$this->_name}' "); if (!$this->_rootTableName) return null;// throw new Exception("Table '{$this->_name}' not exists!"); } else { $this->_rootTableName = $this->_name; // TODO: fix for Postgres } DBG::log("TableAcl({$this->_zasobID})->getRootTableName (\$this->_name='{$this->_name}', \$this->_rootTableName='{$this->_rootTableName}')"); if ($this->_rootTableName != $this->_name) { if ($this->_zasobID) { $affected = DB::getPDO()->update('CRM_LISTA_ZASOBOW', 'ID', $this->_zasobID, [ 'DESC' => $this->_rootTableName ]); DBG::log("TableAcl({$this->_zasobID})->getRootTableName fixed zasob table name (\$affected={$affected})"); } $this->_name = $this->_rootTableName; $this->save(); } return $this->_rootTableName; } public function getID() { return $this->_zasobID; } public function getSqlPrimaryKeyField() { return $this->getPrimaryKeyField(); } // TODO: read from root object schema (_rootTableName) public function setName($name) {// TODO: used only by setNameByTableId DBG::log("setName('{$name}')"); $this->_name = $name; } public function setOpis($opis) { $this->_opis = $opis; } public function getOpis() { return $this->_opis; } public function setLabel($label) { $this->_label = $label; } public function getLabel() { return $this->_label; } public function setNameByTableId($tableID) { //used for init without knowing table name $db = DB::getDB(); $sql = "select `DESC` from CRM_LISTA_ZASOBOW where ID={$tableID} and `TYPE`='TABELA'"; $res = $db->query($sql); $res_ = $db->fetch($res); //DEBUG_S(-3,'setNameByTableId',$res_,__FILE__,__FUNCTION__,__LINE__); self::setName($res->DESC); } public function getRawOpis() { $opis = $this->_opis; if (!$opis) return $this->getRawLabel(100); $opis = strip_tags($opis); return $opis; } public function getRawLabel($posLimit = 20) { // TODO: moved to P5Menu $label = $this->_label; if (empty($label) && !empty($this->_opis)) { $label = $this->_opis; if (mb_strlen($this->_opis) > $posLimit) { $pos = strpos($this->_opis, ' - '); if ($pos > $posLimit || $pos < 5) { $pos = $posLimit; $label = mb_substr($this->_opis, 0, $posLimit, 'utf-8') . '...'; } else { $label = mb_substr($this->_opis, 0, $pos, 'utf-8'); } } } if (empty($label)) { $label = $this->_name; } return $label; } public function getShortLabel($posLimit = 20) { $shortLabel = $this->getRawLabel($posLimit); $opis = $this->_opis; $shortLabel = '' . $shortLabel . ''; return $shortLabel; } public function getLongLabel($posLimit = 30) { // TODO: RMME $longLabel = $this->getRawLabel($posLimit); $opis = $this->_opis; if ($longLabel != $this->_name) { $longLabel .= ' ' . $this->_name . ''; } $longLabel = '' . $longLabel . ''; return $longLabel; } public function getLongRawLabel($posLimit = 30) { $longLabel = $this->getRawLabel($posLimit); $opis = $this->_opis; if ($longLabel != $this->_name) { $longLabel .= ' ' . $this->_name; } return $longLabel; } public function setDB($db) { $this->_db = $db; } public function getDB() { return $this->_db; } public function addField($fieldID, $name, $opis, $sort_prio, $label = '') { $field = array(); $field['name'] = $name; $field['perms'] = ''; $field['opis'] = $opis; $field['sort_prio'] = $sort_prio; $field['label'] = $label; $this->_fields[$fieldID] = $field; } public function getTableDbId($tableID) { return $this->_db; } public function getField($fieldID) { return $this->getFields()[$fieldID]; } public function hasFieldById($fieldID) { return array_key_exists($fieldID, $this->getFields()); } public function getFields() { $this->fieldsInit(); $types = $this->_types; return array_map(function ($field) use ($types) { return array_merge($field, [ 'fieldNamespace' => $field['name'], 'isLocal' => array_key_exists($field['name'], $types), ]); }, $this->_fields); } public function setFieldPerms($fieldID, $perms) { if (array_key_exists($fieldID, $this->getFields())) { $this->_fields[$fieldID]['perms'] .= $perms; } } public function getFieldPerms($fieldID) { if (array_key_exists($fieldID, $this->getFields())) { $perms = V::get('perms', '', $this->_fields[$fieldID]); if ($perms) { return implode(',', array_unique(str_split($perms))); } } return ''; } public function hasFieldPerm($fieldID, $perm) {// TODO: legacy if (array_key_exists($fieldID, $this->getFields())) { if (false !== strpos($this->_fields[$fieldID]['perms'], $perm)) { return true; } return false; } return false; } public function getFieldIdByName($fieldName) { $fieldID = 0; if (empty($fieldName)) { return; } foreach ($this->getFields() as $kID => $vField) { if ($vField['name'] == $fieldName) { $fieldID = $kID; } } return $fieldID; } public function hasEditPerms() { foreach ($this->getFields() as $kFldID => $vFld) { if ($this->hasFieldPerm($kFldID, 'W')) return true; if ($this->hasFieldPerm($kFldID, 'C')) return true; if ($this->hasFieldPerm($kFldID, 'S')) return true; } return false; } public function hasSuperAccessPerms() { foreach ($this->getFields() as $kFldID => $vFld) { if ($this->hasFieldPerm($kFldID, 'S')) { return true; } else if ($this->hasFieldPerm($kFldID, 'V')) { return true; } } return false; } public function hasPermSuperWrite() { foreach ($this->getFields() as $kFldID => $vFld) { if ($this->hasFieldPerm($kFldID, 'S')) { return true; } } return false; } /** * @param $taskPerm - 'C', 'W', 'R' */ public function isAllowed($fieldID, $taskPerm, $record = null) {// TODO: legacy - replace with canWriteField, canReadField, canWriteObjectField, canReadObjectField, canCreateField if (!in_array($taskPerm, array('C', 'W', 'R'))) { return false; } $adminFields = array(); $adminFields[] = 'ID'; $adminFields[] = 'A_RECORD_CREATE_DATE'; $adminFields[] = 'A_RECORD_CREATE_AUTHOR'; $adminFields[] = 'A_RECORD_UPDATE_DATE'; $adminFields[] = 'A_RECORD_UPDATE_AUTHOR'; $fieldName = $this->getFields()[$fieldID]['name']; if ($taskPerm == 'R' && in_array($fieldName, $adminFields)) { return true; } // 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 if(V::get('DBG_ACL', '', $_REQUEST) > 1){ echo'
 (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r(array('Field'=>$fieldID.'('.$fieldName.')'
				,'taskPerm'=>$taskPerm
				,'fieldPerms'=>V::get('perms', null, V::get($fieldID, null, $this->_fields))
				,'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').'"'
			));echo'
'; } 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 canCreateField($fieldName) { $idZasob = $this->getFieldIdByName($fieldName); return ($idZasob && $this->hasFieldPerm($idZasob, $taskPerm = 'C')); } public function canReadField($fieldName) { $idZasob = $this->getFieldIdByName($fieldName); // DBG::log($this->_fields[$idZasob], 'array', "canReadField({$fieldName})"); if (!$idZasob) return false; if ('ID' == $fieldName) return true; 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->hasFieldPerm($idZasob, $taskPerm = 'R')) return true; if ($this->hasFieldPerm($idZasob, $taskPerm = 'V')) return true; if ($this->hasFieldPerm($idZasob, $taskPerm = 'O')) return true; // TODO: has 'O' ? @see canReadObjectField return false; } public function canReadObjectField($fieldName, $record) { // if (!$this->canReadField($fieldName)) return false; if ('ID' == $fieldName) return true; 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 (!$record) { if(V::get('DBG_ACL', '', $_REQUEST) > 2){echo'
canReadObjectField('.$fieldName.', $record) - record not set - return false (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): '.var_export($record, true).'
';} return false; } $idZasob = $this->getFieldIdByName($fieldName); if (!$idZasob) { if(V::get('DBG_ACL', '', $_REQUEST) > 2){echo'
canReadObjectField('.$fieldName.', $record) - $idZasob not set - return false (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): '.var_export($record, true).'
';} return false; } if (!$this->hasFieldPerm($idZasob, $taskPerm = 'R')) { if ($this->hasFieldPerm($idZasob, 'V')) return true; return ($this->hasFieldPerm($idZasob, 'O') && ($this->canReadRecord($record) || $this->canWriteRecord($record)));// 'WO' or 'CO' } return ($this->canReadRecord($record) || $this->hasFieldPerm($idZasob, 'V'));// 'R' require } public function canWriteField($fieldName) { $idZasob = $this->getFieldIdByName($fieldName); if (!$idZasob) return false; return $this->hasFieldPerm($idZasob, $taskPerm = 'W'); } public function canWriteObjectField($fieldName, $record) { if (!$this->canWriteField($fieldName)) return false; $idZasob = $this->getFieldIdByName($fieldName); if (!$idZasob) return false; if(V::get('DBG_ACL', '', $_REQUEST) > 1){echo '(Field: "'.$fieldName.'" ['.$idZasob.'], canWriteRecord: ' . $this->canWriteRecord($record) . ' || (hasFieldPerm(S): ' . $this->hasFieldPerm($idZasob, 'S') . ' && hasFieldPerm(W): ' . $this->hasFieldPerm($idZasob, 'W') . '))';} return ($this->canWriteRecord($record) || $this->hasFieldPerm($idZasob, 'S')); } /** * @param $taskPerm - 'C', 'W' */ public function getFormItem($taskPerm, $fieldID, $fName, $fValue, $params = array(), $record = null) { $out = ''; if (!$this->isAllowed($fieldID, $taskPerm, $record)) { if ($taskPerm == 'R') throw new Exception("Brak uprawnień do odczytu"); else if ($taskPerm == 'W') throw new Exception("Brak uprawnień do zapisu"); else throw new Exception("Brak uprawnień do tego pola ({$taskPerm})"); } $colName = $this->getFields()[$fieldID]['name']; if ($colName == 'ID') return; $colType = $this->getFieldTypeById($fieldID); if (!$colType) throw new Exception("Error - unknown type"); $item = array(); $item['htmlType'] = ''; $item['value'] = $fValue; $item['canRead'] = $this->isAllowed($fieldID, 'R', $record); $item['canWrite'] = $this->isAllowed($fieldID, 'W', $record); $item['rawColType'] = $colType; return $item; $html = new stdClass(); $html->_params = array(); $html->tag = 'input'; $html->cnt = ''; $html->attrs = array(); $html->attrs['id'] = $fName; $html->attrs['name'] = $fName; $html->attrs['type'] = 'text'; $html->attrs['value'] = htmlspecialchars($fValue); if (isset($params['tabindex'])) { $html->attrs['tabindex'] = $params['tabindex']; } if (!$this->hasFieldPerm($fieldID, $taskPerm)) { $html->attrs['disabled'] = 'disabled'; } $maxGrid = V::get('maxGrid', 10, $params); if (substr($colType['type'], 0, 3) == 'int' || substr($colType['type'], 0, 7) == 'tinyint' || substr($colType['type'], 0, 8) == 'smallint' || substr($colType['type'], 0, 6) == 'bigint' ) { //$h->Type_value = (int)str_replace(array(' ','(',')'), '', substr($h->Type, 4)); $html->attrs['type'] = 'number'; $html->attrs['class'][] = 'input-small'; } else if (substr($colType['type'], 0, 6) == 'double') { $html->attrs['type'] = 'text'; $html->attrs['class'][] = 'input-small'; } else if (substr($colType['type'], 0, 7) == 'decimal') { $html->attrs['type'] = 'text'; $html->attrs['class'][] = 'input-small'; } else if (substr($colType['type'], 0, 7) == 'varchar' || substr($colType['type'], 0, 4) == 'char' ) { //$h->Type_value = (int)str_replace(array(' ','(',')'), '', substr($h->Type, 8)); $html->attrs['type'] = 'text'; $maxLength = (int)str_replace(array(' ','(',')'), '', substr($colType['type'], strpos($colType['type'], '(') + 1, -1)); if ($maxLength > 0) { $html->attrs['maxlength'] = $maxLength; } $valLength = strlen($fValue); if (isset($params['widthClass'])) { if ($params['widthClass'] == 'inside-modal') { $html->attrs['style'] = 'width:98%;'; } else { $html->attrs['style'] = 'width:98%;'; } } else { /* if ($maxLength < 11) { $html->attrs['class'][] = 'span2'; } else if ($maxLength < 31) { $html->attrs['class'][] = 'span5'; } else if ($maxLength < 51) { $html->attrs['class'][] = (8 <= $maxGrid)? 'span8' : "span{$maxGrid}"; } else if ($maxLength < 101) { $html->attrs['class'][] = (10 <= $maxGrid)? 'span10' : "span{$maxGrid}"; } else { $html->attrs['class'][] = (12 <= $maxGrid)? 'span12' : "span{$maxGrid}"; } */ } if ($maxLength > 255) {// Fix for long varchar - use textarea $html->tag = 'textarea'; $html->cnt = htmlspecialchars($fValue); $html->attrs['rows'] = '3'; unset($html->attrs['type']); unset($html->attrs['value']); } } else if (substr($colType['type'], 0, 4) == 'date') { $testDatePicker = true; if ($testDatePicker) { $html->attrs['type'] = 'text'; $html->_params[] = 'date'; if (substr($colType['type'], 0, 8) == 'datetime') { $html->attrs['class'][] = 'se_type-datetime';// datetimepicker'; $html->attrs['data-format'] = 'yyyy-MM-dd hh:mm'; $html->attrs['maxlength'] = 19; } else { $html->attrs['class'][] = 'se_type-date';// datetimepicker'; $html->attrs['maxlength'] = 10; } if (substr($html->attrs['value'], 0, 10) == '0000-00-00') { $html->attrs['value'] = ''; } } else { $html->attrs['type'] = 'date'; } } else if ($colType['type'] == 'time') { $testDatePicker = true; if ($testDatePicker) { $html->attrs['type'] = 'text'; $html->_params[] = 'time'; $html->attrs['class'][] = 'se_type-time';// datetimepicker'; $html->attrs['data-format'] = 'hh:mm:ss'; $html->attrs['maxlength'] = 8; if (substr($html->attrs['value'], 0, 8) == '00:00:00') { $html->attrs['value'] = ''; } } else { $html->attrs['type'] = 'time'; } } else if ($colType['type'] == 'timestamp') { $testDatePicker = true; if ($testDatePicker) { $html->attrs['type'] = 'text'; $html->_params[] = 'date'; $html->attrs['class'][] = 'se_type-datetime';// datetimepicker'; $html->attrs['data-format'] = 'yyyy-MM-dd hh:mm'; $html->attrs['maxlength'] = 19; if (substr($html->attrs['value'], 0, 10) == '0000-00-00') { $html->attrs['value'] = ''; } } else { $html->attrs['type'] = 'date'; } } else if (substr($colType['type'], 0, 4) == 'enum') { unset($html->attrs['type']); unset($html->attrs['value']); $html->tag = 'select'; $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType['type'], 5))); $selValue = $fValue; if (empty($selValue) && $selValue !== '0' && !empty($colType['default'])) { if ($taskPerm == 'C') { $selValue = $colType['default']; } else if ($taskPerm == 'W' && $this->isAllowed($fieldID, 'R', $record)) { $selValue = $colType['default']; } } $html->cnt .= ''; if (!empty($selValue) && !in_array($selValue, $values)) { $html->cnt .= ''; } foreach ($values as $val) { $sel = ($selValue == $val)? ' selected="selected"' : ''; $html->cnt .= ''; } } else if (substr($colType['type'], 0, 4) == 'text' || substr($colType['type'], 0, 8) == 'tinytext' || substr($colType['type'], 0, 10) == 'mediumtext' || substr($colType['type'], 0, 8) == 'longtext' ) { $html->tag = 'textarea'; $html->cnt = htmlspecialchars($fValue); if (isset($params['widthClass'])) { if ($params['widthClass'] == 'inside-modal') { $html->attrs['style'] = 'width:98%;'; } else { $html->attrs['style'] = 'width:98%;'; } } else { //$html->attrs['class'][] = (8 <= $maxGrid)? 'span8' : "span{$maxGrid}"; } $html->attrs['rows'] = '3'; unset($html->attrs['type']); unset($html->attrs['value']); } else if ('polygon' == $colType['type']) { return '...'; }// Wielokąt else if ('multipolygon' == $colType['type']) { return '...'; }// Zbiór wielokątów else if ('linestring' == $colType['type']) { return '...'; }// Krzywa z interpolacji liniowej pomiędzy punktami else if ('point' == $colType['type']) { return '...'; }// Punkt w przestrzeni 2-wymiarowej else if ('geometry' == $colType['type']) { return '...'; }// Typy, które mogą przechowywać geometrię dowolnego typu else if ('multipoint' == $colType['type']) { return '...'; }// Zbiór punktów else if ('multilinestring' == $colType['type']) { return '...'; }// Zbiór krzywych z interpolacji liniowej pomiędzy punktami else if ('geometrycollection' == $colType['type']) { return '...'; }// Zbiór obiektów geometrycznych dowolnego typu else throw new Exception("unknown Type '{$colType['type']}'"); $html->attrs['class'][] = 'form-control'; $attrsOut = array(); foreach ($html->attrs as $k => $v) { if (is_array($v)) $v = implode(' ', $v); $attrsOut[] = "{$k}=\"{$v}\""; } if (in_array($html->tag, array('select', 'textarea'))) { $out .= '<' . $html->tag . '' . (($attrsOut)? ' ' . implode(' ', $attrsOut) : '') . '>'; $out .= $html->cnt; $out .= 'tag . '>'; } else { $out .= '<' . $html->tag . '' . (($attrsOut)? ' ' . implode(' ', $attrsOut) : '') . ' />'; } if (in_array('date', $html->_params)) { $out = '
' . $out . '
'; } else if (in_array('time', $html->_params)) { $out = '
' . $out . '
'; } if (true == V::get('appendBack', '', $params) && !in_array('date', $html->_params) && !in_array('time', $html->_params) ) { if ($html->tag == 'input' && $taskPerm == 'W') { $out = '
' . $out . '
'; } } $typeSpecial = Typespecial::getInstance($fieldID, $colName); if ($typeSpecial) { throw new Exception("TODO: TypeSpecial"); $tsParams = array(); $tsValue = V::get('typespecialValue', '', $params); if (!empty($tsValue)) { $tsParams['typespecialValue'] = $tsValue; } $out .= ' ' . $typeSpecial->showFormItem($this->_zasobID, $fName, $fValue, $tsParams, $record); } return $out; } /** * @param $taskPerm - 'C', 'W' */ public function showFormItem($taskPerm, $fieldID, $fName, $fValue, $params = array(), $record = null) { $out = ''; if (!$this->isAllowed($fieldID, $taskPerm, $record)) { if ($taskPerm == 'R') { $out .= 'Brak uprawnień do odczytu'; } else if ($taskPerm == 'W') { $out .= 'Brak uprawnień do zapisu'; } else { $out .= 'Brak uprawnień do tego pola (' . $taskPerm . ')'; } return $out; } $colName = $this->getFields()[$fieldID]['name']; if ($colName == 'ID') { return $out; } $colType = $this->getFieldTypeById($fieldID); if (!$colType) { $out .= 'Error - unknown type'; return $out; } $typeSpecial = Typespecial::getInstance($fieldID, $colName); $html = new stdClass(); $html->_params = array(); $html->tag = 'input'; $html->cnt = ''; $html->attrs = array(); $html->attrs['id'] = $fName; $html->attrs['name'] = $fName; $html->attrs['type'] = 'text'; $html->attrs['value'] = htmlspecialchars($fValue); if (isset($params['tabindex'])) { $html->attrs['tabindex'] = $params['tabindex']; } if (!$this->hasFieldPerm($fieldID, $taskPerm)) { $html->attrs['disabled'] = 'disabled'; } $maxGrid = V::get('maxGrid', 10, $params); if (substr($colType['type'], 0, 3) == 'int' || substr($colType['type'], 0, 7) == 'tinyint' || substr($colType['type'], 0, 8) == 'smallint' || substr($colType['type'], 0, 6) == 'bigint' ) { //$h->Type_value = (int)str_replace(array(' ','(',')'), '', substr($h->Type, 4)); $html->attrs['type'] = 'number'; $html->attrs['class'][] = 'input-small'; } else if (substr($colType['type'], 0, 6) == 'double') { $html->attrs['type'] = 'text'; $html->attrs['class'][] = 'input-small'; } else if (substr($colType['type'], 0, 7) == 'decimal') { $html->attrs['type'] = 'text'; $html->attrs['class'][] = 'input-small'; } else if (substr($colType['type'], 0, 7) == 'varchar' || substr($colType['type'], 0, 4) == 'char' ) { //$h->Type_value = (int)str_replace(array(' ','(',')'), '', substr($h->Type, 8)); $html->attrs['type'] = 'text'; $maxLength = (int)str_replace(array(' ','(',')'), '', substr($colType['type'], strpos($colType['type'], '(') + 1, -1)); if ($maxLength > 0) { $html->attrs['maxlength'] = $maxLength; } $valLength = strlen($fValue); if (isset($params['widthClass'])) { if ($params['widthClass'] == 'inside-modal') { $html->attrs['style'] = 'width:98%;'; } else { $html->attrs['style'] = 'width:98%;'; } } else { /* if ($maxLength < 11) { $html->attrs['class'][] = 'span2'; } else if ($maxLength < 31) { $html->attrs['class'][] = 'span5'; } else if ($maxLength < 51) { $html->attrs['class'][] = (8 <= $maxGrid)? 'span8' : "span{$maxGrid}"; } else if ($maxLength < 101) { $html->attrs['class'][] = (10 <= $maxGrid)? 'span10' : "span{$maxGrid}"; } else { $html->attrs['class'][] = (12 <= $maxGrid)? 'span12' : "span{$maxGrid}"; } */ } if ($maxLength > 255) {// Fix for long varchar - use textarea $html->tag = 'textarea'; $html->cnt = htmlspecialchars($fValue); $html->attrs['rows'] = '3'; unset($html->attrs['type']); unset($html->attrs['value']); } } else if (substr($colType['type'], 0, 4) == 'date') { $testDatePicker = true; if ($testDatePicker) { $html->attrs['type'] = 'text'; $html->_params[] = 'date'; if (substr($colType['type'], 0, 8) == 'datetime') { $html->attrs['class'][] = 'se_type-datetime';// datetimepicker'; $html->attrs['data-format'] = 'yyyy-MM-dd hh:mm'; $html->attrs['maxlength'] = 19; } else { $html->attrs['class'][] = 'se_type-date';// datetimepicker'; $html->attrs['maxlength'] = 10; } if (substr($html->attrs['value'], 0, 10) == '0000-00-00') { $html->attrs['value'] = ''; } } else { $html->attrs['type'] = 'date'; } } else if ($colType['type'] == 'time') { $testDatePicker = true; if ($testDatePicker) { $html->attrs['type'] = 'text'; $html->_params[] = 'time'; $html->attrs['class'][] = 'se_type-time';// datetimepicker'; $html->attrs['data-format'] = 'hh:mm:ss'; $html->attrs['maxlength'] = 8; if (substr($html->attrs['value'], 0, 8) == '00:00:00') { $html->attrs['value'] = ''; } } else { $html->attrs['type'] = 'time'; } } else if ($colType['type'] == 'timestamp') { $testDatePicker = true; if ($testDatePicker) { $html->attrs['type'] = 'text'; $html->_params[] = 'date'; $html->attrs['class'][] = 'se_type-datetime';// datetimepicker'; $html->attrs['data-format'] = 'yyyy-MM-dd hh:mm'; $html->attrs['maxlength'] = 19; if (substr($html->attrs['value'], 0, 10) == '0000-00-00') { $html->attrs['value'] = ''; } } else { $html->attrs['type'] = 'date'; } } else if (substr($colType['type'], 0, 4) == 'enum') { unset($html->attrs['type']); unset($html->attrs['value']); $html->tag = 'select'; $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType['type'], 5))); $selValue = $fValue; if (empty($selValue) && $selValue !== '0' && !empty($colType['default'])) { if ($taskPerm == 'C') { $selValue = $colType['default']; } else if ($taskPerm == 'W' && $this->isAllowed($fieldID, 'R', $record)) { $selValue = $colType['default']; } } $html->cnt .= ''; if (!empty($selValue) && !in_array($selValue, $values)) { $html->cnt .= ''; } foreach ($values as $val) { $sel = ($selValue == $val)? ' selected="selected"' : ''; $html->cnt .= ''; } } else if (substr($colType['type'], 0, 4) == 'text' || substr($colType['type'], 0, 8) == 'tinytext' || substr($colType['type'], 0, 10) == 'mediumtext' || substr($colType['type'], 0, 8) == 'longtext' ) { $html->tag = 'textarea'; $html->cnt = htmlspecialchars($fValue); if (isset($params['widthClass'])) { if ($params['widthClass'] == 'inside-modal') { $html->attrs['style'] = 'width:98%;'; } else { $html->attrs['style'] = 'width:98%;'; } } else { //$html->attrs['class'][] = (8 <= $maxGrid)? 'span8' : "span{$maxGrid}"; } $html->attrs['rows'] = '3'; unset($html->attrs['type']); unset($html->attrs['value']); } else if ('polygon' == $colType['type']) { return '...'; }// Wielokąt else if ('multipolygon' == $colType['type']) { return '...'; }// Zbiór wielokątów else if ('linestring' == $colType['type']) { return '...'; }// Krzywa z interpolacji liniowej pomiędzy punktami else if ('point' == $colType['type']) { return '...'; }// Punkt w przestrzeni 2-wymiarowej else if ('geometry' == $colType['type']) { return '...'; }// Typy, które mogą przechowywać geometrię dowolnego typu else if ('multipoint' == $colType['type']) { return '...'; }// Zbiór punktów else if ('multilinestring' == $colType['type']) { return '...'; }// Zbiór krzywych z interpolacji liniowej pomiędzy punktami else if ('geometrycollection' == $colType['type']) { return '...'; }// Zbiór obiektów geometrycznych dowolnego typu else { return 'unknown Type "'.$colType['type'].'"'; } $html->attrs['class'][] = 'form-control'; $attrsOut = array(); foreach ($html->attrs as $k => $v) { if (is_array($v)) $v = implode(' ', $v); $attrsOut[] = "{$k}=\"{$v}\""; } if (in_array($html->tag, array('select', 'textarea'))) { $out .= '<' . $html->tag . '' . (($attrsOut)? ' ' . implode(' ', $attrsOut) : '') . '>'; $out .= $html->cnt; $out .= 'tag . '>'; } else { $out .= '<' . $html->tag . '' . (($attrsOut)? ' ' . implode(' ', $attrsOut) : '') . ' />'; } if (in_array('date', $html->_params)) { $out = '
' . $out . '
'; } else if (in_array('time', $html->_params)) { $out = '
' . $out . '
'; } if (true == V::get('appendBack', '', $params) && !in_array('date', $html->_params) && !in_array('time', $html->_params) ) { if ($html->tag == 'input' && $taskPerm == 'W') { $out = '
' . $out . '
'; } } if ($typeSpecial) { $tsParams = array(); $tsValue = V::get('typespecialValue', '', $params); if (!empty($tsValue)) { $tsParams['typespecialValue'] = $tsValue; } $out .= ' ' . $typeSpecial->showFormItem($this->_zasobID, $fName, $fValue, $tsParams, $record); } return $out; } /** * List table ids by database * * */ public static function GetTablesByDbId($db) { DEBUG_S(3,'TableAcl_cache',$_SESSION['TableAcl_cache'],__FILE__,__FUNCTION__,__LINE__); static $_cache; $return=array(); if (!$_cache) $_cache = array(); if (!empty($_SESSION['TableAcl_cache'])) { foreach($_SESSION['TableAcl_cache'] as $tableID=>$obj) { //if($obj->db==$db) $return[$obj['name']]=$tableID; } return $return; } return null; } /** * Get column object. Not initialize * @returns object - column instance if exists else null * * static */ public static function getInstance($idTable) { static $_cache; if (!$_cache) $_cache = array(); if (array_key_exists($idTable, $_cache)) { return $_cache[$idTable]; } if (!empty($_SESSION['TableAcl_cache'][$idTable])) { $tableAcl = new TableAcl($idTable); $tableAcl->fromArray($_SESSION['TableAcl_cache'][$idTable]); $_cache[$idTable] = $tableAcl; return $_cache[$idTable]; } if (!empty($_SESSION['AntAcl_cache'][$idTable])) { try { $objectList = SchemaFactory::loadDefaultObject('SystemObject')->getItems([ 'propertyName' => "*,field", 'f_idZasob' => "={$idTable}", ]); if (empty($objectList)) throw new Exception("Acl [{$idTable}] not exists in SystemObject"); // TODO: update Storage object list? $objItem = reset($objectList); DBG::log($objItem, 'array', "DBG objItem({$idTable})"); if (!in_array($objItem['_type'], [ // 'TableAcl', // TODO: TEST - to replace TableAcl by AntAcl or use object with namespace + '/tableName'? 'AntAcl', ])) throw new Exception("Not Implemented acl type '{$objItem['_type']}'"); if (!$objItem['isObjectActive']) { if (!$objItem['hasStruct']) throw new Exception("namespace has no structure '{$namespace}'"); if (!$objItem['isStructInstalled']) throw new Exception("namespace structure not installed '{$namespace}'"); throw new Exception("namespace is not activated '{$namespace}'"); } Lib::loadClass('AntAclBase'); $_cache[$idTable] = AntAclBase::buildInstance($objItem['idZasob'], $objItem); return $_cache[$idTable]; } catch (Exception $e) { DBG::log($e); } } return null; } public static function buildInstance($idTable, $tableConfig) { // TODO: move outside - app session cache? static $_cache; if (!$_cache) $_cache = array(); if (array_key_exists($idTable, $_cache)) { return $_cache[$idTable]; } if (empty($tableConfig)) throw new Exception("Brak danych konfiguracyjnych do tabeli nr {$idTable} #TACL" . __LINE__); // if (empty($tableConfig)) { // $zasobObj = ProcesHelper::getZasobTableInfo($idTable); // if (!$zasobObj) { // return null;// TODO: throw new Exception("Zasob TABELA ID={$idTable} nie istnieje"); // } // $tableConfig['db'] = $zasobObj->P__ID; // $tableConfig['name'] = $zasobObj->DESC; // $tableConfig['label'] = $zasobObj->DESC_PL; // $tableConfig['opis'] = $zasobObj->OPIS; // // $userAcl = User::getAcl(); // $userPermsForTable = $userAcl->getPermsForTable($idTable); // if (!$userPermsForTable) { // return null;// TODO: throw new Exception("Brak uprawnień do pól Tabeli nr {$idTable} '{$zasobObj->DESC}'"); // } // echo'
$userPermsForTable('.$idTable.') ';print_r($userPermsForTable);echo'
'; // if(0){// TODO: from UserAcl big query // $foundTbls[$r->ZASOB_PARENT_ID]->addField($r->ID_ZASOB, $r->ZASOB_DESC, $r->ZASOB_OPIS, $r->z__SORT_PRIO, $r->ZASOB_DESC_PL); // $foundTbls[$r->ZASOB_PARENT_ID]->setFieldPerms($r->ID_ZASOB, $r->FORM_TREAT); // $tableConfig['fields'];// $this->getFields() // $tableConfig['virtualFieldsIdList'];// $this->_virtualFieldsIdList // //$tableConfig['types'];// $this->_types // } // } if (empty($tableConfig)) throw new Exception("Brak danych konfiguracyjnych do tabeli nr {$idTable} #TACL" . __LINE__); $type = (false !== strpos($tableConfig['name'], '/')) ? 'AntAcl' : 'TableAcl'; // TODO: fix naive check this // $type = DB::getPDO()->fetchValue(" select o._type from `CRM_#CACHE_ACL_OBJECT` o where o.idZasob = '{$idTable}' limit 1 "); if ('AntAcl' === $type) { DBG::log("AntAcl save config in TableAcl::buildInstance [{$idTable}] '{$tableConfig['name']}'"); $_SESSION['AntAcl_cache'][$idTable] = true; } else { // TableAcl $obj = new TableAcl($idTable); $obj->fromArray($tableConfig); $obj->getRootTableName(); $obj->save(); } $_cache[$idTable] = $obj; return $_cache[$idTable]; } public function loadSchema() { if ($this->_schemaLoaded) return (bool)$this->_schemaClass; $srvName = $_SERVER['SERVER_NAME']; $this->_schemaClass = Schema_TableFactory::build($this->_name, $this->_db, $srvName); $this->_schemaLoaded = true; return (bool)$this->_schemaClass; } public function getLocalFieldList() { $this->getFields(); return array_keys($this->_types); } public function isLocalField($fieldName) { $this->getFields(); return array_key_exists($fieldName, $this->_types); } public function init($force = false) { // DBG::log("DBG INIT - init ({$this->_zasobID}, {$this->_rootTableName})"); } public function fieldsInit($force = false) { $this->loadSchema(); // DBG::log("TableAcl({$this->_rootTableName}) fieldsInit() isDone: '{$this->_executed_fieldsInit}'"); if (null !== $this->_executed_fieldsInit) return; $this->_executed_fieldsInit = true; DBG::log("DBG INIT - fieldsInit ({$this->_zasobID}, {$this->_rootTableName})"); if (empty($this->_fields)) { $this->_types = array();// clear _types @see $this->isInitialized $userAcl = User::getAcl(); $fieldsConfig = $userAcl->getPermsForTable($this->_zasobID); // DBG::log($fieldsConfig, 'array', "INIT({$this->_zasobID})::initFieldsFromConfig \$fieldsConfig"); $this->initFieldsFromConfig($fieldsConfig); //DBG::_('DBG_SCH', '1', "INIT::\$fieldsConfig({$this->_zasobID}) fields(".count($this->_fields).")", $this, __CLASS__, __FUNCTION__, __LINE__ ); } if ($this->isInitialized() && $force == false) { return; } DBG::simpleLog('auth', "TableAcl::init(name: '{$this->_name}')"); // DBG::log(['$this'=>$this, 'name'=>$this->getName()], 'array', "INIT({$this->_zasobID}):: \$this"); $ds = $this->getDataSource(); // DBG::log($ds, 'array', "INIT({$this->_zasobID})::getDataSource \$ds"); $this->_types = (is_object($this->_schemaClass) && method_exists($this->_schemaClass, 'getLegacyFieldTypes')) ? $this->_schemaClass->getLegacyFieldTypes() : $ds->getFieldTypes(); // DBG::log($this->_types, 'array', "INIT({$this->_zasobID})::getFieldTypes \$this->_types"); uasort($this->_fields, array($this, 'sortFieldsCallback')); $this->_fixTypes(); // DBG::log($this->_types, 'array', "INIT({$this->_zasobID})::after fixTypes \$this->_types"); $this->save(); } public function _fixTypes() { $this->_fixDateFields(); $this->_sortEnumFields(); $this->_fixProjectType(); if ($this->loadSchema()) $this->_types = $this->_schemaClass->fixTypes($this->_types); //DBG::_(true, true, "this->_types", $this->_types, __CLASS__, __FUNCTION__, __LINE__); // fixGeomTypesFromSimpleType foreach ($this->_types as $fieldName => $field) { // [the_geom] => Array( // [type] => geometry // [null] => 1 // [default] => // [simpleType] => linestring if ('geometry' == $field['type']) { if (!empty($field['simpleType'])) { switch ($field['simpleType']) { case 'gml:LineStringPropertyType': $this->_types[ $fieldName ][ 'type' ] = 'linestring'; break; } } $dbName = DB::getPDO()->getDatabaseName(); $tableName = $this->getName(); $geomType = DB::getPDO()->fetchValue(" select DATA_TYPE from `information_schema`.`COLUMNS` where TABLE_SCHEMA='{$dbName}' and TABLE_NAME='{$tableName}' and COLUMN_NAME='{$fieldName}' "); if (!empty($geomType)) $this->_types[ $fieldName ][ 'type' ] = $geomType; } } {// TODO: replace this by $this->_schemaClass (from DataSourceFactory::build(...)) $fieldIds = array_keys($this->_fields); $vColsIdList = Typespecial::initFields($fieldIds); if (!empty($vColsIdList)) { $this->_virtualFieldsIdList = $vColsIdList; } } } public function initFieldsFromConfig($fieldsConfig) { foreach ($fieldsConfig as $idField => $vFieldConfig) { if ((int)$idField <= 0) { DBG::_('DBG_SCH', '1', "BUG key must be integer - skipping '{$idField}'", $vFieldConfig, __CLASS__, __FUNCTION__, __LINE__ ); trigger_error("BUG " . __CLASS__ . "->" . __FUNCTION__ . "(\$fieldsConfig) key must be integer - skipping '{$idField}'", E_USER_NOTICE); continue; } //echo'
INIT::$permField('.$vFieldConfig->ID_CELL.') hasFld('.$this->hasFieldById($vFieldConfig->ID_CELL).') ';echo'
'; if (!$this->hasFieldById($vFieldConfig['ID_CELL'])) { //echo'
INIT::$permField('.$vFieldConfig['ID_CELL'].') addFld('.$vFieldConfig['ID_CELL'] . ', ' . $vFieldConfig['CELL_NAME'] . ', ' . $vFieldConfig['CELL_DESC'] . ', ' . $vFieldConfig['SORT_PRIO'] . ', ' . $vFieldConfig['CELL_LABEL'].') ';echo'
'; $this->addField($vFieldConfig['ID_CELL'], $vFieldConfig['CELL_NAME'], $vFieldConfig['CELL_DESC'], $vFieldConfig['SORT_PRIO'], $vFieldConfig['CELL_LABEL']); } //echo'
INIT::$permField('.$vFieldConfig['ID_CELL'].') hasFld('.$this->hasFieldById($vFieldConfig['ID_CELL']).') ';echo'
'; if (!isset($vFieldConfig['FORM_TREAT'])) {// TODO: convert to legacy perms $vFieldConfig['FORM_TREAT'] = ''; if ($vFieldConfig['PERM_R'] > 0) $vFieldConfig['FORM_TREAT'] .= 'R'; if ($vFieldConfig['PERM_W'] > 0) $vFieldConfig['FORM_TREAT'] .= 'W'; if ($vFieldConfig['PERM_X'] > 0) $vFieldConfig['FORM_TREAT'] .= 'X'; if ($vFieldConfig['PERM_C'] > 0) $vFieldConfig['FORM_TREAT'] .= 'C'; if ($vFieldConfig['PERM_S'] > 0) $vFieldConfig['FORM_TREAT'] .= 'S'; if ($vFieldConfig['PERM_O'] > 0) $vFieldConfig['FORM_TREAT'] .= 'O'; if ($vFieldConfig['PERM_V'] > 0) $vFieldConfig['FORM_TREAT'] .= 'V'; if ($vFieldConfig['PERM_E'] > 0) $vFieldConfig['FORM_TREAT'] .= 'E'; } //echo'
INIT::$permField('.$vFieldConfig['ID_CELL'].') ';print_r($vFieldConfig);echo'
'; if (!empty($vFieldConfig['FORM_TREAT'])) { $this->setFieldPerms($vFieldConfig['ID_CELL'], $vFieldConfig['FORM_TREAT']); } } } private function _fixProjectType() { $tblName = $this->getName(); $fldName = 'M_DIST_TYPE'; if ($tblName == 'IN7_MK_BAZA_DYSTRYBUCJI') { foreach ($this->_fields as $kFldId => $vFld) { if ($vFld['name'] == $fldName) { $sqlTypes = array(); if (!empty($this->_types[$fldName])) { if (substr($this->_types[$fldName]['type'], 0, 4) == 'enum') { $sqlTypes = explode(',', str_replace(array('(',')',"'",'"'), '', substr($this->_types[$fldName]['type'], 5))); } } if (!empty($sqlTypes)) { $allowedTypes = array(); $db = DB::getDB(); $sql = "select z.DESC from `CRM_LISTA_ZASOBOW` as z where z.`A_STATUS`='NORMAL' and z.`PARENT_ID`={$kFldId} order by z.`DESC` asc "; $res = $db->query($sql); while ($r = $db->fetch($res)) { if (in_array($r->DESC, $sqlTypes)) { $allowedTypes[] = $r->DESC; } } sort($allowedTypes); if (!empty($allowedTypes)) { $this->_types[$fldName]['type'] = "enum('" . implode("','", $allowedTypes) . "')"; } } } } } } private function _sortEnumFields() { foreach ($this->_fields as $kFldId => $vFld) { $type = $this->getFieldTypeById($kFldId); if (!empty($type['type'])) { if (substr($type['type'], 0, 4) == 'enum') { $sqlTypes = explode(',', str_replace(array('(',')',"'",'"'), '', substr($type['type'], 5))); if (!empty($sqlTypes)) { sort($sqlTypes); $this->_types[$vFld['name']]['type'] = "enum('" . implode("','", $sqlTypes) . "')"; } } } } } private function _fixDateFields() { foreach ($this->_types as $kFldName => $vType) { if ($kFldName == 'L_APPOITMENT_DATE') { $this->_types[$kFldName]['type'] = 'datetime'; } else if ($kFldName == 'A_PROBLEM_DATE') { $this->_types[$kFldName]['type'] = 'datetime'; } } } public function getUniqueKeys() {// TODO: RM NOT USED? $sqlKeys = array(); $dbID = $this->getDB(); $tblName = $this->getName(); $db = DB::getDB($dbID); if (!$db) { die('Error - Brak konfiguracji dla bazy danych ID=' . $dbID); } $sql = "SHOW KEYS FROM `{$tblName}`"; $res = $db->query($sql); while ($r = $db->fetch($res)) { if ($r->Non_unique == '0') { $sqlKeys[$r->Column_name] = true; } } $sqlKeys = array_keys($sqlKeys); return $sqlKeys; } public function sortFieldsCallback($a, $b) { if ($a['name'] == 'ID') { return -1; } else if ($b['name'] == '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 isInitialized() { return (!empty($this->_types)); } /** * Save data in session cache. */ function save() { $_SESSION['TableAcl_cache'][$this->_zasobID] = $this->toArray(); // DBG::log("save(name='{$_SESSION['TableAcl_cache'][$this->_zasobID]['name']}')"); // DBG::simpleLog('auth', "TableAcl::save(name: '{$this->_name}')"); } public function getFieldTypeById($fieldID) { if (!array_key_exists($fieldID, $this->getFields())) return null; $fieldName = $this->_fields[$fieldID]['name']; if (!array_key_exists($fieldName, $this->_types)) return null; return $this->_types[$fieldName]; } public function getFieldType($fieldName) { if (!array_key_exists($fieldName, $this->_types)) return null; return $this->_types[$fieldName]; } public function hasFieldType($fieldName) { return (array_key_exists($fieldName, $this->_types)); } public function getVisibleFieldList() { return $this->getVisibleFieldListByIdZasob(); } public function getVisibleFieldListByIdZasob() { $primaryKeyField = $this->getSqlPrimaryKeyField(); $cols = array(); $id = 0; foreach ($this->getFields() as $kFieldID => $vField) { if ($vField['name'] == $primaryKeyField) { $id = $kFieldID; } } $cols[$id] = $primaryKeyField; foreach ($this->getFields() as $kFieldID => $vField) { if ($vField['name'] == $primaryKeyField) { continue; } $cols[$kFieldID] = $vField['name']; } return $cols; } public function getExportFieldList() { $cols = array(); $realFlds = $this->getRealFieldList(); foreach ($realFlds as $vFieldName) { $fldId = $this->getFieldIdByName($vFieldName); if ($fldId > 0 && $this->hasFieldPerm($fldId, 'E')) { $cols[] = $vFieldName; } } return $cols; } /** * List of real fields in database. */ public function getRealFieldList() { $cols = array(); $cols[] = 'ID'; foreach ($this->getFields() as $kFieldID => $vField) { if ($vField['name'] == 'ID') { continue; } if (array_key_exists($vField['name'], $this->_types)) { $cols[] = $vField['name']; } } return $cols; } public function getFieldListByIdZasob() { $cols = array(); foreach ($this->getFields() as $idField => $fld) { if ($fld['name'] == 'ID') { $cols[$idField] = 'ID'; } } foreach ($this->getFields() as $idField => $fld) { if ($fld['name'] == 'ID') continue; $cols[$idField] = $fld['name']; } return $cols; } public function getRealFieldListByIdZasob() { $cols = array(); foreach ($this->getFields() as $idField => $fld) { if ($fld['name'] == 'ID') { $cols[$idField] = 'ID'; } } foreach ($this->getFields() as $idField => $fld) { if ($fld['name'] == 'ID') continue; if (array_key_exists($fld['name'], $this->_types)) { $cols[$idField] = $fld['name']; } } return $cols; } public function getVirtualFieldListByIdZasob() { $cols = array(); foreach ($this->getFields() as $kFieldID => $vField) { if ($vField['name'] == 'ID') { continue; } if (in_array($kFieldID, $this->_virtualFieldsIdList)) { $cols[$kFieldID] = $vField['name']; } else if (!array_key_exists($vField['name'], $this->_types)) { $cols[$kFieldID] = $vField['name']; } } return $cols; } public function getFieldLabel($fieldName) { $idField = $this->getFieldIdByName($fieldName); if (array_key_exists($idField, $this->getFields())) { if (!empty($this->_fields[$idField]['label'])) { return $this->_fields[$idField]['label']; } } return null; } public function getFieldOpis($fieldName) { $idField = $this->getFieldIdByName($fieldName); if (array_key_exists($idField, $this->getFields())) { if (!empty($this->_fields[$idField]['opis'])) { return $this->_fields[$idField]['opis']; } } return null; } public function getTypes() { return $this->_types; } public function fixEmptyValueFromUser($fieldID) { $value = ''; $type = $this->getFieldTypeById($fieldID); if ($type) { if ($type['type'] == 'date') { $value = $type['default']; } if (substr($type['type'], 0, 3) == 'int' || substr($type['type'], 0, 7) == 'tinyint' || substr($type['type'], 0, 8) == 'smallint' || substr($type['type'], 0, 6) == 'bigint' ) { $value = intval($type['default']); } // 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 = $type['default']; } } } return $value; } public function fromArray($arr) { // DBG::log("fromArray(name='{$arr['name']}')"); $this->_db = $arr['db']; $this->_name = $arr['name']; $this->_rootTableName = V::get('_rootTableName', null, $arr); $this->_label = $arr['label']; $this->_opis = $arr['opis']; $this->_executed_fieldsInit = null; // V::get('_executed_fieldsInit', null, $arr); $this->_fields = V::get('fields', array(), $arr); $this->_virtualFieldsIdList = V::get('virtualFieldsIdList', array(), $arr); $this->_types = V::get('types', array(), $arr); } public function toArray() { $arr = array(); $arr['db'] = $this->_db; $arr['name'] = $this->_name; $arr['_rootTableName'] = $this->_rootTableName; $arr['label'] = $this->_label; $arr['opis'] = $this->_opis; // if ($this->_executed_fieldsInit) $arr['_executed_fieldsInit'] = $this->_executed_fieldsInit; $arr['fields'] = $this->_fields; $arr['virtualFieldsIdList'] = $this->_virtualFieldsIdList; $arr['types'] = $this->_types; return $arr; } 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], '', "after parseUserItem, validateAndFixField"); return $item; } public function parseUserItem($userItem, $type = 'array_by_id', $prefix = 'f') { $item = []; foreach ($this->getFieldsMap() as $userKey => $fieldName) { if (!array_key_exists("f{$userKey}", $userItem)) continue; $item[$fieldName] = $userItem["f{$userKey}"]; } return $item; } public function getFieldsMap() {// [ $userKey => $fieldName ] // TODO: $this->_fieldsMap $fieldsMap = []; foreach ($this->getFields() as $id => $field) $fieldsMap[ $id ] = $field['name']; return $fieldsMap; } 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); } break; case 'p5:price': { return V::convert($value, 'price'); } break; } return $value; } public function fixFieldEmptyValue($fieldName) {// TODO: legacy $value = ''; $type = $this->getFieldType($fieldName); if (!$type) return ''; if ('date' == $type['type']) { $value = $type['default']; } if (substr($type['type'], 0, 3) == 'int' || substr($type['type'], 0, 7) == 'tinyint' || substr($type['type'], 0, 8) == 'smallint' || substr($type['type'], 0, 6) == 'bigint' ) { $value = intval($type['default']); } // 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 = $type['default']; // } } return $value; } public function buildQuery($params = []) { Lib::loadClass('AclQueryFeatures'); return new AclQueryFeatures($this, $params); } public function getItem($primaryKey, $params = []) { $ds = $this->getDataSource(); return $ds->getItem($primaryKey); } public function prepareQuery($params = array()) { DBG::log($params, 'array', 'TableAcl->prepareQuery $params'); $ds = $this->getDataSource(); $filtrIsInstance = []; // TODO: read instances from $params $filtrIsNotInstance = []; Lib::loadClass('ACL'); return ACL::query($this) ->isInstance($filtrIsInstance) ->isNotInstance($filtrIsNotInstance) ->whereRaw($ds->_parseSqlWhere($params)); } public function getItems($params = array()) { $orderBy = V::get('order_by', '', $params); $orderDir = V::get('order_dir', '', $params); $sortBy = (!empty($orderBy)) ? ( !empty($orderDir) ? "{$orderBy} {$orderDir}" : $orderBy ) : ''; $limit = V::get('limit', 10, $params, 'int'); $offset = V::get('limitstart', 0, $params, 'int'); $ds = $this->getDataSource(); return $this->prepareQuery($params) ->select([ 'rawSelect' => $ds->_getSqlCols() ]) ->select(!empty($params['@instances']) ? '@instances' : '') ->limit($limit) ->offset($offset) ->orderBy($sortBy) ->fetchAll(); } public function getTotal($params = array()) { return $this->prepareQuery($params) ->select([ 'rawSelect' => "count(1) as cnt" ]) ->fetchValue(); } public function getFieldDefaultValue($fieldName) { // TODO: get dafault value from xsd file - TODO: p5:default attribute $ds = $this->getDataSource(); return $ds->getColDefault($fieldName); } public function getColDefault($fieldName) { return $this->getFieldDefaultValue($fieldName); } public function getSpecialFilters() { $ds = $this->getDataSource(); return $ds->getSpecialFilters(); } public function isGeomField($fldName) { return ('the_geom' === $fldName); // $ds = $this->getDataSource(); // return $ds->isGeomField($fldName); } public function getGeomFieldType($fieldName) { if (empty($this->_types)) $this->fieldsInit($force = true); $dbGeomType = $this->getFieldType($fieldName); $dbGeomType = (!empty($dbGeomType['type']))? $dbGeomType['type'] : ''; $geomType = strtolower($dbGeomType); return $geomType; } public function getSqlTableFrom() { if ($this->loadSchema() && method_exists($this->_schemaClass, 'getSqlTableFrom')) { return $this->_schemaClass->getSqlTableFrom(); } return DB::getPDO( $this->getDB() )->tableNameQuote( $this->getRootTableName() ); } public function getHistItems($primaryKey) { if ($this->loadSchema() && method_exists($this->_schemaClass, 'hasGetHistItems') && $this->_schemaClass->hasGetHistItems()) { return $this->_schemaClass->getHistItems($primaryKey); } $ds = $this->getDataSource(); return $ds->getHistItems($primaryKey); } public function getHistItem($id, $idHist) { $ds = $this->getDataSource(); $histItems = $ds->getHistItems($id, ['ID' => $idHist]); if (empty($histItems)) return null; return reset($histItems); } public function addItem($itemTodo) { if (is_object($itemTodo)) { $itemTodo = (array)$itemTodo; } else if (!is_array($itemTodo)) { throw new HttpException('Item is not array', 400); } $ds = $this->getDataSource(); // from convertObjectFromUserInput - fixEmptyValueFromUser $item = array(); $fields = $this->getFields(); foreach ($fields as $kID => $vField) { $vFieldName = $vField['name']; 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 empty record is allowed - empty($item) {// add DefaultAclGroup if no create perms ('C') $defaultAclGroup = User::getDefaultAclGroup(); if ($defaultAclGroup) { $permFields = array('A_ADM_COMPANY', 'A_CLASSIFIED'); foreach ($permFields as $permFldName) { if (array_key_exists($permFldName, $this->_types)) { $permFldId = $this->getFieldIdByName($permFldName); if (0 == $permFldId || !$this->isAllowed($permFldId, 'C')) { $item[$permFldName] = $defaultAclGroup; } } } } } DBG::_('DBG_DS', '>2', "addItem", $item, __CLASS__, __FUNCTION__, __LINE__); return $ds->addItem($item); } /** * @param array $itemPatch */ 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)) { //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 = $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 $itemPatchChecked $itemPatchChecked = array(); $fields = $this->getFields(); foreach ($fields as $kID => $vField) { $vFieldName = $vField['name']; if (!$this->isAllowed($kID, 'W', $itemOld)) { continue; } if (array_key_exists($vFieldName, $itemPatch)) { if (!$this->isAllowed($kID, 'R', $itemOld) && '*****' == $itemPatch[$vFieldName]) { // default value for perms 'W' without 'R' is '*****' } else { $value = $itemPatch[$vFieldName]; if (empty($itemPatch[$vFieldName]) && strlen($itemPatch[$vFieldName]) == 0) {// fix bug in input type date and value="0000-00-00" $value = $this->fixEmptyValueFromUser($kID); } if ($value != $itemOld->$vFieldName) { $itemPatchChecked[$vFieldName] = $value; } } } } if (empty($itemPatchChecked)) { //throw new HttpException("Item Primary Key not set!", 400); return 0;// nothing to change } $itemPatchChecked[$primaryKeyField] = $primaryKey; if ($this->loadSchema() && method_exists($this->_schemaClass, 'hasUpdateItem') && $this->_schemaClass->hasUpdateItem()) { $affected = $this->_schemaClass->updateItem($itemPatchChecked); } else { $ds = $this->getDataSource(); $affected = $ds->updateItem($itemPatchChecked); } return $affected; } public function createItemCopy($item) { $ds = $this->getDataSource(); $types = $this->getTypes(); $uniqKeys = $ds->getUniqueKeys();// TODO: getUniqueFields $primaryKeyField = $ds->getPrimaryKeyField(); $itemCopy = array(); foreach ($types as $kName => $vType) { if ($kName == $primaryKeyField) continue; if (in_array($kName, array('A_RECORD_UPDATE_AUTHOR','A_RECORD_UPDATE_DATE'))) continue; $value = V::get($kName, '', $item); if (in_array($kName, $uniqKeys)) { $value .= '?'; } if ($ds->isGeomField($kName) && !empty($value)) { $value = "GeomFromText('{$value}')"; } $itemCopy[$kName] = $value; } return $itemCopy; } public function getDataSource() { $realFieldList = $this->getRealFieldList(); $dataSource = $this->_getDataSource($realFieldList); $dataSource->setFieldGroupWrite('A_ADM_COMPANY', $this->hasFieldType('A_ADM_COMPANY')); $dataSource->setFieldGroupRead('A_CLASSIFIED', $this->hasFieldType('A_CLASSIFIED')); $dataSource->setFieldOwner('L_APPOITMENT_USER', $this->hasFieldType('L_APPOITMENT_USER')); $adminFields = array('A_RECORD_CREATE_DATE', 'A_RECORD_CREATE_AUTHOR', 'A_RECORD_UPDATE_DATE', 'A_RECORD_UPDATE_AUTHOR'); foreach ($adminFields as $vAdmFld) { if (!in_array($vAdmFld, $realFieldList) && $this->hasFieldType($vAdmFld)) { $dataSource->addCol($vAdmFld); } } return $dataSource; } private function _getDataSource($cols) { $dsConfig = array(); $dsConfig['source_id'] = $this->getDB(); $dsConfig['object_name'] = $this->getRootTableName(); $dsConfig['fields'] = $cols; $dsConfig['field_types'] = $this->getTypes(); $dsConfig['fields_virtual'] = $this->getVirtualFieldListByIdZasob(); $dsConfig['acl_fltr_allowed'] = !$this->hasSuperAccessPerms(); // filtr Access is visible only if user dont have supe access perms. If has then see all rows return DataSourceFactory::buildFromZasobInfo($dsConfig); } public function getPrimaryKeyField() { if ($this->loadSchema()) { $pkField = $this->_schemaClass->getPrimaryKeyField(); if ($pkField) return $pkField; } $ds = $this->getDataSource(); return $ds->getPrimaryKeyField(); } public function isIntegerField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 3) == 'int' || substr($type['type'], 0, 7) == 'tinyint' || substr($type['type'], 0, 8) == 'smallint' || substr($type['type'], 0, 9) == 'mediumint' || substr($type['type'], 0, 6) == 'bigint' ) { return true; } return false; } public function isDecimalField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 7) == 'decimal' || substr($type['type'], 0, 7) == 'numeric' || substr($type['type'], 0, 6) == 'double' || substr($type['type'], 0, 5) == 'float' || substr($type['type'], 0, 4) == 'real' ) { return true; } return false; } public function isDateField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 4) == 'date' && substr($type['type'], 0, 8) != 'datetime') { return true; } return false; } public function isDateTimeField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 8) == 'datetime') { return true; } return false; } public function isTimeField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; return ('time' === $type['type']); } public function isStringField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 7) == 'varchar' || substr($colType['type'], 0, 4) == 'char' ) { return true; } return false; } public function isTextField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 4) == 'text' || substr($type['type'], 0, 8) == 'tinytext' || substr($type['type'], 0, 10) == 'mediumtext' || substr($type['type'], 0, 8) == 'longtext' ) { return true; } return false; } public function isBinaryField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 4) == 'blob' || substr($type['type'], 0, 8) == 'tinyblob' || substr($type['type'], 0, 10) == 'mediumblob' || substr($type['type'], 0, 8) == 'longblob' ) { return true; } return false; } public function isEnumerationField($fldName) { $type = $this->getFieldType($fldName); if (!$type) return false; if (substr($type['type'], 0, 4) == 'enum') { return true; } return false; } public function getEnumerations($fldName) { $type = $this->getFieldType($fldName); if (!$type) return []; if (!$this->isEnumerationField($fldName)) return []; $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($type['type'], 5))); $enum = array(); foreach ($values as $val) { $enum[$val] = $val; } return $enum; } public function getAttributesFromZasoby() { $attributes = array(); $db = DB::getDB(); $sql = " select `ID` as `id_zasob` , `DESC` as `field_name` , `DESC_PL` as `label` , `OPIS` as `description` from `CRM_LISTA_ZASOBOW` where `PARENT_ID`={$this->_zasobID} and `TYPE`='KOMORKA' "; $res = $db->query($sql); while ($r = $db->fetch($res)) { $fldAttr = array(); $fldAttr['id_zasob'] = $r->id_zasob; if (!empty($r->label)) $fldAttr['label'] = $r->label; if (!empty($r->description)) $fldAttr['description'] = $r->description; $attributes[$r->field_name] = $fldAttr; } // fetch field values $sql = " select z.`ID` as `id_zasob` , z.`DESC` as `field_name` , v.`DESC` as `value` , v.`DESC_PL` as `label` -- , v.`OPIS` as `description` from `CRM_LISTA_ZASOBOW` z join `CRM_LISTA_ZASOBOW` v on(v.`PARENT_ID` = z.`ID`) where z.`PARENT_ID`={$this->_zasobID} and z.`TYPE`='KOMORKA' "; $res = $db->query($sql); while ($r = $db->fetch($res)) { if (!empty($r->value) && !empty($r->label)) { $valuesMap = V::get('valuesMap', array(), $attributes[$r->field_name]); $valuesMap[$r->value] = $r->label; $attributes[$r->field_name]['valuesMap'] = $valuesMap; } } return $attributes; } public function getXsdFieldType($fieldName) {// @returns string - xsd type, TODO: throw Exception when field not found static $_xsdStruct = []; if (array_key_exists($fieldName, $_xsdStruct)) return $_xsdStruct[$fieldName]; $_xsdStruct[$fieldName] = $this->_getXsdFieldType($fieldName); return $_xsdStruct[$fieldName]; } public function _getXsdFieldType($fieldName) {// @returns string - xsd type, TODO: throw Exception when field not found if ($this->loadSchema()) { $schemaType = $this->_schemaClass->getType($fieldName); if ($schemaType) return $schemaType; } $fldType = 'xsd:string'; if ('A_RECORD_UPDATE_DATE' == $fieldName) return 'xsd:string'; if ('A_RECORD_CREATE_DATE' == $fieldName) return 'xsd:string'; if ($this->isIntegerField($fieldName)) return 'xsd:integer'; else if ($this->isDecimalField($fieldName)) return 'xsd:decimal'; else if ($this->isDateTimeField($fieldName)) return 'xsd:dateTime'; else if ($this->isTimeField($fieldName)) return 'xsd:time'; else if ($this->isDateField($fieldName)) return 'xsd:date'; else if ($this->isTextField($fieldName)) return 'p5:text'; else if ($this->isGeomField($fieldName)) { //$fldType = 'gml:GeometryPropertyType'; $geomType = $this->getGeomFieldType($fieldName); // DBG::log("DBG Geom field type ({$fieldName}) type({$geomType})"); if ('polygon' == $geomType) return 'gml:PolygonPropertyType'; else if ('point' == $geomType) return 'gml:PointPropertyType'; else if ('linestring' == $geomType) return 'gml:LineStringPropertyType'; else return 'gml:GeometryPropertyType'; } else if ($this->isEnumerationField($fieldName)) return 'p5:enum'; else if ($this->isBinaryField($fieldName)) return 'xsd:base64Binary'; return $fldType; } public function getXsdFieldParam($fieldName, $paramKey) { return ($this->loadSchema()) ? $this->_schemaClass->getFieldParam($fieldName, $paramKey) : $this->_getXsdFieldParam($fieldName, $paramKey) ; } public function _getXsdFieldParam($fieldName, $paramKey) { switch ($paramKey) { case 'maxLength': { $colType = $this->getFieldType($fieldName); if (!$colType) return null; return (int)str_replace(array(' ','(',')'), '', substr($colType['type'], strpos($colType['type'], '(') + 1, -1)); } } return null; } public function getXsdTypes() { // @returns [ fieldName => xsdType, ... ] $xsdTypes = []; foreach ($this->getFields() as $field) { $fieldName = $field['name']; $xsdTypes[ $fieldName ] = $this->getXsdFieldType( $fieldName ); } return $xsdTypes; } public function getFieldsWithXsdTypes() { $xsdTypes = []; foreach ($this->getFields() as $idZasob => $field) { $xsdTypes[ $field['name'] ] = [ 'name' => $field['name'], 'perms' => $field['perms'], 'idZasob' => $idZasob, 'xsdType' => $this->getXsdFieldType($field['name']), ]; } return $xsdTypes; } public function getSqlFieldName($childName) { return $childName; } public function hasField($fieldName) {// TODO: fix use Core_AclFields or ACL::getObjectFields($namespace) - use cache - one place to store structure return array_key_exists($fieldName, $this->_types); } }