/**
  * 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);
     }
 }
Beispiel #2
0
 /**
  * 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),'%')";
     }
 }
Beispiel #3
0
 /**
  * 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) . "'";
     }
 }
Beispiel #4
0
 /**
  * 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']);
     }
 }
Beispiel #5
0
 /**
  * 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;
     }
 }
Beispiel #6
0
 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="&lt;" 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="&gt;&gt;" onClick="shuttle_moveall(\'' . $leftname . '\', \'' . $rightname . '\', \'' . $fieldname . '\');return false;"><i class="glyphicon glyphicon-forward"></i></button>';
     $result .= '<button class="btn btn-default" type="button" value="&lt;&lt;" 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;
 }
Beispiel #7
0
 /**
  * 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;
 }
Beispiel #8
0
 /**
  * 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);
 }
Beispiel #9
0
 /**
  * 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;
 }
Beispiel #10
0
 /**
  * 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 '';
 }