/handlers/class.atkattributeedithandler.inc
PHP | 600 lines | 347 code | 83 blank | 170 comment | 47 complexity | cad90b1cbe45a032d72311025888f4b8 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-3.0
- <?php
- /**
- * This file is part of the Ibuildings E-business Platform.
- * Detailed copyright and licensing information can be found
- * in the doc/COPYRIGHT and doc/LICENSE files which should be
- * included in the distribution.
- *
- * @package atk
- * @subpackage handlers
- *
- * @author Dennis Luitwieler <dennis@ibuildings.nl>
- *
- * @copyright (c) 2007 Ibuildings.nl BV
- * @license see doc/LICENSE
- *
- * @version $Revision: 6310 $
- * $Id$
- */
-
- atkimport("atk.handlers.atkactionhandler");
- /**
- * Some defines
- * @access private
- */
- define("ATTRIBUTEEDIT_ERROR_DEFAULT", 1);
- define("ATTRIBUTEEDIT_ERROR_UPDATE", 2);
- define("ATTRIBUTEEDIT_ERROR_NO_SELECTOR_SET", 4);
- define("ATTRIBUTEEDIT_ERROR_VALIDATE", 8);
- /**
- * Handler for the 'attributeedit' action of a node. It shows a dialog for altering the value of
- * a selectable attribute for multiple records at the same time.
- *
- * This handler only supports dialogs.
- *
- * @author Dennis Luitwieler <dennis@ibuildings.nl>
- * @package atk
- * @subpackage handlers
- *
- */
- class atkAttributeEditHandler extends atkActionHandler
- {
- var $m_processUrl = null;
- var $m_masterNode = null;
-
- /**
- * Set the maste node
- *
- * @param atkNode $node The master node
- */
- function setMasterNode($node)
- {
- $this->m_masterNode = $node;
- }
-
- /**
- * The action method.
- */
- function action_attributeedit()
- {
- if ($this->m_masterNode == null)
- {
- $this->m_masterNode = $this->m_node;
- }
-
- $this->setRenderMode('dialog');
- if ($this->m_partial == 'process')
- {
- $this->handleProcess();
- }
- elseif ($this->m_partial == 'refreshvaluefield')
- {
- $this->handleRefreshValuesField();
- }
- else
- {
- $atkselector = $this->getSelector();
- if (!isset($atkselector) || $atkselector=="")
- {
- $this->handleError(ATTRIBUTEEDIT_ERROR_NO_SELECTOR_SET, null, false);
- }
- else
- {
- $this->handleDialog();
- }
- }
- }
- /**
- * Get the atkselector from the postvars.
- *
- * The atkselector could be prefixed, depending on the page where we come
- * from. From the admin page it will be prefixed with the formname, from the
- * attributeedit dialog, it will not be prefixed anymore.
- *
- * @return Array
- */
- function getSelector()
- {
- // The selector should be in the atkselector postvar
- return $this->m_node->m_postvars['atkselector'];
- }
- /**
- * Handle dialog partial.
- */
- function handleDialog()
- {
- $page = &$this->getPage();
- $result = $this->invoke('attributeEditPage');
- $page->addContent($result);
- }
- /**
- * Handle process partial.
- */
- function handleProcess()
- {
- $node = &$this->m_node;
- $page = &$this->getPage();
- $atkselector = $this->getSelector();
- if (!isset($atkselector) || count($atkselector)==0)
- {
- $this->handleError(ATTRIBUTEEDIT_ERROR_NO_SELECTOR_SET);
- return;
- }
-
- $attributename = $node->m_postvars["attributename"];
- $attributevalue = $node->m_postvars[$attributename];
- $attribute = $node->getAttribute($attributename);
-
- /** check if input is correct ... */
- if (!is_object($attribute) || empty($attributename))
- {
- $this->handleError(ATTRIBUTEEDIT_ERROR_DEFAULT);
- return;
- }
- // All updates and validates will be successfully executed, until proven otherwise
- $validate = true;
- $success = true;
- foreach ($atkselector as $selector)
- {
- list($rec) = $node->selectDb($selector, "", "", "", array($attributename));
- $rec[$attributename] = $attribute->fetchValue($node->m_postvars);
- // Get all the attributes we are NOT changing.
- $ignoreList = $this->getIgnoreList($attributename);
- // Try to validate the new record.
- if (!$node->validate($rec, 'edit', $ignoreList))
- {
- $validate = false;
- break;
- }
- // If the validation succeeded, we will get here and try to perform the update.
- if (!$node->updateDb($rec, false, "", array($attributename)))
- {
- $success = false;
- triggerError($rec, $attributename, $node->getDb()->getErrorType(), $node->getDb()->getErrorMsg());
- break;
- }
- }
- // on succes, commit the changes and refresh the page where this dialog was initiated.
- if ($validate && $success)
- {
- $node->getDb()->commit();
- $content = "<script type=\"text/javascript\">document.location.href = document.location.href;</script>";
- $page->addContent($content);
- return;
- }
- // On validation error, show a validation error message.
- if (!$validate)
- {
- $this->handleError(ATTRIBUTEEDIT_ERROR_VALIDATE, $rec, true);
- return;
- }
- // On failure, do a rollback (if the db supports it) and show an error page.
- $node->getDb()->rollback();
- $this->handleError(ATTRIBUTEEDIT_ERROR_UPDATE, $rec, true);
- }
- /**
- * Handle errors of different types.
- *
- * @param int $error The AttributeEditHandler error type.
- * @param array $record The record
- * @param bool $reload Reload the page?
- */
- function handleError($error, $record=null, $reload=false)
- {
- atkimport('atk.ui.atkdialog');
- $this->registerExternalFiles();
- $content = $this->getErrorPage($error, $record);
- $page = &$this->getPage();
- if (!$reload)
- {
- $page->addContent($content);
- }
- else
- {
- $script = atkDialog::getUpdateCall($content, false);
- $page->register_loadscript($script);
- }
- }
- /**
- * Get a page indicating an error has occurred.
- *
- * @param Int $error
- * @param array $record The record
- * @param String $customerror
- * @return String HTML Error page
- */
- function getErrorPage($error, $record=null, $customerror='')
- {
- $errortext = '';
- if ($customerror != '')
- {
- $errortext = $customerror;
- }
- elseif ($error == ATTRIBUTEEDIT_ERROR_UPDATE)
- {
- $errortext = $this->m_node->text('error_attributeedit_update');
- }
- elseif ($error == ATTRIBUTEEDIT_ERROR_NO_SELECTOR_SET)
- {
- $errortext = $this->m_node->text("error_attributeedit_noselectorset");
- }
- elseif ($error == ATTRIBUTEEDIT_ERROR_VALIDATE)
- {
- $errortext = $this->m_node->text("error_attributeedit_validationfailed");
- }
- else // Other errors
- {
- $errortext = $this->m_node->text('error_attributeedit_default');
- }
- $errormsg = '';
- if (isset($record) && isset($record['atkerror']))
- {
- $errormsg = $record['atkerror']['attrib_name'].': '.$record['atkerror']['msg'].' ';
- }
- $ui = &$this->m_node->getUi();
- atkimport('atk.ui.atkdialog');
- $params = array();
- $params["content"] = "<b>".$errortext."</b><br />";
- $params["content"].= $errormsg;
- $params["buttons"][] = '<input type="button" class="btn_cancel" value="'.$this->m_node->text('close').'" onClick="'.atkDialog::getCloseCall().'" />';
- $content = $ui->renderAction("attributeedit", $params);
- $params = array();
- $params["title"] = $this->m_node->actionTitle('attributeedit');
- $params["content"] = $content;
- $content = $ui->renderDialog($params);
- return $content;
- }
- /**
- * AttributeEdit page.
- *
- * @return String The attribute edit page
- */
- function attributeEditPage()
- {
- return $this->getAttributeEditPage();
- }
- /**
- * Returns the attributeEdit page contents.
- *
- * @return string attributeEdit page contents
- */
- function getAttributeEditPage()
- {
- $url = $this->getProcessUrl();
- $controller = &atkController::getInstance();
- $this->registerExternalFiles();
- $params = array();
- $params["formstart"] = $this->getFormStart();
- $params["formend"] = '</form>';
- $params["content"] = $this->getContent();
- $params["buttons"][] = $controller->getDialogButton('save', $this->m_node->text('update_value'), $url);
- $params["buttons"][] = $controller->getDialogButton('cancel');
- return $this->renderAttributeEditPage($params);
- }
- /**
- * Register external files
- *
- */
- function registerExternalFiles()
- {
- $page = &$this->getPage();
- $ui = &$this->getUi();
- $page->register_script(atkconfig("atkroot")."atk/javascript/tools.js");
- $page->register_script(atkconfig('atkroot').'atk/javascript/class.atkattributeedithandler.js');
- $page->register_style($ui->stylePath("style.css"));
- }
- /**
- * Render the add or copy page using the given parameters.
- *
- * @param array $params parameters
- * @return string rendered page
- */
- function renderAttributeEditPage($params)
- {
- $node = &$this->m_node;
- $ui = &$node->getUi();
- $output = $ui->renderAction("add", $params);
- $this->addRenderBoxVar("title", $node->actionTitle('addorcopy'));
- $this->addRenderBoxVar("content", $output);
- $total = $ui->renderDialog($this->m_renderBoxVars);
- return $total;
- }
- /**
- * Returns the attributeEdit page contents.
- *
- * @return string attributeEdit page contents
- */
- function getContent()
- {
- $content = '
- <div id="dialogcontent">' .
- $this->_getDropDownAttributes() .
- '<br />
- <div id="selectedvaluediv">' .
- $this->_getDropDownValues() .
- '</div>
- </div>';
- return $content;
- }
- /**
- * Get dropdown attributes
- *
- * @param string $selectedAttribute
- * @return String Dropdown with attributenames
- */
- function _getDropDownAttributes($selectedAttribute="")
- {
- $fieldprefix = $this->m_node->m_postvars['atkfieldprefix'];
- if ($fieldprefix == '') $fieldprefix = $this->m_node->getEditFieldPrefix();
- $attributes = $this->getSupportedAttributes();
- $attr = null;
- // Select the first attribute if none is selected
- if ($selectedAttribute=="")
- {
- // select the first (if available)
- $record['attributename'] = isset($attributes[0]) ? $attributes[0]->fieldName() : null;
- }
- else
- {
- $record['attributename'] = $selectedAttribute;
- }
- // Create options and values
- foreach ($attributes as $attribute)
- {
- $options[] = $this->m_node->text($attribute->label($record));
- $values[] = $attribute->fieldName();
- }
- $list = &new atkListAttribute('attributename', $options, $values);
- $list->addFlag(AF_LIST_NO_NULL_ITEM);
- $list->m_ownerInstance = &$this->m_node;
- $list->addOnChangeHandler($this->onChange());
- return $list->edit($record,$fieldprefix);
- }
- /**
- * Return the onchange code
- *
- * @return String The onchange javascript code
- */
- function onChange()
- {
- $url = partial_url($this->m_masterNode->atkNodeType(), 'attributeedit', 'refreshvaluefield');
- $script = "
- ATK.AttributeEditHandler.refreshvalues('$url');
- ";
- return $script;
- }
- /**
- * Get the dropdown with the possible values for
- * the selected attribute.
- *
- * @param String $selectedAttribute
- * @return unknown
- */
- function _getDropDownValues($selectedAttribute="")
- {
- $fieldprefix = $this->m_node->m_postvars['atkfieldprefix'];
- $attr = null;
- // Select the first attribute if none is selected
- if ($selectedAttribute=="")
- {
- // get first attribute
- list($attr) = $this->getSupportedAttributes();
- }
- else
- {
- $attr = &$this->m_node->getAttribute($selectedAttribute);
- }
- if (is_object($attr))
- {
- $record[$attr->fieldName()] = $this->m_node->m_postvars[$attr->fieldName()];
- return $attr->edit($record, $fieldprefix, 'edit');
- }
- return "";
- }
- /**
- * Get the supported attributes.
- *
- * If no supported attributes were set, ATK determines them by itself.
- *
- * @return array Array with attribute objects
- */
- function getSupportedAttributes()
- {
- $supported = array();
- if (method_exists($this->m_node, 'getAttributeEditSupportedAttributes'))
- {
- $supported_attributes = $this->m_node->getAttributeEditSupportedAttributes();
- if (isset($supported_attributes) && is_array($supported_attributes))
- {
- foreach ($supported_attributes as $attribname)
- {
- $attr = $this->m_node->getAttribute($attribname);
- if (is_object($attr))
- $supported[] = $attr;
- }
- }
- return $supported;
- }
- // We let ATK determine the available attributes.
- $attributes = $this->m_node->getAttributes();
- // We do not need certain attributes.
- foreach ($attributes as $index=>$attr)
- {
- // Attributes without labels will not be selectable.
- if ($attr->hasFlag(AF_NO_LABEL) || $attr->hasFlag(AF_BLANK_LABEL))
- continue;
- // Hidden attributes will not be selectable
- if ($attr->hasFlag(AF_HIDE) || $attr->hasFlag(AF_HIDE_EDIT))
- continue;
- // You cannot give multiple records a value for a field that should be unique.
- $atkselector = $this->getSelector();
- if (isset($atkselector) && count($atkselector)>1 && $attr->hasFlag(AF_UNIQUE))
- continue;
- // You cannot update readonly fields
- if ($attr->hasFlag(AF_READONLY) || $attr->hasFlag(AF_READONLY_EDIT))
- continue;
- // We do not support manytomany relations (for now...).
- if (is_a($attr, 'atkmanytomanyrelation'))
- continue;
- $supported[] = $attr;
- }
- return $supported;
- }
- /**
- * Get a list of attributenames that we can ignore (i.e. when calling
- * validate() on a node.)
- *
- * @param String $selectedattributename
- * @return Array A list of attributenames.
- */
- function getIgnoreList($selectedattributename)
- {
- $attributes = $this->m_node->getAttributes();
- $attribnames = array();
- foreach ($attributes as $attr)
- {
- $attribnames[] = $attr->fieldName();
- }
- // remove the selected attribute from all the available attributes,
- // and we have a list of attributes that we can ignore.
- return array_diff($attribnames, array($selectedattributename));
- }
- /**
- * Returns the form start.
- *
- * @return string Html form start
- */
- function getFormStart()
- {
- $controller = &atkcontroller::getInstance();
- $controller->setNode($this->m_node);
- $formstart = '<form id="dialogform" name="dialogform" action="'.$controller->getPhpFile().'?'.SID.'" method="post">';
- $atkselector = $this->getSelector();
- if (isset($atkselector))
- {
- foreach ($atkselector as &$selector)
- {
- $formstart.= '<input type="hidden" id="atkselector[]" name="atkselector[]" value="'.$selector.'">';
- }
- }
- return $formstart;
- }
- /**
- * Handle refresh values
- *
- */
- function handleRefreshValuesField()
- {
- $page = &$this->getPage();
- atkimport('atk.utils.atkjson');
- // get selected attribute
- $selectedattribute = $this->m_node->m_postvars["attributename"];
- $field = $this->_getDropDownValues($selectedattribute);
- $keys = implode(',', array_keys($this->m_node->m_postvars));
- $content = "<script type=\"text/javascript\">$('selectedvaluediv').innerHTML = ".atkJSON::encode($field)."</script>";
- $page->addContent($content);
- }
- /**
- * Returns the process URL.
- *
- * @return string process URL
- */
- function getProcessUrl()
- {
- if ($this->m_processUrl != null)
- {
- return $this->m_processUrl;
- }
- else
- {
- return partial_url($this->m_masterNode->atkNodeType(), 'attributeedit', 'process');
- }
- }
- /**
- * Override the default process URL.
- *
- * @param string $url process URL
- */
- function setProcessUrl($url)
- {
- $this->m_processUrl = $url;
- }
- }
- ?>