/** * Get an instance of the columnconfig class. * * @param Node $node * @param string $id * @param bool $forceNew force new instance? * * @return ColumnConfig An instance of the columnconfig class */ public static function getConfig($node, $id = null, $forceNew = false) { static $s_instances = []; $sm = SessionManager::getInstance(); if ($id == null) { $id = $node->atkNodeUri(); } if (!isset($s_instances[$id]) || $forceNew) { $cc = new self(); $s_instances[$id] = $cc; $cc->setNode($node); $colcfg = $sm != null ? $sm->pageVar('atkcolcfg_' . $id) : null; if (!is_array($colcfg) || $forceNew) { // create new Tools::atkdebug('New colconfig initialising'); $cc->init(); } else { // inherit old config from session. Tools::atkdebug('Resuming colconfig from session'); $cc->m_colcfg =& $colcfg; } // See if there are any url params which influence this colcfg. $cc->doUrlCommands(); } if ($sm != null) { $sm->pageVar('atkcolcfg_' . $id, $s_instances[$id]->m_colcfg); } return $s_instances[$id]; }
/** * Copies a record, based on parameters passed in the url. */ public function nodeCopy() { Tools::atkdebug('CopyHandler::nodeCopy()'); $recordset = $this->m_node->select($this->m_postvars['atkselector'])->mode('copy')->getAllRows(); $db = $this->m_node->getDb(); if (count($recordset) > 0) { // allowed to copy record? if (!$this->allowed($recordset[0])) { $this->renderAccessDeniedPage(); return; } if (!$this->m_node->copyDb($recordset[0])) { Tools::atkdebug('node::action_copy() -> Error'); $db->rollback(); $location = $this->m_node->feedbackUrl('save', self::ACTION_FAILED, $recordset[0], $db->getErrorMsg()); Tools::atkdebug('node::action_copy() -> Redirect'); $this->m_node->redirect($location); } else { $db->commit(); $this->notify('copy', $recordset[0]); $this->clearCache(); } } $this->m_node->redirect(); }
/** * Get new menu object. * * @return Menu class object */ public static function getInstance() { static $s_instance = null; if ($s_instance == null) { Tools::atkdebug('Creating a new menu instance'); $s_instance = new static(); } return $s_instance; }
/** * Notify the listener of any action on a record. * * This method is called by the framework for each action called on a * node. Depending on the actionfilter passed in the constructor, the * call is forwarded to the actionPerformed($action, $record) method. * * @param string $trigger The trigger being performed * @param array $record The record on which the trigger is performed * @param string $mode The mode (add/update) * * @return bool Result of operation. */ public function notify($trigger, &$record, $mode = null) { if (method_exists($this, $trigger)) { Tools::atkdebug('Call listener ' . get_class($this) . " for trigger {$trigger} on " . $this->m_node->atkNodeUri() . ' (' . $this->m_node->primaryKey($record) . ')'); return $this->{$trigger}($record, $mode); } else { return true; } }
/** * check if database table exists. * * @return bool */ protected function tableExist() { if ($this->m_table_exists !== null) { return $this->m_table_exists; } $db = $this->m_node->getDb(); $this->m_table_exists = $db->tableExists($this->m_table); Tools::atkdebug('tableExists checking table: ' . $this->m_table . ' exists : ' . print_r($this->m_table_exists, true)); return $this->m_table_exists; }
/** * Select records using the given criteria. * * @param string $selector selector string * @param string $order order string * @param array $limit limit array * * @return array selected records */ public function select($selector = null, $order = null, $limit = null) { Tools::atkdebug(get_class($this) . '::select(' . $selector . ')'); if ($order == null) { $order = $this->getOrder(); } $params = array('selector' => $selector, 'order' => $order, 'offset' => isset($limit['offset']) ? $limit['offset'] : 0, 'limit' => isset($limit['limit']) ? $limit['limit'] : -1, 'search' => isset($this->m_postvars['atksearch']) ? $this->m_postvars['atksearch'] : null); $result = $this->findData($params); Tools::atkdebug('Result ' . get_class($this) . '::select(' . $selector . ') => ' . count($result) . ' row(s)'); return $result; }
/** * Replace the bind parameters in the parsed query with their escaped values. * * @param array $params parameters * * @return string query */ protected function _bindParams($params) { $query = $this->_getParsedQuery(); Tools::atkdebug('Binding parameters for query: ' . $this->_getParsedQuery()); foreach (array_values($this->_getBindPositions()) as $i => $param) { Tools::atkdebug("Bind param {$i}: " . ($params[$param] === null ? 'NULL' : $params[$param])); } foreach (array_reverse($this->_getBindPositions(), true) as $position => $param) { $query = substr($query, 0, $position) . ($params[$param] === null ? 'NULL' : "'" . $this->getDb()->escapeSQL($params[$param]) . "'") . substr($query, $position + 1); } return $query; }
/** * Converts an ip (in number or string format) to a long number. * * The supplied ip must be a valid ip. If the given ip is not * valid, then atkerror will be called. * * @static This function may be used statically * * @param mixed $ip String or long numeric IP address. * * @return bool True if the ip is valid, False if not. */ public static function ipLongFormat($ip) { if (!self::ipValidate($ip)) { Tools::atkdebug('IpUtils::ipLongFormat() Invalid ip given'); return; } if (is_numeric($ip)) { return $ip; } $array = explode('.', $ip); return $array[3] + 256 * $array[2] + 256 * 256 * $array[1] + 256 * 256 * 256 * $array[0]; }
/** * Get the selected record from. * * @return array the record to be copied */ protected function getCopyRecord() { $selector = $this->m_postvars['atkselector']; $recordset = $this->m_node->select($selector)->mode('copy')->getAllRows(); if (count($recordset) > 0) { return $recordset[0]; } else { Tools::atkdebug("Geen records gevonden met selector: {$selector}"); $this->m_node->redirect(); } return; }
/** * Implements the {atkmessages} plugin for use in templates. * * The {atkmessages} tag does not output anything. Instead, it loads * the messages into the template variable {$atkmessages}, which is * an array of elements, each with a single message. * * <b>Example:</b> * <code> * {atkmessages} * * {foreach from=$atkmessages item=message} * {$message.message}<br> * {/foreach} * </code> * * @author Patrick van der Velden <*****@*****.**> */ function smarty_function_atkmessages($params, $smarty) { $sessionManager = SessionManager::getInstance(); if (is_object($sessionManager)) { $msgs = MessageQueue::getMessages(); $smarty->assign('atkmessages', $msgs); if (empty($msgs)) { Tools::atkdebug('No messages in MessageQueue'); } return ''; } return ''; }
/** * Bind statement parameters. * * @param array $params parameters */ private function _bindParams($params) { if (count($params) == 0) { return; } $i = 0; $args = []; $args[] = str_repeat('s', count($this->_getBindPositions())); foreach ($this->_getBindPositions() as $param) { Tools::atkdebug("Bind param {$i}: " . ($params[$param] === null ? 'NULL' : $params[$param])); $args[] =& $params[$param]; ++$i; } call_user_func_array(array($this->m_stmt, 'bind_param'), $args); }
/** * Check if Zend Platform is available and good to go. * * @return bool */ protected function zendPlatformAvailable() { if (!function_exists('accelerator_license_info')) { Tools::atkdebug('Zend Platform was not detected'); return false; } if (!function_exists('accelerator_get_configuration')) { $licenseInfo = accelerator_license_info(); Tools::atkdebug('The Zend Platform extension is not loaded correctly: ' . $licenseInfo['failure_reason']); return false; } if (!function_exists('monitor_custom_event')) { Tools::atkdebug('Zend Platform seems to be there, but the function \'monitor_custom_event\' could not be found'); return false; } return true; }
/** * Get the Smarty instance. * * @return \Smarty The one and only instance. */ public static function getInstance() { static $s_smarty = null; if ($s_smarty == null) { Tools::atkdebug('Creating Smarty instance'); $tplcompiledir = Config::getGlobal('tplcompiledir'); if (!is_dir($tplcompiledir) && !mkdir($tplcompiledir, 0755, true)) { Tools::atkerror("Unable to create template compile directory: {$tplcompiledir}"); } $tplcompiledir = realpath($tplcompiledir); $s_smarty = new Smarty(); $s_smarty->setTemplateDir(Config::getGlobal('template_dir')); // name of directory for templates $s_smarty->autoload_filters = []; // indicates which filters will be auto-loaded $s_smarty->setCompileDir($tplcompiledir); // name of directory for compiled templates $s_smarty->setForceCompile(Config::getGlobal('tplforcecompile')); // force templates to compile every time, $s_smarty->addPluginsDir(__DIR__ . '/plugins'); Tools::atkdebug('Instantiated new Smarty'); } return $s_smarty; }
/** * Get Country option, when current language doesn't exists * it will return the english language. * * @param string $iso_code 2 Letter iso code of the country * * @return string Country name */ public function getCountryOption($iso_code) { $lng = Language::getLanguage(); if (!array_key_exists($iso_code, $this->m_country)) { Tools::atkdebug('UNKNOWN ISO CODE: ' . $iso_code); } if (array_key_exists($lng, $this->m_country[$iso_code])) { return $this->m_country[$iso_code][$lng]; } else { return $this->m_country[$iso_code]['en']; } }
/** * Populate the record with the destination record data. * * @param array $record record * @param mixed $fullOrFields load all data, only the given fields or only the descriptor fields? */ public function populate(&$record, $fullOrFields = false) { if (!is_array($record) || $record[$this->fieldName()] == '') { return; } Tools::atkdebug('Delayed loading of ' . ($fullOrFields || is_array($fullOrFields) ? '' : 'descriptor ') . 'fields for ' . $this->m_name); $this->createDestination(); $includes = ''; if (is_array($fullOrFields)) { $includes = array_merge($this->m_destInstance->m_primaryKey, $fullOrFields); } else { if (!$fullOrFields) { $includes = $this->m_destInstance->descriptorFields(); } } $result = $this->m_destInstance->select($this->m_destInstance->primaryKey($record[$this->fieldName()]))->orderBy($this->m_destInstance->getColumnConfig()->getOrderByStatement())->includes($includes)->getFirstRow(); if ($result != null) { $record[$this->fieldName()] = $result; } }
/** * Creates a special Recordlist that can be used for exporting to files or to make it printable. * * @param Node $node The node to use as definition for the columns. * @param array $recordset The records to render * @param string $sol String to use at start of each row * @param string $sof String to use at start of each field * @param string $eof String to use at end of each field * @param string $eol String to use at end of each row * @param int $type 0=Render rows in simple html tabl; 1= raw export * @param string $compression Compression technique (bzip / gzip) * @param array $suppressList List of attributes from $node that should be ignored * @param array $outputparams Key-Value parameters for output. Currently existing: * filename - the name of the file (without extension .csv) * @param string $mode The mode that is passed to attributes' display() method * (for overrides). Defaults to 'list'. * @param bool $titlerow Should titlerow be rendered or not * @param bool $decode Should data be decoded or not (for exports) * @param string $fsep String to use between fields * @param string $rfeplace String for replacing line feeds in recordset field values (null = do not replace) * * @return string|null */ public function render($node, $recordset, $sol, $sof, $eof, $eol, $type = 0, $compression = '', $suppressList = '', $outputparams = [], $mode = 'list', $titlerow = true, $decode = false, $fsep = '', $rfeplace = null) { $this->setNode($node); $this->m_mode = $mode; // example html csv // $sol = '<tr>' or '' // $sof = '<td>' or '"' // $eof = '</td>' or '"' // $eol = '</tr>' or '\r\n' // $fsep = '' or ';' //$empty om lege tabelvelden op te vullen; // stuff for the totals row.. $output = ''; $empty = ''; if ($type == '0') { $empty = ' '; } if ($titlerow) { $output .= $sol; // display a headerrow with titles. // Since we are looping the attriblist anyway, we also check if there // are totalisable collumns. foreach (array_keys($this->m_node->m_attribList) as $attribname) { $p_attrib = $this->m_node->m_attribList[$attribname]; $musthide = is_array($suppressList) && count($suppressList) > 0 && in_array($attribname, $suppressList); if (!$this->isHidden($p_attrib) && !$musthide) { $output .= $sof . $this->eolreplace($p_attrib->label(), $rfeplace) . $eof . $fsep; } } if ($fsep) { // remove separator at the end of line $output = substr($output, 0, -strlen($fsep)); } $output .= $eol; } // Display the values for ($i = 0, $_i = count($recordset); $i < $_i; ++$i) { $output .= $sol; foreach (array_keys($this->m_node->m_attribList) as $attribname) { $p_attrib = $this->m_node->m_attribList[$attribname]; $musthide = is_array($suppressList) && count($suppressList) > 0 && in_array($attribname, $suppressList); if (!$this->isHidden($p_attrib) && !$musthide) { // An <attributename>_display function may be provided in a derived // class to display an attribute. $funcname = $p_attrib->m_name . '_display'; if (method_exists($this->m_node, $funcname)) { $value = $this->eolreplace($this->m_node->{$funcname}($recordset[$i], $this->m_mode), $rfeplace); } else { // otherwise, the display function of the particular attribute // is called. $value = $this->eolreplace($p_attrib->display($recordset[$i], $this->m_mode), $rfeplace); } if (Tools::atkGetCharset() != '' && $decode) { $value = Tools::atk_html_entity_decode(htmlentities($value, ENT_NOQUOTES), ENT_NOQUOTES); } $output .= $sof . ($value == '' ? $empty : $value) . $eof . $fsep; } } if ($fsep) { // remove separator at the end of line $output = substr($output, 0, -strlen($fsep)); } $output .= $eol; } // html requires table tags if ($type == '0') { $output = '<table border="1" cellspacing="0" cellpadding="2">' . $output . '</table>'; } Tools::atkdebug(Tools::atk_html_entity_decode($output)); // To a File if (!array_key_exists('filename', $outputparams)) { $outputparams['filename'] = 'achievo'; } if ($this->m_exportcsv) { $ext = $type == '0' ? 'html' : 'csv'; $exporter = new FileExport(); $exporter->export($output, $outputparams['filename'], $ext, $ext, $compression); } else { return $output; } return; }
/** * Generic method invoker. * * Handler methods invoked with invoke() instead of directly, have a major * advantage: the handler automatically searches for an override in the * node. For example, If a handler calls its getSomething() method using * the invoke method, the node may implement its own version of * getSomething() and that method will then be called instead of the * original. The handler is passed by reference to the override function * as first parameter, so if necessary, you can call the original method * from inside the override. * * The function accepts a variable number of parameters. Any parameter * that you would pass to the method, can be passed to invoke(), and * invoke() will pass the parameters on to the method. * * There is one limitation: you can't pass parameters by reference if * you use invoke(). * * <b>Example:</b> * * <code> * $handler->invoke("editPage", $record, $mode); * </code> * * This will call editPage(&$handler, $record, $mode) on your node class * if present, or editPage($record, $mode) in the handler if the node has * no override. * * @param string $methodname The name of the method to call. * * @return mixed The method returns the return value of the invoked * method. */ public function invoke($methodname) { $arguments = func_get_args(); // Put arguments in a variable (php won't let us pass func_get_args() to other functions directly. // the first argument is $methodname, which we already defined by name. array_shift($arguments); if ($this->m_node !== null && method_exists($this->m_node, $methodname)) { Tools::atkdebug("Invoking '{$methodname}' override on node"); // We pass the original object as first parameter to the override. array_unshift($arguments, $this); $arguments[0] =& $this; // reference copy workaround; return call_user_func_array(array(&$this->m_node, $methodname), $arguments); } else { if (method_exists($this, $methodname)) { Tools::atkdebug("Invoking '{$methodname}' on ActionHandler for action " . $this->m_action); return call_user_func_array(array(&$this, $methodname), $arguments); } } Tools::atkerror("Undefined method '{$methodname}' in ActionHandler"); return; }
/** * Add file to archive with optional filepath. * * @param string $archive archive-path * @param string $filename file to add * @param string $filepath path where file will be placed in (optional, and only for zipmode "internal") * * @return bool $result */ public function add($archive, $filename, $filepath = '') { if (!$this->test()) { Tools::atkerror('atkZip->add: Could not add, system is not capable of add to a ZIP archive'); } if ($this->m_zipmode == 'internal') { $zip = new ZipArchive(); if ($zip->open($archive) === true) { Tools::atkdebug('AtkZip::add|adding ' . $filepath . basename($filename) . " to {$archive}"); $zip->addFile($filename, $filepath . basename($filename)); $zip->close(); return true; } else { Tools::atkerror("atkZip->add: Error while opening the zip archive ({$archive})"); return false; } } if ($this->m_zipmode == 'infozip') { $params = " -j {$archive} {$filename}"; $returncode = $this->runInfozipCommand(self::ATKZIP_ZIP, $params); if ($returncode <= 0) { return true; } else { Tools::atkerror(sprintf('atkZip->add: Infozip returned an error: %s (return code %d)', $this->getInfozipError(self::ATKZIP_ZIP, $returncode), $returncode)); return false; } } return false; }
/** * Rollback the the current transaction. * * @param string $savepoint The savepoint to rollback to * * @return bool */ public function rollback($savepoint = '') { if ($this->m_link_id) { if (!empty($savepoint)) { Tools::atkdebug(get_class($this) . "::rollback (rollback to savepoint {$savepoint})"); $this->query('ROLLBACK TO SAVEPOINT ' . $savepoint); } else { Tools::atkdebug('Rollback'); mysqli_rollback($this->m_link_id); } } return true; }
/** * Function returns a generic html form for editing a record. * * @param string $mode The edit mode ("add" or "edit"). * @param array $record The record to edit. * @param array $forceList A key-value array used to preset certain * fields to a certain value. * @param array $suppressList An array of fields that will be hidden. * @param string $fieldprefix If set, each form element is prefixed with * the specified prefix (used in embedded * forms) * @param string $template The template to use for the edit form * @param bool $ignoreTab Ignore the tabs an attribute should be shown on. * * @return string the edit form as a string */ public function editForm($mode = 'add', $record = null, $forceList = '', $suppressList = '', $fieldprefix = '', $template = '', $ignoreTab = false) { $node = $this->m_node; /* get data, transform into form, return */ $data = $node->editArray($mode, $record, $forceList, $suppressList, $fieldprefix, $ignoreTab); // Format some things for use in tpl. /* check for errors and display them */ $tab = $node->getActiveTab(); $error_title = ''; $pk_err_attrib = []; $tabs = $node->getTabs($node->m_action); // Handle errors $errors = []; if (count($data['error']) > 0) { $error_title = '<b>' . Tools::atktext('error_formdataerror') . '</b>'; foreach ($data['error'] as $error) { if ($error['err'] == 'error_primarykey_exists') { $pk_err_attrib[] = $error['attrib_name']; } else { if (count($tabs) > 1 && $error['tab']) { $tabLink = $this->getTabLink($node, $error); $error_tab = ' (' . Tools::atktext('error_tab') . ' ' . $tabLink . ' )'; } else { $tabLink = null; $error_tab = ''; } if (is_array($error['label'])) { $label = implode(', ', $error['label']); } else { if (!empty($error['label'])) { $label = $error['label']; } else { if (!is_array($error['attrib_name'])) { $label = $node->text($error['attrib_name']); } else { $label = []; foreach ($error['attrib_name'] as $attrib) { $label[] = $node->text($attrib); } $label = implode(', ', $label); } } } /* Error messages should be rendered in templates using message, label and the link to the tab. */ $err = array('message' => $error['msg'], 'tablink' => $tabLink, 'label' => $label); /* * @deprecated: For backwards compatibility, we still support the msg variable as well. * Although the message, tablink variables should be used instead of msg and tab. */ $err = array_merge($err, array('msg' => $error['msg'] . $error_tab)); $errors[] = $err; } } if (count($pk_err_attrib) > 0) { // Make primary key error message $pk_err_msg = ''; for ($i = 0; $i < count($pk_err_attrib); ++$i) { $pk_err_msg .= Tools::atktext($pk_err_attrib[$i], $node->m_module, $node->m_type); if ($i + 1 < count($pk_err_attrib)) { $pk_err_msg .= ', '; } } $errors[] = array('label' => Tools::atktext('error_primarykey_exists'), 'message' => $pk_err_msg); } } /* display the edit fields */ $fields = []; $errorFields = []; $attributes = []; for ($i = 0, $_i = count($data['fields']); $i < $_i; ++$i) { $field =& $data['fields'][$i]; $tplfield = $this->createTplField($data['fields'], $i, $mode, $tab); $fields[] = $tplfield; // make field available in numeric array $params[isset($field['name']) ? $field['name'] : null] = $tplfield; // make field available in associative array $attributes[isset($field['name']) ? $field['name'] : null] = $tplfield; // make field available in associative array if (!empty($field['error'])) { $errorFields[] = $field['id']; } } $ui = $this->getUi(); $page = $this->getPage(); $page->register_script(Config::getGlobal('assets_url') . 'javascript/formsubmit.js'); // register fields that contain errornous values $page->register_scriptcode('var atkErrorFields = ' . Json::encode($errorFields) . ';'); if (Config::getGlobal('lose_changes_warning', true)) { // If we are in the save or update action the user has added a nested record, has done // a selection using the select handler or generated an error, in either way we assume // the form has been changed, so we always warn the user when leaving the page. $isChanged = 'false'; if (isset($record['atkerror']) && count($record['atkerror']) > 0 || isset($this->m_node->m_postvars['__atkunloadhelper']) && $this->m_node->m_postvars['__atkunloadhelper']) { $isChanged = 'true'; } $unloadText = addslashes($this->m_node->text('lose_changes_warning')); $page->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkunloadhelper.js'); $page->register_loadscript("new ATK.UnloadHelper('entryform', '{$unloadText}', {$isChanged});"); } $result = ''; foreach ($data['hide'] as $hidden) { $result .= $hidden; } $params['activeTab'] = $tab; $params['fields'] = $fields; // add all fields as a numeric array. $params['attributes'] = $attributes; // add all fields as an associative array $params['errortitle'] = $error_title; $params['errors'] = $errors; // Add the list of errors. Tools::atkdebug("Render editform - {$template}"); if ($template) { $result .= $ui->render($template, $params); } else { $tabTpl = $this->_getTabTpl($node, $tabs, $mode, $record); $params['fieldspart'] = $this->_renderTabs($fields, $tabTpl); $result .= $ui->render('editform_common.tpl', $params); } return $result; }
/** * 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 * * @return string The searchcondition to use. */ public function getSearchCondition(Query $query, $table, $value, $searchmode, $fieldname = '') { if ($this->createDestination() && is_array($value)) { // we are a relation, so instead of hooking ourselves into the // query, hook the attributes in the destination node onto the query foreach ($value as $key => $val) { // if we aren't searching for anything in this field, there is no need // to look any further: if ($val === '' || $val === null) { continue; } $p_attrib = $this->m_destInstance->m_attribList[$key]; if (is_object($p_attrib)) { if ($this->m_refKey && $this->createDestination()) { // master mode $new_table = $this->fieldName(); } else { // slave mode $new_table = $this->m_destInstance->m_table; // we need to left join the destination table into the query // (don't worry ATK won't add it when it's already there) $query->addJoin($new_table, $new_table, $this->getJoinCondition($query), false); } $p_attrib->searchCondition($query, $new_table, $val, $this->getChildSearchMode($searchmode, $p_attrib->fieldName())); } else { // attribute not found in destination, so it should // be in the owner (this is the case when extra fields // are in the relation $p_attrib = $this->m_ownerInstance->m_attribList[$key]; if (is_object($p_attrib)) { $p_attrib->searchCondition($query, $p_attrib->getOwnerInstance()->getTable(), $val, $this->getChildSearchMode($searchmode, $p_attrib->fieldName())); } else { Tools::atkdebug("Field {$key} was not found in this relation (this is very weird)"); } } } } else { // we were passed a value that is not an array, so appearantly the function calling us // does not know we are a relation, not just another attrib // so we assume that it is looking for something in the descriptor def of the destination if ($this->createDestination()) { $descfields = $this->m_destInstance->descriptorFields(); foreach ($descfields as $key) { $p_attrib = $this->m_destInstance->m_attribList[$key]; if (is_object($p_attrib)) { if ($this->m_refKey && $this->createDestination()) { // master mode $new_table = $this->fieldName(); } else { // slave mode $new_table = $this->m_destInstance->m_table; // we need to left join the destination table into the query // (don't worry ATK won't add it when it's already there) $query->addJoin($new_table, $new_table, $this->getJoinCondition($query), false); } $p_attrib->searchCondition($query, $new_table, $value, $searchmode); } } } } }
/** * Validate a record. * * @param string $mode Override the mode * @param array $ignoreList Override the ignoreList */ public function validate($mode = '', $ignoreList = array()) { // check overrides if (count($ignoreList)) { $this->setIgnoreList($ignoreList); } if ($mode != '') { $this->setMode($mode); } Tools::atkdebug('validate() with mode ' . $this->m_mode . ' for node ' . $this->m_nodeObj->atkNodeUri()); // set the record $record =& $this->m_record; // Check flags and values $db = $this->m_nodeObj->getDb(); foreach ($this->m_nodeObj->m_attribIndexList as $attribdata) { $attribname = $attribdata['name']; if (!Tools::atk_in_array($attribname, $this->m_ignoreList)) { $p_attrib = $this->m_nodeObj->m_attribList[$attribname]; $this->validateAttributeValue($p_attrib, $record); if ($p_attrib->hasFlag(Attribute::AF_PRIMARY) && !$p_attrib->hasFlag(Attribute::AF_AUTO_INCREMENT)) { $atkorgkey = $record['atkprimkey']; if ($atkorgkey == '' || $atkorgkey != $this->m_nodeObj->primaryKey($record)) { $cnt = $this->m_nodeObj->select($this->m_nodeObj->primaryKey($record))->ignoreDefaultFilters(true)->ignorePostvars(true)->getRowCount(); if ($cnt > 0) { Tools::triggerError($record, $p_attrib, 'error_primarykey_exists'); } } } // if no root elements may be added to the tree, then every record needs to have a parent! if ($p_attrib->hasFlag(Attribute::AF_PARENT) && $this->m_nodeObj->hasFlag(TreeNode::NF_TREE_NO_ROOT_ADD) && $this->m_nodeObj->m_action == 'save') { $p_attrib->m_flags |= Attribute::AF_OBLIGATORY; } // validate obligatory fields (but not the auto_increment ones, because they don't have a value yet) if ($p_attrib->hasFlag(Attribute::AF_OBLIGATORY) && !$p_attrib->hasFlag(Attribute::AF_AUTO_INCREMENT) && $p_attrib->isEmpty($record)) { Tools::atkTriggerError($record, $p_attrib, 'error_obligatoryfield'); } else { if ($p_attrib->hasFlag(Attribute::AF_UNIQUE) && !$p_attrib->hasFlag(Attribute::AF_PRIMARY) && !$p_attrib->isEmpty($record)) { $condition = $this->m_nodeObj->getTable() . ".{$attribname}='" . $db->escapeSQL($p_attrib->value2db($record)) . "'"; if ($this->m_mode != 'add') { $condition .= ' AND NOT (' . $this->m_nodeObj->primaryKey($record) . ')'; } $cnt = $this->m_nodeObj->select($condition)->ignoreDefaultFilters(true)->ignorePostvars(true)->getRowCount(); if ($cnt > 0) { Tools::atkTriggerError($record, $p_attrib, 'error_uniquefield'); } } } } } if (isset($record['atkerror']) && count($record['atkerror']) > 0) { for ($i = 0, $_i = count($record['atkerror']); $i < $_i; ++$i) { $record['atkerror'][$i]['node'] = $this->m_nodeObj->m_type; } } $this->validateUniqueFieldSets($record); if (isset($record['atkerror'])) { for ($i = 0, $_i = count($record['atkerror']); $i < $_i; ++$i) { $record['atkerror'][$i]['node'] = $this->m_nodeObj->m_type; } return false; } return true; }
/** * Sets the restrictions on passwords. * * @param array $restrictions Restrictions that should apply to this attribute */ public function setRestrictions($restrictions) { $this->m_restrictions = array('minsize' => 0, 'minupperchars' => 0, 'minlowerchars' => 0, 'minalphabeticchars' => 0, 'minnumbers' => 0, 'minspecialchars' => 0); if (is_array($restrictions)) { foreach ($restrictions as $name => $value) { if (in_array(strtolower($name), array('minsize', 'minupperchars', 'minlowerchars', 'minalphabeticchars', 'minnumbers', 'minspecialchars'))) { $this->m_restrictions[strtolower($name)] = $value; } else { Tools::atkdebug("atkPasswordAttribute->setRestrictions(): Unknown restriction: \"{$name}\"=\"{$value}\"", Tools::DEBUG_WARNING); } } } }
public function registerModule($moduleClass) { $reflection = new \ReflectionClass($moduleClass); $name = $reflection->getStaticPropertyValue('module'); $this->g_modules[$name] = $moduleClass; if (!self::isModule($name)) { Tools::atkdebug("Constructing a new module - {$name}"); $modClass = $this->g_modules[$name]; /** @var Menu $menuClass */ $menuClass = Config::getGlobal('menu'); $menu = $menuClass::getInstance(); /* @var \Sintattica\Atk\Core\Module $module */ $module = new $modClass(static::$s_instance, $menu); $this->g_moduleRepository[$name] = $module; $module->register(); } }
/** * Returns a piece of html code that can be used in a form to edit this * attribute's value. * * @param array $record The record that holds the value for this attribute. * @param string $fieldprefix The fieldprefix to put in front of the name * of any html form element for this attribute. * @param string $mode The mode we're in ('add' or 'edit') * * @return string A piece of htmlcode for editing this attribute */ public function edit($record, $fieldprefix, $mode) { if ($this->m_default == "NOW" && $this->m_ownerInstance->m_action == "add" || $this->m_default == "" && $this->hasFlag(self::AF_OBLIGATORY) && !$this->hasFlag(self::AF_TIME_DEFAULT_EMPTY)) { $this->m_default = date("H:i:s"); } $default = explode(":", $this->m_default); $id = $this->getHtmlId($fieldprefix); $name = $this->getHtmlName($fieldprefix); $field = Tools::atkArrayNvl($record, $this->fieldName()); if ($field && !is_array($field)) { $field = self::parseTime($field); } $onChangeCode = ''; if (count($this->m_onchangecode)) { $this->_renderChangeHandler($fieldprefix); $onChangeCode = ' onChange="' . $this->getHtmlId($fieldprefix) . '_onChange(this);"'; } $m_hourBox = '<select id="' . $id . '[hours]" name="' . $name . "[hours]\" class=\"atktimeattribute form-control select-standard\"{$onChangeCode}>\n"; $m_minBox = '<select id="' . $id . '[minutes]" name="' . $name . "[minutes]\" class=\"atktimeattribute form-control select-standard\"{$onChangeCode}>\n"; $m_secBox = '<select id="' . $id . '[seconds]" name="' . $name . "[seconds]\" class=\"atktimeattribute form-control select-standard\"{$onChangeCode}>\n"; if (is_array($field)) { $m_defHour = $field['hours']; $m_defMin = $field['minutes']; $m_defSec = $field['seconds']; } else { $m_defHour = $default[0]; $m_defMin = $default[1]; $m_defSec = $default[2]; } Tools::atkdebug("defhour={$m_defHour} defmin={$m_defMin}"); // generate hour dropdown if (!$this->hasFlag(self::AF_OBLIGATORY) || $this->hasFlag(self::AF_TIME_DEFAULT_EMPTY)) { $m_hourBox .= '<option value=""' . ($m_defHour === '' ? ' selected' : '') . '></option>'; } for ($i = $this->m_beginTime; $i <= $this->m_endTime; ++$i) { if ($m_defHour !== '' && $i == $m_defHour) { $sel = ' selected'; } else { $sel = ''; } $m_hourBox .= sprintf("<option value='%02d'%s>%02d</option>\n", $i, $sel, $i); } // generate minute dropdown if (!$this->hasFlag(self::AF_OBLIGATORY) || $this->hasFlag(self::AF_TIME_DEFAULT_EMPTY)) { $m_minBox .= '<option value=""' . ($m_defMin === '' ? ' selected' : '') . '></option>'; } if ($this->hasFlag(self::AF_TIME_SECONDS)) { $minute_steps = range(00, 59); } else { $minute_steps = $this->m_steps; } for ($i = 0; $i <= count($minute_steps) - 1; ++$i) { if ($i != 0) { $prev = $minute_steps[$i - 1]; } else { $prev = -1; } if ($minute_steps[$i] >= $m_defMin && $prev < $m_defMin && $m_defMin != '') { $sel = ' selected'; } else { $sel = ''; } $m_minBox .= sprintf("<option value='%02d'%s>%02d</option>\n", $minute_steps[$i], $sel, $minute_steps[$i]); } // generate second dropdown if (!$this->hasFlag(self::AF_OBLIGATORY) || $this->hasFlag(self::AF_TIME_DEFAULT_EMPTY)) { $m_secBox .= '<option value""' . ($m_defSec === '' ? ' selected' : '') . '></option>'; } for ($i = 0; $i <= count($this->m_steps) - 1; ++$i) { if ($i != 0) { $prev = $this->m_steps[$i - 1]; } else { $prev = -1; } if ($this->m_steps[$i] >= $m_defSec && $prev < $m_defSec && $m_defSec != '') { $sel = ' selected'; } else { $sel = ''; } $m_secBox .= sprintf("<option value='%02d' %s>%02d</option>\n", $this->m_steps[$i], $sel, $this->m_steps[$i]); } // close dropdown structures $m_hourBox .= '</select>'; $m_minBox .= '</select>'; if ($this->hasFlag(self::AF_TIME_SECONDS)) { $m_secBox .= '</select>'; $m_secBox = ':' . $m_secBox; } else { $m_secBox = '<input type="hidden" id="' . $fieldprefix . $this->fieldName() . '[seconds]" name="' . $fieldprefix . $this->fieldName() . "[seconds]\" value=\"00\">\n"; } // assemble display version $timeedit = $m_hourBox . ':' . $m_minBox . $m_secBox; return '<div class="' . $this->get_class_name() . ' form-inline">' . $timeedit . '</div>'; }
/** * Wrapper function to execute an insert query. */ public function executeInsert() { $result = parent::executeInsert(); if ($result && $this->m_returnSeqValue) { $this->m_seqValue = $this->getDb()->getInsertId(); Tools::atkdebug("Value for sequence column {$this->m_tables[0]}.{$this->m_seqField}: {$this->m_seqValue}"); } return $result; }
/** * This function returns password or false, if password can't be retrieve/recreate. * * @param string $username User for which the password should be regenerated * * @return mixed string with password or false */ public function gettingPassword($username) { // Query the database for user records having the given username and return if not found $atk = Atk::getInstance(); $usernode = $atk->atkGetNode(Config::getGlobal('auth_usernode')); $selector = sprintf("%s.%s = '%s'", Config::getGlobal('auth_usertable'), Config::getGlobal('auth_userfield'), $username); $userrecords = $usernode->select($selector)->mode('edit')->includes(array(Config::getGlobal('auth_userpk'), Config::getGlobal('auth_emailfield'), Config::getGlobal('auth_passwordfield')))->getAllRows(); if (count($userrecords) != 1) { Tools::atkdebug("User '{$username}' not found."); return false; } // Retrieve the email address $email = $userrecords[0][Config::getGlobal('auth_emailfield')]; if (empty($email)) { Tools::atkdebug("Email address for '{$username}' not available."); return false; } // Regenerate the password /** @var \Sintattica\Atk\Attributes\PasswordAttribute $passwordattr */ $passwordattr = $usernode->getAttribute(Config::getGlobal('auth_passwordfield')); $newpassword = $passwordattr->generatePassword(); // Update the record in the database $userrecords[0][Config::getGlobal('auth_passwordfield')]['hash'] = password_hash($newpassword, PASSWORD_DEFAULT); $usernode->updateDb($userrecords[0], true, '', array(Config::getGlobal('auth_passwordfield'))); $usernode->getDb()->commit(); // Return true return $newpassword; }
/** * Returns the sessionmanager. * * @return SessionManager Session manager */ public static function getInstance() { static $s_instance = null; if ($s_instance == null) { Tools::atkdebug('Created a new SessionManager instance'); $s_instance = new self(); } return $s_instance; }
/** * Apply posted (normal) search criteria to query. * * @param Query $query query object * @param array $attrsByLoadType attributes by load type */ protected function _applyPostedSearchCriteriaToQuery(Query $query, array $attrsByLoadType) { $searchCriteria = Tools::atkArrayNvl($this->_getNode()->m_postvars, 'atksearch'); if (!is_array($searchCriteria) || count($searchCriteria) == 0) { return; } foreach ($searchCriteria as $key => $value) { if ($value === null || $value === '' || $this->m_mode != 'admin' && $this->m_mode != 'export' && !array_key_exists($key, $attrsByLoadType[Attribute::ADDTOQUERY])) { continue; } $attr = $this->_getNode()->getAttribute($key); if (is_object($attr)) { if (is_array($value) && isset($value[$key]) && count($value) == 1) { $value = $value[$key]; } $searchMode = $this->_getNode()->getSearchMode(); if (is_array($searchMode)) { $searchMode = $searchMode[$key]; } if ($searchMode == null) { $searchMode = Config::getGlobal('search_defaultmode'); } $attr->searchCondition($query, $this->_getNode()->getTable(), $value, $searchMode, ''); } else { Tools::atkdebug("Using default search method for {$key}"); //$condition = 'LOWER('.$this->_getNode()->getTable().'.'.$key.") LIKE LOWER('%".$this->_getDb()->escapeSQL($value, true)."%')"; $condition = $this->_getNode()->getTable() . '.' . $key . " LIKE '%" . $this->_getDb()->escapeSQL($value, true) . "%'"; $query->addSearchCondition($condition); } } }
/** * Add a query string to the debugger. * * @param string $query * * @return bool Indication if query is added */ protected function _addQuery($query) { if (!$this->m_isconsole) { // don't add queries executed by the console itself $data = $this->getDebuggerData(); $data['queries'][] = array('query' => $query, 'trace' => Tools::atkGetTrace()); Tools::atkdebug('[' . $this->consoleLink('query details', 'query', array('query_id' => count($data['queries']) - 1), true) . '] ' . htmlentities($query)); return true; } return false; }