/** * Constructor. * * @param string $name Name of the attribute * @param int $flags Flags for this attribute * @param array $optionArray Array with options * @param $valueArray $value Array with values. If you don't use this parameter, * values are assumed to be the same as the options. */ public function __construct($name, $flags = 0, $optionArray, $valueArray = null) { parent::__construct($name, $flags, $optionArray, $valueArray); $size = 0; $valueArray = $this->getValues(); for ($i = 0, $_i = count($valueArray); $i < $_i; ++$i) { $size += Tools::atk_strlen($valueArray[$i]) + 1; // 1 extra for the '|' symbol } if ($size > 0) { $this->setAttribSize($size); } }
/** * Generate an SQL searchcondition for a soundex match. * * @param string $field The fieldname on which the soundex match will * be performed. * @param string $value The value to search for. * @param bool $inverse Set to false (default) to perform a normal * match. Set to true to generate a SQL string * that searches for values dat do not match. * * @return string A SQL soundex expression. */ public function soundexCondition($field, $value, $inverse = false) { if ($value[0] == '!') { return "soundex({$field}) NOT like concat('%',substring(soundex('" . substr($value, 1, Tools::atk_strlen($value)) . "') from 2),'%')"; } else { return "soundex({$field}) like concat('%',substring(soundex('{$value}') from 2),'%')"; } }
/** * Generate a searchcondition that accepts '*' as wildcard character. * * @param string $field * @param string $value */ public function wildcardCondition($field, $value) { if ($this->getDb()->getForceCaseInsensitive()) { if ($value[0] == '!') { return $field . " NOT ILIKE '" . str_replace('*', '%', substr($value, 1, Tools::atk_strlen($value))) . "'"; } return $field . " ILIKE '" . str_replace('*', '%', $value) . "'"; } else { if ($value[0] == '!') { return $field . " NOT LIKE '" . str_replace('*', '%', substr($value, 1, Tools::atk_strlen($value))) . "'"; } return $field . " LIKE '" . str_replace('*', '%', $value) . "'"; } }
/** * Validates the supplied passwords. * * @param array $record Record that contains value to be validated. * Errors are saved in this record * @param string $mode can be either "add" or "update" */ public function validate(&$record, $mode) { $error = false; $value = $record[$this->fieldName()]; if ($mode == 'update' && (Tools::atk_strlen($value['new']) > 0 || Tools::atk_strlen($value['again']) > 0) && !$this->hasFlag(self::AF_PASSWORD_NO_VALIDATE) && !$this->verify($value['current'], $value['hash'])) { Tools::triggerError($record, $this->fieldName(), 'error_password_incorrect'); } if (Tools::atk_strlen($value['new']) > 0 && Tools::atk_strlen($value['again']) > 0 && $value['new'] != $value['again']) { $error = true; Tools::triggerError($record, $this->fieldName(), 'error_password_nomatch'); } if ($mode == 'add' && $this->hasFlag(self::AF_OBLIGATORY) && Tools::atk_strlen($value['new']) == 0) { $error = true; Tools::triggerError($record, $this->fieldName(), 'error_obligatoryfield'); } // Check if the password meets the restrictions. If not, set error to true and // triger an error with the human readable form of the restrictions as message. if (isset($value['new']) && Tools::atk_strlen($value['new']) > 0 && !$this->validateRestrictions($value['new'])) { $error = true; Tools::triggerError($record, $this->fieldName(), $this->getRestrictionsText()); } // new password? if (!$error && isset($value['new']) && Tools::atk_strlen($value['new']) > 0) { $record[$this->fieldName()]['hash'] = $this->encode($record[$this->fieldName()]['new']); } }
/** * Parses the data that we are going to display in the textfield * and adjust rows to ensure that all the data is actually displayed. * * @param string $data Data we want to display * @param int $rows Rows of the textarea * @param int $cols Columns of the textarea */ public function doAutoAdjust($data, &$rows, &$cols) { $browser = new BrowserInfo(); $maxlinechars = 0; for ($counter = 0, $linecharacters = 0, $rowsrequired = 1; $counter < Tools::atk_strlen($data); $counter++, $linecharacters++) { // Current character we are parsing $character = substr($data, $counter, 1); // If we encounter a newline character or the number of characters // equals the number of columns we have (with IE)... if ($character == chr(13) || $linecharacters == $cols && $browser->browser == 'MSIE') { if ($linecharacters > $maxlinechars) { $maxlinechars = $linecharacters; } // We start another line $linecharacters = 0; // But need another row ++$rowsrequired; } } // If we need more rows, we set them if ($rowsrequired > $rows) { $rows = $rowsrequired; } // IE wraps characters, other don't, so if we're not dealing with IE // we need more columns if ($maxlinechars > $cols && $browser->browser !== 'MSIE') { $cols = $maxlinechars; } }
public function edit($record, $fieldprefix, $mode) { $this->createDestination(); $this->createLink(); $this->_renderChangeHandler($fieldprefix); $selectedPk = []; // first the selected records.. for ($i = 0; $i < count($record[$this->m_name]); ++$i) { if (is_array($record[$this->fieldName()][$i][$this->getRemoteKey()])) { $newselected = $this->m_destInstance->primaryKey($record[$this->m_name][$i][$this->getRemoteKey()]); } else { $newselected = $this->m_destInstance->primaryKey(array($this->m_destInstance->primaryKeyField() => $record[$this->m_name][$i][$this->getRemoteKey()])); } $selectedPk[] = $newselected; } $recordset = $this->_getSelectableRecords($record, $mode); $left = []; $right = []; $width = 100; for ($i = 0; $i < count($recordset); ++$i) { if (in_array($this->m_destInstance->primaryKey($recordset[$i]), $selectedPk) || in_array($recordset[$i][$this->m_destInstance->primaryKeyField()], $this->initialValue()) && $mode == 'add') { $right[] = $recordset[$i]; } else { $left[] = $recordset[$i]; } // fancy autowidth detection $width = max(Tools::atk_strlen($this->m_destInstance->descriptor($recordset[$i])) * 10, $width); } if ($this->m_maxlistwidth) { $width = min($this->m_maxlistwidth, $width); } $result = '<table border="0" class="' . $this->get_class_name() . '"><tr><td>' . Tools::atktext('available', 'atk') . ':<br/>'; $fieldname = $fieldprefix . $this->fieldName(); $leftname = $fieldname . '_sel'; $rightname = $fieldname . '[][' . $this->getRemoteKey() . ']'; $filterbox_left = false; $filterbox_right = false; $rightname_clean = ''; if ($this->m_filterBox) { // fix for selecting with jQuery // css ids shouldn't contain characters like [ and ] : http://www.w3.org/TR/html5/dom.html#the-id-attribute $rightname_clean = str_replace('[', '\\\\[', $rightname); $rightname_clean = str_replace(']', '\\\\]', $rightname_clean); $filterbox_left = $fieldname . 'left_filter_box'; $filterbox_right = $fieldname . 'right_filter_box'; } $result .= $this->_renderSelect($leftname, $left, $width, $rightname, $fieldname, $filterbox_left); $result .= '</td><td class="shuttle-controls">'; if ($this->m_filterBox) { // move buttons down a little if filter boxes are being displayed $result .= '<br><br><br>'; } $result .= '<div class="shuttle-controls-single">'; $result .= '<button class="btn btn-default" onClick="shuttle_move(\'' . $leftname . '\', \'' . $rightname . '\', \'' . $fieldname . '\');return false;"><i class="glyphicon glyphicon-triangle-right"></i></button>'; $result .= '<button class="btn btn-default" type="button" value="<" onClick="shuttle_move(\'' . $rightname . '\', \'' . $leftname . '\', \'' . $fieldname . '\');return false;"><i class="glyphicon glyphicon-triangle-left"></i></button>'; $result .= '</div>'; $result .= '<div class="shuttle-controls-multiple">'; $result .= '<button class="btn btn-default" type="button" value=">>" onClick="shuttle_moveall(\'' . $leftname . '\', \'' . $rightname . '\', \'' . $fieldname . '\');return false;"><i class="glyphicon glyphicon-forward"></i></button>'; $result .= '<button class="btn btn-default" type="button" value="<<" onClick="shuttle_moveall(\'' . $rightname . '\', \'' . $leftname . '\', \'' . $fieldname . '\');return false;"><i class="glyphicon glyphicon-backward"></i></button>'; $result .= '</div>'; $result .= '</td><td>' . Tools::atktext('selected', 'atk') . ':<br/>'; $result .= $this->_renderSelect($rightname, $right, $width, $leftname, $fieldname, $filterbox_right); // on submit, we must select all items in the right selector, as unselected items // will not be posted. $page = $this->m_ownerInstance->getPage(); $page->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkshuttlerelation.js'); if ($this->m_filterBox && $rightname_clean && $filterbox_right && $filterbox_left && $rightname && $leftname) { // do the filtering $page->register_scriptcode("\n jQuery(function(\$){\n \$('#{$filterbox_left}').on('input', function() {\n var val = this.value.toLowerCase();\n \$('#{$leftname} > option').hide()\n .filter(function() {\n return this.text.toLowerCase().indexOf( val ) > -1;\n })\n .show();\n });\n\n \$('#{$filterbox_right}').on('input', function() {\n var val = this.value.toLowerCase();\n \$('#{$rightname_clean} > option').hide()\n .filter(function() {\n return this.text.toLowerCase().indexOf( val ) > -1;\n })\n .show();\n });\n });\n "); } $page->register_submitscript("shuttle_selectAll('" . $rightname . "');"); $result .= '</table>'; return $result; }
/** * Return the meta data of a certain table. * * @param string $table the table name * @param bool $full all meta data or not * * @return array with meta data */ public function metadata($table, $full = false) { $ddl = Ddl::create('PgSql'); if (strpos($table, '.') != false) { // there is a period in the table, so we split out the schema name. $schema = substr($table, 0, strpos($table, '.')); $table = substr($table, strpos($table, '.') + 1); $schema_condition = "AND n.nspname = '{$schema}' "; $schema_join = ' LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)'; } else { //no period in the name, so there is no schema $schema_condition = ''; $schema_join = ''; } // Get meta data from system tables. // See developer manual (www.postgresql.org) // for system table specification. $sql = "SELECT\n a.attnum AS i,\n a.attname AS name,\n t.typname AS type,\n (CASE WHEN LOWER(t.typname) = 'varchar' AND a.attlen = -1 THEN a.atttypmod - 4 ELSE a.attlen END) AS length,\n (CASE WHEN a.attnotnull THEN 1 ELSE 0 END) AS is_not_null,\n (\n SELECT COUNT(1)\n FROM pg_index i\n WHERE i.indrelid = c.oid\n AND i.indisprimary = true\n AND a.attnum IN (\n i.indkey[0], i.indkey[1], i.indkey[2],\n i.indkey[3], i.indkey[4], i.indkey[5],\n i.indkey[6], i.indkey[7], i.indkey[8]\n )\n LIMIT 1\n ) AS is_primary,\n (\n SELECT COUNT(1)\n FROM pg_index i\n WHERE i.indrelid = c.oid\n AND i.indisunique = true\n AND i.indnatts = 1\n AND i.indkey[0] = a.attnum\n LIMIT 1\n ) AS is_unique,\n (CASE WHEN ad.adsrc LIKE 'nextval(%::text)' THEN 1 ELSE 0 END) AS is_auto_inc,\n (CASE WHEN ad.adsrc LIKE 'nextval(%::text)' THEN SUBSTRING(ad.adsrc, '''(.*?)''') END) AS sequence,\n (CASE WHEN t.typname = 'varchar' THEN SUBSTRING(ad.adsrc FROM '^''(.*)''.*\$') ELSE ad.adsrc END) AS default\n FROM pg_class c\n JOIN pg_attribute a ON (a.attrelid = c.oid AND a.attnum > 0)\n JOIN pg_type t ON (t.oid = a.atttypid)\n LEFT JOIN pg_attrdef ad ON (ad.adrelid = c.oid AND ad.adnum = a.attnum)\n {$schema_join}\n WHERE c.relname = '{$table}'\n {$schema_condition}\n ORDER BY a.attnum"; $meta = []; $rows = $this->getRows($sql); foreach ($rows as $i => $row) { $meta[$i]['table'] = $table; $meta[$i]['type'] = $row['type']; $meta[$i]['gentype'] = $ddl->getGenericType($row['type']); $meta[$i]['name'] = $row['name']; $meta[$i]['len'] = $row['length']; $meta[$i]['flags'] = ($row['is_primary'] == 1 ? Db::MF_PRIMARY : 0) | ($row['is_unique'] == 1 ? Db::MF_UNIQUE : 0) | ($row['is_not_null'] == 1 ? Db::MF_NOT_NULL : 0) | ($row['is_auto_inc'] == 1 ? Db::MF_AUTO_INCREMENT : 0); if ($row['is_auto_inc'] == 1) { $meta[$i]['sequence'] = $row['sequence']; } else { if (Tools::atk_strlen($row['default']) > 0) { // date/time/datetime if (strtolower($row['default']) == 'now' && in_array($meta[$i]['gentype'], array('date', 'time', 'datetime'))) { $meta[$i]['default'] = 'NOW'; } else { if (in_array($meta[$i]['gentype'], array('number', 'decimal'))) { $meta[$i]['default'] = $row['default']; } else { if (in_array($meta[$i]['gentype'], array('string', 'text'))) { $meta[$i]['default'] = $row['default']; } else { if ($meta[$i]['gentype'] == 'boolean') { $meta[$i]['default'] = strtolower($row['default']) == 't' ? 1 : 0; } } } } } } if ($full) { $meta['meta'][$row['name']] =& $meta[$i]; } } if ($full) { $meta['num_fields'] = count($rows); } return $meta; }
/** * Constructor. * * Warning: very old versions of this attribute supported passing the * parameters in a different order: $name, $flags, $optionArray. * This order used to be supported even when the new order was * implemented, but it has now been removed. Keep this in mind * when upgrading from a very old ATK version (pre ATK4). * * @param string $name Name of the attribute * @param int $flags Flags for this attribute * @param array $optionArray Array with options * @param array $valueArray Array with values. If you don't use this parameter, * values are assumed to be the same as the options. */ public function __construct($name, $flags = 0, $optionArray, $valueArray = null) { if (!is_array($valueArray) || count($valueArray) == 0) { $valueArray = $optionArray; } // If all values are numeric, we can use a numeric field to store the selected // value. $this->m_dbfieldtype = 'number'; for ($i = 0, $_i = count($valueArray); $i < $_i && $this->m_dbfieldtype == 'number'; ++$i) { if (!is_numeric($valueArray[$i])) { $this->m_dbfieldtype = 'string'; } // if one of the values is not a number, the fieldtype must be string, and // the loop is stopped. } // the max size we have is equal to the biggest value. $size = 0; for ($i = 0, $_i = count($valueArray); $i < $_i; ++$i) { $size = max($size, Tools::atk_strlen($valueArray[$i])); } if ($size > 0) { $this->setAttribSize($size); } parent::__construct($name, $flags); $this->setOptions($optionArray, $valueArray); }
/** * Add the allField to the col_map array * but only if a valid field is selected. * * @param array $col_map The map of columns (!stub) * * @return mixed The value for the field to use with all records */ public function getAllFieldsValues(&$col_map) { $allFields = $this->m_postvars['allFields']; foreach ($allFields as $key => $allField) { if ($allField != '') { $attr = $this->getUsableAttribute($allField); if ($attr) { $col_map[] = $allField; } //get the value from the postvars $allFieldValue = $this->m_postvars[$allField]; if (strstr($allFieldValue, '=')) { $allFieldValue = substr(strstr($allFieldValue, '='), 2); $allFieldValue = substr($allFieldValue, 0, Tools::atk_strlen($allFieldValue) - 1); } $allFieldsValues[$allField] = $allFieldValue; } } return $allFieldsValues; }
/** * Creates a searchcondition for the field, * was once part of searchCondition, however, * searchcondition() also immediately adds the search condition. * * @param Query $query The query object where the search condition should be placed on * @param string $table The name of the table in which this attribute * is stored * @param mixed $value The value the user has entered in the searchbox * @param string $searchmode The searchmode to use. This can be any one * of the supported modes, as returned by this * attribute's getSearchModes() method. * @param string $fieldname alias? * * @return string The searchcondition to use. */ public function getSearchCondition(Query $query, $table, $value, $searchmode, $fieldname = '') { // If we are accidentally mistaken for a relation and passed an array // we only take our own attribute value from the array if (is_array($value)) { $value = $value[$this->fieldName()]; } if ($this->m_searchmode) { $searchmode = $this->m_searchmode; } // @todo Is this really needed? if (strpos($value, '*') !== false && Tools::atk_strlen($value) > 1) { // auto wildcard detection $searchmode = 'wildcard'; } $func = $searchmode . 'Condition'; if (method_exists($query, $func) && ($value || $value == 0)) { return $query->{$func}($table . '.' . $this->fieldName(), $this->escapeSQL($value), $this->dbFieldType()); } elseif (!method_exists($query, $func)) { Tools::atkdebug("Database doesn't support searchmode '{$searchmode}' for " . $this->fieldName() . ', ignoring condition.'); } return ''; }