/** * This is the actual trigger that moves the record to the recycle bin table. * * @param array $record The record that is being deleted * * @return false if there was an error, true if everything is ok */ public function preDelete($record) { Tools::atkdebug('delete performed, storing record in recyclebin'); if (isset($this->_options['node'])) { $atk = Atk::getInstance(); $node = $atk->atkGetNode($this->_options['node']); $node->addDb($record); } else { $node = clone $this->m_node; $pkFields = $node->m_primaryKey; foreach ($pkFields as $fieldName) { // We need to make sure the record in the bin has the same primary key as the original // record, so we remove Attribute::AF_AUTOINCREMENT and setForceInsert. $node->getAttribute($fieldName)->setForceInsert(true)->removeFlag(Attribute::AF_AUTO_INCREMENT); } if (isset($this->_options['table'])) { $node->setTable($this->_options['table']); } else { // default behaviour: assume table with _bin appendix $node->setTable($node->getTable() . '_bin'); } Tools::atkdebug('adding record to recyclebin'); $node->addDb($record); } return true; }
/** * This function renders the url that is used by * AdminHandler::getAddLink(). * * @return string The url for the add link for the admin page */ public function getAddUrl() { $atk = Atk::getInstance(); $node = $atk->atkGetNode($this->invoke('getAddNodeType')); return Config::getGlobal('dispatcher') . '?atknodeuri=' . $node->atkNodeUri() . '&atkaction=add'; }
/** * Create the instance of the destination. * * If succesful, the instance is stored in the m_destInstance member variable. * * @return bool true if succesful, false if something went wrong. */ public function createDestination() { if (!is_object($this->m_destInstance)) { $atk = Atk::getInstance(); $cache_id = $this->m_owner . '.' . $this->m_name; $this->m_destInstance = $atk->atkGetNode($this->m_destination, true, $cache_id); // Validate if destination was created succesfully if (!is_object($this->m_destInstance)) { Tools::atkerror("Relation with unknown nodetype '" . $this->m_destination . "' (in node '" . $this->m_owner . "')"); $this->m_destInstance = null; return false; } if ($this->hasFlag(self::AF_NO_FILTER)) { $this->m_destInstance->m_flags |= Node::NF_NO_FILTER; } foreach (array_keys($this->m_destInstance->m_attribList) as $key) { $attribute = $this->m_destInstance->m_attribList[$key]; if (is_subclass_of($attribute, 'Relation') && is_object($this->m_ownerInstance) && $attribute->m_destination == $this->m_ownerInstance->atkNodeUri()) { $attribute->m_destInstance = $this->m_ownerInstance; if (count($attribute->m_tabs) == 1 && $attribute->m_tabs[0] == 'default') { $attribute->setTabs($this->m_tabs); } } } if (!empty($this->m_descHandler)) { $this->m_destInstance->setDescriptorHandler($this); } if (!empty($this->m_descTemplate)) { $this->m_destInstance->setDescriptorTemplate($this->m_descTemplate); } } return true; }
/** * The delete method is called by the framework to inform the attribute * that the master record is deleted. * * Note that the framework only calls the method when the * self::AF_CASCADE_DELETE flag is set. When calling this method, the detail * record belonging to the master record is deleted. * * @param array $record The record that is deleted. * * @return bool true if cleanup was successful, false otherwise. */ public function delete($record) { $atk = Atk::getInstance(); $classname = $this->m_destination; $cache_id = $this->m_owner . '.' . $this->m_name; $rel = $atk->atkGetNode($classname, true, $cache_id); Tools::atkdebug("O2O DELETE for {$classname}: " . $this->m_refKey . '=' . $record[$this->m_ownerInstance->primaryKeyField()]); if ($this->m_refKey != '') { // Foreign key is in the destination node $condition = $rel->m_table . '.' . $this->m_refKey . '=' . $this->m_ownerInstance->m_attribList[$this->m_ownerInstance->primaryKeyField()]->value2db($record); } else { // Foreign key is in the source node. $condition = $rel->m_table . '.' . $rel->m_primaryKey[0] . '=' . $record[$this->fieldName()][$this->m_ownerInstance->primaryKeyField()]; } return $rel->deleteDb($condition); }
/** * Handle the error. * * @param string $errorMessage * @param string $debugMessage */ public function handle($errorMessage, $debugMessage) { $sessionManager = SessionManager::getInstance(); $sessionData =& SessionManager::getSession(); $txt_app_title = Tools::atktext('app_title'); if ($this->params['mailto'] != '') { // only if enabled.. $atk = Atk::getInstance(); $subject = '[' . $_SERVER['SERVER_NAME'] . "] {$txt_app_title} error"; $defaultfrom = sprintf('%s <%s@%s>', $txt_app_title, Config::getGlobal('identifier', 'atk'), $_SERVER['SERVER_NAME']); $from = Config::getGlobal('mail_sender', $defaultfrom); $body = "Hello,\n\nAn error seems to have occurred in the atk application named '{$txt_app_title}'.\n"; $body .= "\nThe errormessage was:\n\n" . implode("\n", is_array($errorMessage) ? $errorMessage : array()) . "\n"; $body .= "\nA detailed report follows:\n"; $body .= "\nPHP Version: " . phpversion() . "\n\n"; $body .= "\nDEBUGMESSAGES\n" . str_repeat('-', 70) . "\n"; $lines = []; for ($i = 0, $_ = count($debugMessage); $i < $_; ++$i) { $lines[] = $this->_wordwrap(Tools::atk_html_entity_decode(preg_replace('(\\[<a.*</a>\\])', '', $debugMessage[$i]))); } $body .= implode("\n", $lines); if (is_array($_GET)) { $body .= "\n\n_GET\n" . str_repeat('-', 70) . "\n"; foreach ($_GET as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 20 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } if (function_exists('getallheaders')) { $request = getallheaders(); if (count($request) > 0) { $body .= "\n\nREQUEST INFORMATION\n" . str_repeat('-', 70) . "\n"; foreach ($request as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 30 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } } if (is_array($_POST)) { $body .= "\n\n_POST\n" . str_repeat('-', 70) . "\n"; foreach ($_POST as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 20 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } if (is_array($_COOKIE)) { $body .= "\n\n_COOKIE\n" . str_repeat('-', 70) . "\n"; foreach ($_COOKIE as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 20 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } $body .= "\n\nATK CONFIGURATION\n" . str_repeat('-', 70) . "\n"; foreach ($GLOBALS as $key => $value) { if (substr($key, 0, 7) == 'config_') { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 30 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } $body .= "\n\nMODULE CONFIGURATION\n" . str_repeat('-', 70) . "\n"; foreach ($atk->g_modules as $modname => $modpath) { $modexists = file_exists($modpath) ? ' (path exists)' : ' (PATH DOES NOT EXIST!)'; $body .= $this->_wordwrap($modname . ':' . str_repeat(' ', max(1, 20 - strlen($modname))) . var_export($modpath, 1) . $modexists) . "\n"; } $body .= "\n\nCurrent User:\n" . str_repeat('-', 70) . "\n"; $user = SecurityManager::atkGetUser(); if (is_array($user) && count($user)) { foreach ($user as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 30 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } else { $body .= "Not known\n"; } if (is_object($sessionManager)) { $body .= "\n\nATK SESSION\n" . str_repeat('-', 70); $body .= "\nNamespace: " . $sessionManager->getNameSpace() . "\n"; if (isset($sessionData[$sessionManager->getNameSpace()]['stack'])) { $stack = $sessionData[$sessionManager->getNameSpace()]['stack']; for ($i = 0; $i < count($stack); ++$i) { $body .= "\nStack level {$i}:\n"; $item = isset($stack[$i]) ? $stack[$i] : null; if (is_array($item)) { foreach ($item as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 30 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } } } if (isset($sessionData[$sessionManager->getNameSpace()]['globals'])) { $ns_globals = $sessionData[$sessionManager->getNameSpace()]['globals']; if (count($ns_globals) > 0) { $body .= "\nNamespace globals:\n"; foreach ($ns_globals as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 30 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } } if (isset($sessionData['globals'])) { $globals = $sessionData['globals']; if (count($globals) > 0) { $body .= "\nGlobals:\n"; foreach ($globals as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 30 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } } } } $body .= "\n\nSERVER INFORMATION\n" . str_repeat('-', 70) . "\n"; foreach ($_SERVER as $key => $value) { $body .= $this->_wordwrap($key . str_repeat(' ', max(1, 20 - strlen($key))) . ' = ' . var_export($value, 1)) . "\n"; } //TODO: replace with some mailer object mail($this->params['mailto'], $subject, $body, "From: {$from}"); } }
/** * Gets the node and the descriptor for the current item * and returns a trace of that. * * So for instance, if we were adding a grade to a student, * it would show: * Student [ Teknoman ] - Grade [ A+ ] * * @return string The descriptortrace */ public function descriptorTrace() { $sessionData =& self::getSession(); $stack = $sessionData[$this->m_namespace]['stack'][$this->atkStackID()]; $res = []; $node = null; $module = null; $nodename = null; $stackcount = count($stack); $atk = Atk::getInstance(); for ($i = 0; $i < $stackcount; ++$i) { if (isset($stack[$i]['descriptor']) || $i == $stackcount - 1) { if ($stack[$i]['atknodeuri'] != '') { $node = $atk->atkGetNode($stack[$i]['atknodeuri']); $module = Tools::getNodeModule($stack[$i]['atknodeuri']); $nodename = Tools::getNodeType($stack[$i]['atknodeuri']); } if (is_object($node)) { $ui = Ui::getInstance(); $txt = $ui->title($module, $nodename); } else { $txt = Tools::atktext($nodename, $module); } $res[] = $txt . (isset($stack[$i]['descriptor']) ? " [ {$stack[$i]['descriptor']} ] " : ''); } } return $res; }
/** * Are we allowed to delete a record? * * @return mixed bool if allowed or string with not allowed message */ public function deleteAllowed() { if ($this->hasFlag(self::AF_RESTRICTED_DELETE)) { // Get the destination node $classname = $this->m_destination; $cache_id = $this->m_owner . '.' . $this->m_name; $atk = Atk::getInstance(); $rel = $atk->atkGetNode($classname, $cache_id); // Get the current atkselector $where = $this->translateSelector($this->m_ownerInstance->m_postvars['atkselector']); if ($where) { $childrecords = $rel->select($where)->getAllRows(); if (!empty($childrecords)) { return Tools::atktext('restricted_delete_error'); } } else { return false; } } return true; }
/** * 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; }
/** * Create instance of the intermediary link node. * * If succesful, the instance is stored in the m_linkInstance member * variable. * * @return bool True if successful, false if not. */ public function createLink() { if ($this->m_linkInstance == null) { $atk = Atk::getInstance(); $this->m_linkInstance = $atk->newAtkNode($this->m_link); // Validate if destination was created succesfully if (!is_object($this->m_linkInstance)) { Tools::atkerror("Relation with unknown nodetype '" . $this->m_link . "' (in node '" . $this->m_owner . "')"); $this->m_linkInstance = null; return false; } } return true; }
/** * Get the atkActionHandler object for a certain action. * * The default implementation returns a default handler for the action, * but derived classes may override this to return a custom handler. * * @param string $action The action for which the handler is retrieved. * * @return ActionHandler The action handler. */ public function getHandler($action) { Tools::atkdebug('self::getHandler(); action: ' . $action); //check if a handler exists registered including the module name $atk = Atk::getInstance(); $handler = $atk->atkGetNodeHandler($this->atkNodeUri(), $action); // The node handler might return a class, then we need to instantiate the handler if (is_string($handler) && class_exists($handler)) { $handler = new $handler(); } // The node handler might return a function as nodehandler. We cannot // return a function so we ignore this option. // this would probably only work fine when using PHP5, but's better then nothing? // or why support functions at all?! // handler object if ($handler != null && is_subclass_of($handler, 'ActionHandler')) { Tools::atkdebug('self::getHandler: Using existing ActionHandler ' . get_class($handler) . " class for '" . $action . "'"); $handler->setNode($this); $handler->setAction($action); } else { $handler = ActionHandler::getDefaultHandler($action); $handler->setNode($this); $handler->setPostvars($this->m_postvars); $handler->setAction($action); //If we use a default handler we need to register it to this node //because we might call it a second time. Tools::atkdebug('self::getHandler: Register default ActionHandler for ' . $this->m_type . " action: '" . $action . "'"); $atk->atkRegisterNodeHandler($this->m_type, $action, $handler); } return $handler; }
/** * Regenerates a user password and sends it to his e-mail address. * * @param string $username User for which the password should be regenerated * * @return bool */ public function mailPassword($username) { $atk = Atk::getInstance(); // Query the database for user records having the given username and return if not found $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)->includes(array(Config::getGlobal('auth_userpk'), Config::getGlobal('auth_emailfield'), Config::getGlobal('auth_passwordfield')))->mode('edit')->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 $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'))); $db = $userNode->getDb(); $db->commit(); // Send an email containing the new password to user $subject = Tools::atktext('auth_passwordmail_subjectnew_password', 'atk'); $body = Tools::atktext('auth_passwordmail_explanation', 'atk') . "\n\n"; $body .= Tools::atktext(Config::getGlobal('auth_userfield')) . ': ' . $username . "\n"; $body .= Tools::atktext(Config::getGlobal('auth_passwordfield')) . ': ' . $newPassword . "\n"; //TODO: replace with some mailer object mail($email, $subject, $body); // Return true return true; }
/** * Return the title to render. * * @param string $module the module in which to look * @param string $nodetype the nodetype of the action * @param string $action the action that we are trying to find a title for * @param bool $actiononly wether or not to return a name of the node * if we couldn't find a specific title * * @return string the title for the action */ public function title($module, $nodetype, $action = null, $actiononly = false) { if ($module == null || $nodetype == null) { return ''; } $atk = Atk::getInstance(); return $this->nodeTitle($atk->atkGetNode($module . '.' . $nodetype), $action, $actiononly); }
/** * Retrieve all possible module/node actions. * * @param array $record The record * @param bool $splitPerSection * * @return array Array with actions */ public function getAllActions($record, $splitPerSection = false) { $atk = Atk::getInstance(); $result = []; // hierarchic groups, only return actions of parent (if this record has a parent) $parentAttr = $this->m_parentAttrName; if (!empty($parentAttr) && is_numeric($record[$parentAttr])) { $db = $this->getDb(); $query = 'SELECT DISTINCT node, action FROM ' . Config::getGlobal('auth_accesstable') . ' ' . 'WHERE ' . $this->m_accessField . ' = ' . $record[$parentAttr]; $rows = $db->getRows($query); foreach ($rows as $row) { $module = Tools::getNodeModule($row['node']); $node = Tools::getNodeType($row['node']); $result[$module][$module][$node][] = $row['action']; } } else { // get nodes for each module foreach (array_keys($atk->g_modules) as $module) { $instance = $atk->atkGetModule($module); if (method_exists($instance, 'getNodes')) { $instance->getNodes(); } } // retrieve all actions after we registered all actions $result = $atk->g_nodes; } if (!$splitPerSection) { $temp = []; foreach ($result as $section => $modules) { foreach ($modules as $module => $nodes) { if (!is_array($temp[$module])) { $temp[$module] = []; } $temp[$module] = array_merge($temp[$module], $nodes); } } $result = $temp; } return $result; }
/** * Creates an instance of the node we are searching on and stores it * in a member variable ($this->m_searchnodeInstance). * * @return bool */ public function createSearchNodeInstance() { if (!is_object($this->m_searchnodeInstance)) { $atk = Atk::getInstance(); $this->m_searchnodeInstance = $atk->atkGetNode($this->m_searchnode); return is_object($this->m_searchnodeInstance); } return true; }
/** * Method for getting the relative path to the languagedirectory * of a module. * Supports 2 special modules: * - atk (returns the path of the atk languagedir) * - langoverrides (returns the path of the languageoverrides dir). * * Special method in that it can run both in static and non-static * mode. * * @param string $moduleName The module to get the languagedir for * * @return string The relative path to the languagedir */ public function getLanguageDirForModule($moduleName) { if ($moduleName == 'atk') { $path = __DIR__ . '/../Resources/' . $this->LANGDIR; } else { if ($moduleName == 'langoverrides') { $path = Config::getGlobal('language_basedir', $this->LANGDIR); } else { $atk = Atk::getInstance(); $path = $atk->moduleDir($moduleName) . $this->LANGDIR; } } return $path; }