/library/Adapto/Attribute.php
PHP | 1980 lines | 659 code | 214 blank | 1107 comment | 158 complexity | 3417581a86029525812ff761dc1bb95e MD5 | raw file
- <?php
- /**
- * This file is part of the Adapto Toolkit.
- * Detailed copyright and licensing information can be found
- * in the doc/COPYRIGHT and doc/LICENSE files which should be
- * included in the distribution.
- *
- * @package adapto
- * @subpackage attributes
- *
- * @copyright (c)2000-2006 Ivo Jansch
- * @copyright (c)2000-2006 Ibuildings.nl BV
- * @license http://www.achievo.org/atk/licensing ATK Open Source License
- *
- */
- /**
- * Attributeflags. The following flags can be used for attributes
- * @internal WARNING: flags may *not* exceed 2^31 (2147483648), because
- * that's the integer limit beyond which the bitwise operators won't
- * work anymore!
- */
- /**
- * Value must be entered
- *
- * "database-level" processing flag
- */
- define("AF_OBLIGATORY", 1);
- /**
- * Value must be unique
- *
- * "database-level" processing flag
- */
- define("AF_UNIQUE", 2);
- /**
- * Part of the primary-key entity, also makes it obligatory
- *
- * "database-level" processing flag
- */
- define("AF_PRIMARY", 4 | AF_OBLIGATORY);
- /**
- * Auto-increment field
- *
- * "database-level" processing flag
- */
- define("AF_AUTO_INCREMENT", 8);
- /**
- * Alias for AF_AUTO_INCREMENT (auto-increment flag is often mistyped)
- *
- * "database-level" processing flag
- */
- define("AF_AUTOINCREMENT", AF_AUTO_INCREMENT);
- /**
- * Don't show in record lists
- *
- * hide flag
- */
- define("AF_HIDE_LIST", 16);
- /**
- * Don't show on add pages
- *
- * hide flag
- */
- define("AF_HIDE_ADD", 32);
- /**
- * Don't show on edit pages
- *
- * hide flag
- */
- define("AF_HIDE_EDIT", 64);
- /**
- * Don't show on select pages
- *
- * hide flag
- */
- define("AF_HIDE_SELECT", 128);
- /**
- * Don't show on view pages
- *
- * hide flag
- */
- define("AF_HIDE_VIEW", 256);
- /**
- * Not searchable in extended search
- *
- * hide flag
- */
- define("AF_HIDE_SEARCH", 512); // not searchable in extended search
- /**
- * Load always, even if not displayed anywhere
- *
- * hide flag
- */
- define("AF_FORCE_LOAD", 1024); // load always, even if not displayed anywhere
- /**
- * Attribute is totally hidden
- *
- * hide flag
- */
- define("AF_HIDE",
- AF_HIDE_EDIT | AF_HIDE_ADD | // attribute is totally hidden
- AF_HIDE_LIST | AF_HIDE_SEARCH | AF_HIDE_VIEW | AF_HIDE_SELECT);
- /**
- * Readonly in add
- *
- * readonly flag
- */
- define("AF_READONLY_ADD", 2048); // readonly in add
- /**
- * Readonly when edited
- *
- * readonly flag
- */
- define("AF_READONLY_EDIT", 4096); // readonly when edited
- /**
- * Always readonly
- *
- * readonly flag
- */
- define("AF_READONLY", AF_READONLY_EDIT | AF_READONLY_ADD); // always readonly
- /**
- * No label in forms
- *
- * display-related processing flag
- */
- define("AF_NO_LABEL", 8192); // no label in forms
- /**
- * Alias for AF_NO_LABEL (mistyped)
- *
- * display-related processing flag
- */
- define("AF_NOLABEL", AF_NO_LABEL); // no label (mistyped)
- /**
- * Blank label in forms
- *
- * display-related processing flag
- */
- define("AF_BLANK_LABEL", 16384); // blank label in forms
- /**
- * Alias for AF_BLANK_LABEL (mistyped)
- *
- * display-related processing flag
- */
- define("AF_BLANKLABEL", AF_BLANK_LABEL); // blank label (mistyped)
- /**
- * Cannot be sorted in recordlists
- *
- * display-related processing flag
- */
- define("AF_NO_SORT", 32768); // cannot be sorted in recordlists.
- /**
- * Alias for AF_NO_SORT (mistyped)
- *
- * display-related processing flag
- */
- define("AF_NOSORT", AF_NO_SORT); // no-sort flag is often mistyped
- /**
- * Attribute is searchable in list views
- *
- * display-related processing flag
- */
- define("AF_SEARCHABLE", 65536); // Attribute is searchable in list views
- /**
- * The attribute will have a 'total' column in lists
- *
- * display-related processing flag
- */
- define("AF_TOTAL", 131072); // The attribute will have a 'total' column in lists.
- /**
- * If supported, use pop-up window
- *
- * display-related processing flag
- */
- define("AF_POPUP", 262144); // if supported, use pop-up window
- /**
- * Delete function is called when owning entity is deleted
- *
- * miscellaneous processing flag
- */
- define("AF_CASCADE_DELETE", 524288); // delete function is called when owning entity is deleted
- /**
- * Will have a large amount of recors (relation)
- *
- * Instead of showing a listbox with all the records it will show an add link to a select page
- *
- * miscellaneous processing flag
- */
- define("AF_LARGE", 1048576); // will have a large ammount of records (relation)
- /**
- * Ignore filters when selecting records (relation)
- *
- * miscellaneous processing flag
- */
- define("AF_NO_FILTER", 2097152); // ignore filters when selecting records (relation)
- /**
- * Parent field for parent child relations (treeview)
- *
- * miscellaneous processing flag
- */
- define("AF_PARENT", 4194304); // parent field for parent child relations (treeview)
- /**
- * No quotes are used when adding to the database
- *
- * miscellaneous processing flag
- */
- define("AF_NO_QUOTES", 8388608); // no quotes are used when adding to database
- /**
- * Multi-language field
- *
- * miscellaneous processing flag
- */
- define("AF_ML", 16777216); // multi-language field
- /**
- * Alias for AF_ML (spelled out)
- *
- * miscellaneous processing flag
- */
- define("AF_MULTILANGUAGE", AF_ML);
- /**
- * Shortcut for hidden auto-incremented primary key
- *
- * miscellaneous processing flag
- */
- define("AF_AUTOKEY", AF_PRIMARY | AF_HIDE | // shortcut for hidden auto-incremented primary-key
- AF_AUTOINCREMENT);
- /*
- * flag (values) that can be used for attribute specific flags
- * NOTE: Attribute specific flags aren't good behaviour, but for
- * compatibility reasons we support them anyway. Newly derived attributes
- * should not use these specific flags, but work with extra parameters.
- */
- /**
- * Specific attribute flag 1
- */
- define("AF_SPECIFIC_1", 33554432); // specific attribute flag 1
- /**
- * Specific attribute flag 2
- */
- define("AF_SPECIFIC_2", 67108864); // specific attribute flag 2
- /**
- * Specific attribute flag 3
- */
- define("AF_SPECIFIC_3", 134217728); // specific attribute flag 3
- /**
- * Specific attribute flag 4
- */
- define("AF_SPECIFIC_4", 268435456); // specific attribute flag 4
- /**
- * Specific attribute flag 5
- */
- define("AF_SPECIFIC_5", 536870912); // specific attribute flag 5
- /**
- * Do not store this attribute
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("NOSTORE", 0);
- /**
- * Do not load this attribute
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("NOLOAD", 0);
- /**
- * Store before all other ('normal') attributes (?)
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("PRESTORE", 1);
- /**
- * Call load before selectDb()
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("PRELOAD", 1);
- /**
- * Store after all other ('normal') attributes (?)
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("POSTSTORE", 2);
- /**
- * Call load after selectDb()
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("POSTLOAD", 2);
- /**
- * Do addToQuery() of this attribute
- *
- * Storage type flag, used by the storageType() and related methods
- */
- define("ADDTOQUERY", 4);
- /**
- * Attribute is disable in view mode
- */
- define("DISABLED_VIEW", 1);
- /**
- * Attribute is disable in edit mode
- */
- define("DISABLED_EDIT", 2);
- /**
- * Attribute is disabled in view and edit mode
- */
- define("DISABLED_ALL", DISABLED_VIEW | DISABLED_EDIT);
- /**
- * The Adapto_Attribute class represents an attribute of an atkEntity.
- * An Adapto_Attribute has a name and a set of parameters that
- * control its behaviour, like whether an Adapto_Attribute
- * is obligatory, etc.
- *
- * @author ijansch
- * @package adapto
- * @subpackage attributes
- */
- class Adapto_Attribute
- {
- /**
- * The name of the attribute
- * @access private
- * @var String
- */
- public $m_name; // defaulted to public
- /**
- * The attribute flags (see above)
- * @access private
- * @var int
- */
- public $m_flags = 0; // defaulted to public
- /**
- * The name of the atkEntity that owns this attribute (set by atkentity)
- * @access private
- * @var String
- */
- public $m_owner = ""; // defaulted to public
- /**
- * The module of the attribute (if empty, the module from the owner entity
- * should be assumed).
- * @access private
- * @var String
- *
- */
- public $m_module = ""; // defaulted to public
- /**
- * Instance of the atkEntity that owns this attribute
- * @access private
- * @var atkEntity
- */
- public $m_ownerInstance = ""; // defaulted to public
- /**
- * The size the attribute's field.
- * @access private
- * @var int
- */
- public $m_size = 0; // defaulted to public
- /**
- * The size the attribute's search input field.
- * @access private
- * @var int
- */
- public $m_searchsize = 0; // defaulted to public
- /**
- * The maximum size the attribute's value may have in the database.
- * @access private
- * @var int
- */
- public $m_maxsize = 0; // defaulted to public
- /**
- * The database fieldtype.
- * @access private
- * @var String
- */
- public $m_dbfieldtype = ""; // defaulted to public
- /**
- * The order of the attribute within its entity.
- * @access private
- * @var int
- */
- public $m_order = 0; // defaulted to public
- /**
- * Index of the attribute within its entity.
- * @access private
- * @var int
- */
- public $m_index = 0; // defaulted to public
- /**
- * The tab(s) on which the attribute lives.
- * @access private
- * @var mixed
- */
- public $m_tabs = "*"; // defaulted to public
- /**
- * The section(s) on which the attribute lives.
- * @access private
- * @var mixed
- */
- public $m_sections = "*"; // defaulted to public
- /**
- * The id of the attribute in the HTML
- * @access private
- * @var String
- */
- public $m_htmlid; // defaulted to public
- /**
- * The css classes of the attribute
- * @access private
- * @var sttsy
- */
- public $m_cssclasses = array(); // defaulted to public
- /**
- * The label of the attribute.
- * @access private
- * @var String
- */
- public $m_label = ""; // defaulted to public
- /**
- * The postfix label of the attribute.
- * @access private
- * @var String
- */
- public $m_postfixlabel = ""; // defaulted to public
- /**
- * The searchmode for this attribute
- *
- * This var exists so that you can assign searchmodes to specific
- * attributes instead of having a general searchmode for the entire
- * search. This can be any one of the supported modes, as returned by
- * the attribute's getSearchModes() method.
- * @access private
- * @var String
- */
- public $m_searchmode = ""; // defaulted to public
- /**
- * Wether to force an insert of the attribute
- * @access private
- * @var bool
- */
- public $m_forceinsert = false; // defaulted to public
- /**
- * Wether to force a reload of the attribute ignoring the saved session data
- *
- * @access private
- * @var bool
- */
- public $m_forcereload = false; // defaulted to public
- /**
- * Wether to force an update of the attribute
- * @access private
- * @var bool
- */
- public $m_forceupdate = false; // defaulted to public
- /**
- * Array for containing onchange javascript code
- * @access private
- * @var Array
- */
- public $m_onchangecode = array(); // defaulted to public
- /**
- * Variable to store initialisation javascript code
- * in for the changehandler.
- * @access private
- * @var String
- */
- public $m_onchangehandler_init = ""; // defaulted to public
- /**
- * Variable to store dependency callbacks.
- *
- * @var array
- */
- private $m_dependencies = array();
- /**
- * Attribute to store disabled modes.
- * @access private
- * @var int
- */
- public $m_disabledModes = 0; // defaulted to public
- /**
- * Whether to hide initially or not
- * @access private
- * @var bool
- */
- public $m_initial_hidden = false; // defaulted to public
- /**
- * Storage type.
- * @access private
- * @var int
- * @see setStorageType
- */
- public $m_storageType = array(); // defaulted to public
- /**
- * Load type.
- * @access private
- * @var int
- * @see setLoadType
- */
- public $m_loadType = array(); // defaulted to public
- /**
- * Initial value.
- * @access private
- * @var mixed
- * @see setInitialValue
- */
- public $m_initialValue = NULL; // defaulted to public
- /**
- * Column.
- *
- * @var string
- */
- private $m_column;
- /**
- * JavaScript observers. Key is the event name
- * value is an array with event handlers.
- *
- * @var array
- */
- private $m_jsObservers = array();
- /**
- * View callback.
- *
- * @var mixed
- */
- private $m_viewCallback = null;
- /**
- * Edit callback.
- *
- * @var mixed
- */
- private $m_editCallback = null;
- /**
- * Constructor
- *
- * <b>Example:</b>
- * $this->add(new Adapto_Attribute("name",AF_OBLIGATORY, 30));
- *
- * Note: If you want to use the db/ddl utility class to
- * automatically generate the table, the $size parameter must be
- * set, for it will use the size specified here to determine the
- * field length. (Derived classes might have reasonable default
- * values, but the standard Adapto_Attribute doesn't.)
- *
- * @param String $name Name of the attribute (unique within an entity, and
- * for most attributes, corresponds to a field in
- * the database.
- * @param int $flags Flags for the attribute.
- * @param mixed $size The size(s) of the attribute. See the $size
- * parameter of the setAttribSize() method for more
- * information on the possible values of this
- * parameter.
- *
- */
- public function __construct($name, $flags = 0, $size = 0)
- {
- $this->m_name = $name;
- $this->setFlags((int) $flags);
- $this->setAttribSize($size);
- // default class
- $this->addCSSClass(get_class($this));
- }
- /**
- * Returns the owner instance.
- *
- * @return atkEntity owner instance
- */
- function &getOwnerInstance()
- {
- return $this->m_ownerInstance;
- }
- /**
- * Sets the owner instance.
- *
- * @param atkEntity $instance
- */
- function setOwnerInstance(&$instance)
- {
- $this->m_ownerInstance = &$instance;
- }
- /**
- * Check if the attribute has a certain flag.
- * @param int $flag The flag you want to check
- * @return boolean
- */
- function hasFlag($flag)
- {
- return (($this->m_flags & $flag) == $flag);
- }
- /**
- * Returns the full set of flags of the attribute.
- * @return int $m_flags The full set of flags
- */
- function getFlags()
- {
- return $this->m_flags;
- }
- /**
- * Adds a flag to the attribute.
- * Note that adding flags at any time after the constructor might not
- * always work. There are flags that are processed only at
- * constructor time.
- * @param int $flag The flag to add to the attribute
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function addFlag($flag)
- {
- $this->m_flags |= $flag;
- if (!$this->hasFlag(AF_PRIMARY) && is_object($this->m_ownerInstance)) {
- if (hasFlag($flag, AF_HIDE_LIST) && !in_array($this->fieldName(), $this->m_ownerInstance->m_listExcludes)) {
- $this->m_ownerInstance->m_listExcludes[] = $this->fieldName();
- }
- if (hasFlag($flag, AF_HIDE_VIEW) && !in_array($this->fieldName(), $this->m_ownerInstance->m_viewExcludes)) {
- $this->m_ownerInstance->m_viewExcludes[] = $this->fieldName();
- }
- }
- return $this;
- }
- /**
- * Sets the flags of the attribute
- *
- * Note that if you assign nothing or 0, this will remove all the flags
- * from the attribute. You can assign multiple flags by using the pipe
- * symbol. Setting the flags will overwrite all previous flag-settings.
- * @param int $flags The flags to be set to the attribute.
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function setFlags($flags = 0)
- {
- $this->m_flags = 0;
- $this->addFlag($flags); // always call addFlag
- return $this;
- }
- /**
- * Removes a flag from the attribute.
- *
- * Note that removing flags at any time after the constructor might not
- * always work. There are flags that have already been processed at
- * constructor time, so removing them will be futile.
- * @param int $flag The flag to remove from the attribute
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function removeFlag($flag)
- {
- if ($this->hasFlag($flag)) {
- $this->m_flags ^= $flag;
- }
- if (!$this->hasFlag(AF_PRIMARY) && is_object($this->m_ownerInstance)) {
- if (hasFlag($flag, AF_HIDE_LIST) && in_array($this->fieldName(), $this->m_ownerInstance->m_listExcludes)) {
- $key = array_search($this->fieldName(), $this->m_ownerInstance->m_listExcludes);
- unset($this->m_ownerInstance->m_listExcludes[$key]);
- }
- if (hasFlag($flag, AF_HIDE_VIEW) && in_array($this->fieldName(), $this->m_ownerInstance->m_viewExcludes)) {
- $key = array_search($this->fieldName(), $this->m_ownerInstance->m_viewExcludes);
- unset($this->m_ownerInstance->m_viewExcludes[$key]);
- }
- }
- return $this;
- }
- /**
- * Adds a disabled mode flag to the attribute (use DISABLED_VIEW and DISABLED_EDIT flags).
- * @param int $flag The flag to add to the attribute
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function addDisabledMode($flag)
- {
- $this->m_disabledModes |= $flag;
- return $this;
- }
- /**
- * Check if the attribute is disabled in some mode (use DISABLED_VIEW and DISABLED_EDIT flags).
- * @param int $flag The flag you want to check
- * @return boolean
- */
- function hasDisabledMode($flag)
- {
- return (($this->m_disabledModes & $flag) == $flag);
- }
- /**
- * Sets the disabled mode flag of the attribute
- *
- * Note that if you assign nothing or 0, this will remove all the flags
- * from the attribute. You can assign multiple flags by using the pipe
- * symbol. Setting the flags will overwrite all previous flag-settings.
- * @param int $flags The flags to be set to the attribute.
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function setDisabledModes($flags = 0)
- {
- $this->m_disabledModes = $flags;
- return $this;
- }
- /**
- * Removes a disabled mode from the attribute.
- *
- * @param int $flag The flag to remove from the attribute
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function removeDisabledMode($flag)
- {
- if ($this->hasDisabledMode($flag)) {
- $this->m_disabledModes ^= $flag;
- }
- return $this;
- }
- /**
- * Returns the name of the attribute.
- *
- * For most attributes, this corresponds to the name of the field in the
- * database. For some attributes though (like one2many relations), the
- * name is a mere identifier within an entity. This method always returns
- * the attribute name, despite the 'field' prefix of the method.
- *
- * @return String fieldname
- */
- function fieldName()
- {
- return $this->m_name;
- }
- /**
- * Check if a record has an empty value for this attribute.
- * @param array $record The record that holds this attribute's value.
- * @return boolean
- */
- function isEmpty($record)
- {
- return (!isset($record[$this->fieldName()]) || $record[$this->fieldName()] === "");
- }
- /**
- * Converts the internal attribute value to one that is understood by the
- * database.
- *
- * For the regular Adapto_Attribute, this means escaping things like
- * quotes and slashes. Derived attributes may reimplement this for their
- * own conversion.
- * This is the exact opposite of the db2value method.
- *
- * @param array $rec The record that holds this attribute's value.
- * @return String The database compatible value
- */
- function value2db($rec)
- {
- if (is_array($rec) && isset($rec[$this->fieldName()])) {
- return $this->escapeSQL($rec[$this->fieldName()]);
- }
- return NULL;
- }
- /**
- * Converts a database value to an internal value.
- *
- * For the regular Adapto_Attribute
- * Derived attributes may reimplement this for their own conversion.
- * (In which case, the return type might be 'mixed')
- *
- * This is the exact opposite of the value2db method.
- *
- * @param array $rec The database record that holds this attribute's value
- * @return mixed The internal value
- */
- function db2value($rec)
- {
- if (isset($rec[$this->fieldName()])) {
- return $rec[$this->fieldName()] === NULL ? NULL : $rec[$this->fieldName()];
- }
- return NULL;
- }
- /**
- * Is there a value posted for this attribute?
- *
- * @param array $postvars
- * @return boolean posted?
- */
- function isPosted($postvars)
- {
- return is_array($postvars) && isset($postvars[$this->fieldName()]);
- }
- /**
- * Set initial value for this attribute.
- *
- * NOTE: the initial value only works if there is no initial_values override
- * in the entity or if the override properly calls parent::initial_values!
- *
- * @param mixed $value initial value
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function setInitialValue($value)
- {
- $this->m_initialValue = $value;
- return $this;
- }
- /**
- * Initial value. Returns the initial value for this attribute
- * which will be used in the add form etc.
- *
- * @return mixed initial value for this attribute
- */
- function initialValue()
- {
- return $this->m_initialValue;
- }
- /**
- * Convert values from an HTML form posting to an internal value for
- * this attribute.
- *
- * For the regular Adapto_Attribute, this means getting the field with the
- * same name as the attribute from the html posting.
- *
- * @param array $postvars The array with html posted values ($_POST, for
- * example) that holds this attribute's value.
- * @return String The internal value
- */
- function fetchValue($postvars)
- {
- if ($this->isPosted($postvars)) {
- return $postvars[$this->fieldName()];
- }
- }
- /**
- * Register JavaScript event handlers.
- *
- * @param string $fieldId field identifier
- */
- protected function registerJavaScriptObservers($fieldId)
- {
- foreach ($this->m_jsObservers as $event => $handlers) {
- foreach ($handlers as $handler) {
- $code = '$(\'' . $fieldId . '\').observe(\'' . $event . '\', function(event) { var fieldId = \'' . $fieldId . '\'; ' . $handler . ' });';
- $this->getOwnerInstance()->getPage()->register_loadscript($code);
- }
- }
- }
- /**
- * 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
- */
- function edit($record = "", $fieldprefix = "", $mode = "")
- {
- $id = $this->getHtmlId($fieldprefix);
- $this->registerKeyListener($id, KB_CTRLCURSOR | KB_UPDOWN);
- if (count($this->m_onchangecode)) {
- $onchange = 'onChange="' . $id . '_onChange(this);"';
- $this->_renderChangeHandler($fieldprefix);
- } else {
- $onchange = '';
- }
- $this->registerJavaScriptObservers($id);
- $size = $this->m_size;
- if ($mode == 'list' && $size > 20)
- $size = 20;
- $value = (isset($record[$this->fieldName()]) && !is_array($record[$this->fieldName()]) ? htmlspecialchars($record[$this->fieldName()]) : "");
- $result = '<input type="text" id="' . $id . '" name="' . $id . '" ' . $this->getCSSClassAttribute() . ' value="' . $value . '"'
- . ($size > 0 ? ' size="' . $size . '"' : '') . ($this->m_maxsize > 0 ? ' maxlength="' . $this->m_maxsize . '"' : '') . ' ' . $onchange . ' />';
- return $result;
- }
- /**
- * Add a javascript onchange event handler.
- * @param string $jscode A block of valid javascript code.
- * @return Adapto_Attribute Returns the instance of this attribute.
- */
- function addOnChangeHandler($jscode)
- {
- if (!in_array($jscode, $this->m_onchangecode))
- $this->m_onchangecode[] = $jscode;
- return $this;
- }
- /**
- * Renders the onchange code on the page.
- *
- * @access private
- * @param String $fieldprefix The prefix to the field
- * @param String $elementNr The number of the element when attribute contains multiple options
- */
- function _renderChangeHandler($fieldprefix, $elementNr = "")
- {
- if (count($this->m_onchangecode)) {
- $page = &$this->m_ownerInstance->getPage();
- $page
- ->register_scriptcode(
- "
- function " . $this->getHtmlId($fieldprefix) . $elementNr . "_onChange(el)
- {
- {$this->m_onchangehandler_init}
- " . implode("\n ", $this->m_onchangecode) . "
- }\n");
- }
- }
- /**
- * Returns a piece of html code for hiding this attribute in an HTML form,
- * while still posting its value. (<input type="hidden">)
- *
- * @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.
- * @return String A piece of htmlcode with hidden form elements that post
- * this attribute's value without showing it.
- */
- function hide($record = "", $fieldprefix = "")
- {
- // the next if-statement is a workaround for derived attributes which do
- // not override the hide() method properly. This will not give them a
- // working hide() functionality but at least it will not give error messages.
- if (!is_array($record[$this->fieldName()])) {
- $id = $id = $this->getHtmlId($fieldprefix);
- $result = '<input type="hidden" id="' . $id . '" name="' . $fieldprefix . $this->formName() . '" value="'
- . htmlspecialchars($record[$this->fieldName()]) . '">';
- return $result;
- } else
- Adapto_Util_Debugger::debug("Warning attribute " . $this->m_name . " has no proper hide method!");
- }
- /**
- * Return the html identifier (id="") of the attribute. (unique within a
- * page)
- * @param String $fieldprefix The fieldprefix to put in front of the name
- * of any html form element for this attribute.
- * @return String the HTML identifier.
- */
- function getHtmlId($fieldprefix)
- {
- $this->m_htmlid = $fieldprefix . $this->fieldName();
- return $this->m_htmlid;
- }
- /**
- * Returns the html identifier of the attribute without setting it
- * Created because getHtmlId would always SET the htmlid while getting it.
- * @return String The HTML id of this attribute
- */
- function getAttributeHtmlId()
- {
- if ($this->m_htmlid)
- return $this->m_htmlid;
- else
- return $this->fieldName();
- }
- /**
- * Adds the attribute's view / hide HTML code to the view array.
- *
- * This method is called by the entity if it wants the data needed to create
- * a view form.
- *
- * This is a framework method, it should never be called directly.
- *
- * @param String $mode the mode ("view")
- * @param array $arr pointer to the view array
- * @param array $defaults pointer to the default values array
- */
- function addToViewArray($mode, &$arr, &$defaults)
- {
- if (!$this->hasFlag(AF_HIDE_VIEW)) {
- $entry = array("name" => $this->m_name, "attribute" => &$this);
- /* label? */
- $entry["label"] = $this->getLabel($defaults, $mode);
- // on which tab?
- $entry["tabs"] = $this->getTabs($mode);
- //on which sections?
- $entry["sections"] = $this->getSections();
- /* the actual edit contents */
- $entry["html"] = $this->getView($mode, $defaults);
- $arr["fields"][] = $entry;
- }
- }
- /**
- * Prepare for edit. Is called before all attributes are added to the
- * edit array and allows for last minute manipulations based on the
- * record but also manipulations on the record itself.
- *
- * @param array $record reference to the record
- * @param string $fieldPrefix field prefix
- * @param string $mode edit mode
- */
- public function preAddToEditArray(&$record, $fieldPrefix, $mode)
- {
- }
- /**
- * Prepare for view. Is called before all attributes are added to the
- * view array and allows for last minute manipulations based on the
- * record but also manipulations on the record itself.
- *
- * @param array $record reference to the record
- * @param string $mode view mode
- */
- public function preAddToViewArray(&$record, $mode)
- {
- }
- /**
- * Adds the attribute's edit / hide HTML code to the edit array.
- *
- * This method is called by the entity if it wants the data needed to create
- * an edit form.
- *
- * This is a framework method, it should never be called directly.
- *
- * @param String $mode the edit mode ("add" or "edit")
- * @param array $arr pointer to the edit array
- * @param array $defaults pointer to the default values array
- * @param array $error pointer to the error array
- * @param String $fieldprefix the fieldprefix
- */
- function addToEditArray($mode, &$arr, &$defaults, &$error, $fieldprefix)
- {
- /* hide */
- if (($mode == "edit" && $this->hasFlag(AF_HIDE_EDIT)) || ($mode == "add" && $this->hasFlag(AF_HIDE_ADD))) {
- /* when adding, there's nothing to hide, unless we're dealing with atkHiddenAttribute... */
- if ($mode == "edit" || ($mode == "add" && (!$this->isEmpty($defaults) || $this instanceof atkHiddenAttribute))) {
- $arr["hide"][] = $this->hide($defaults, $fieldprefix, $mode);
- }
- }
- /* edit */
- else {
- global $Adapto_VARS;
- $entry = array("name" => $this->m_name, "obligatory" => $this->hasFlag(AF_OBLIGATORY), "attribute" => &$this);
- $entry["id"] = $this->getHtmlId($fieldprefix);
- /* label? */
- $entry["label"] = $this->getLabel($defaults, $mode);
- /* error? */
- $entry["error"] = $this->getError($error)
- || (isset($Adapto_VARS["atkerrorfields"]) && Adapto_in_array($entry['id'], $Adapto_VARS['atkerrorfields']));
- // on which tab?
- $entry["tabs"] = $this->getTabs($mode);
- //on which sections?
- $entry["sections"] = $this->getSections();
- // the actual edit contents
- $entry["html"] = $this->getEdit($mode, $defaults, $fieldprefix);
- // initially hidden
- $entry["initial_hidden"] = $this->isInitialHidden($defaults);
- $arr["fields"][] = $entry;
- }
- }
- /**
- * Put the attribute on one or more tabs.
- * @param array $tabs An array of tabs on which the attribute should
- * be displayed.
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function setTabs($tabs)
- {
- if (empty($tabs) && isset($this->m_ownerInstance) && is_object($this->m_ownerInstance)) {
- $tabs = array($this->m_ownerInstance->m_default_tab);
- } else if (empty($tabs)) {
- $tabs = array('default');
- }
- $this->m_tabs = $tabs;
- return $this;
- }
- /**
- * retrieve the tabs for this attribute.
- * @param string $mode
- * @return array
- */
- function getTabs($mode = "")
- {
- return $this->m_tabs;
- }
- /**
- * Put the attribute on one or more tabs and/or sections.
- *
- * Example:
- * <code>$attribute->setSections(array('tab.section','tab.othersection));</code>
- *
- * @param array $sections An array of tabs and/or sections on which the attribute should
- * be displayed.
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function setSections($sections)
- {
- if ($sections == NULL) {
- $this->m_sections = array();
- } else {
- $this->m_sections = $sections;
- }
- return $this;
- }
- /**
- * retrieve the tabs and/or sections for this attribute.
- *
- * @return array
- */
- function getSections()
- {
- return $this->m_sections;
- }
- /**
- * Get column.
- *
- * @return string column name
- */
- public function getColumn()
- {
- return $this->m_column;
- }
- /**
- * Set column.
- *
- * @param string $name column name
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- public function setColumn($name)
- {
- $this->m_column = $name;
- return $this;
- }
- /**
- * Returns the view callback (if set).
- *
- * @return mixed callback method
- */
- protected function getViewCallback()
- {
- return $this->m_viewCallback;
- }
- /**
- * Sets the view callback.
- *
- * The callback is called instead of the regular display method of the
- * attribute.
- *
- * @param mixed $callback callback method
- */
- public function setViewCallback($callback)
- {
- $this->m_viewCallback = $callback;
- }
- /**
- * Retrieve the html code for placing this attribute in a view page.
- *
- * Method is 'smart' and can be overridden in the entity using the
- * <attributename>_display() methods.
- *
- * Framework method, it should not be necessary to call this method
- * directly.
- *
- * @param String $mode The mode ("view")
- * @param array $defaults The record holding the values for this attribute
- *
- * @return String the HTML code for this attribute that can be used in a
- * viewpage.
- */
- function getView($mode, &$defaults)
- {
- $method = $this->m_name . "_display";
- if ($this->getViewCallback() != null) {
- return call_user_func($this->getViewCallback(), $defaults, $mode, $this);
- } else if (method_exists($this->m_ownerInstance, $method)) {
- return $this->m_ownerInstance->$method($defaults, $mode);
- } else {
- return $this->display($defaults, $mode) . (strlen($this->m_postfixlabel) > 0 ? " " . $this->m_postfixlabel : "");
- }
- }
- /**
- * Retrieve the html/javascript code for showing the tooltip for this attribute.
- *
- * @return String HTML
- */
- function getToolTip()
- {
- $tooltip = $this->text($this->fieldName() . '_tooltip', false);
- if (!$tooltip) {
- return '';
- }
- $template = atkTheme::getInstance()->tplPath('tooltip.tpl', $this->getModule());
- $vars = array('tooltip' => $tooltip, 'attribute' => $this);
- $result = $this->getOwnerInstance()->getUi()->render($template, $vars, $this->getModule());
- return $result;
- }
- /**
- * Returns the edit callback (if set).
- *
- * @return mixed callback method
- */
- protected function getEditCallback()
- {
- return $this->m_editCallback;
- }
- /**
- * Sets the edit callback.
- *
- * The callback is called instead of the regular display method of the
- * attribute.
- *
- * @param mixed $callback callback method
- */
- public function setEditCallback($callback)
- {
- $this->m_editCallback = $callback;
- }
- /**
- * Retrieve the HTML code for placing this attribute in an edit page.
- *
- * The difference with the edit() method is that the edit() method just
- * generates the HTML code for editing the attribute, while the getEdit()
- * method is 'smart', and implements a hide/readonly policy based on
- * flags and/or custom override methodes in the entity.
- * (<attributename>_edit() and <attributename>_display() methods)
- *
- * Framework method, it should not be necessary to call this method
- * directly.
- *
- * @param String $mode The edit mode ("add" or "edit")
- * @param array $defaults The record holding the values for this attribute
- * @param String $fieldprefix The fieldprefix to put in front of the name
- * of any html form element for this attribute.
- * @return String the HTML code for this attribute that can be used in an
- * editpage.
- */
- function getEdit($mode, &$defaults, $fieldprefix)
- {
- // readonly
- if (($mode == "edit" && $this->hasFlag(AF_READONLY_EDIT)) || ($mode == "add" && $this->hasFlag(AF_READONLY_ADD))) {
- return $this->hide($defaults, $fieldprefix) . $this->getView($mode, $defaults);
- }
- $method = $this->m_name . "_edit";
- if ($this->getEditCallback() != null) {
- return call_user_func($this->getEditCallback(), $defaults, $fieldprefix, $mode, $this);
- } else if ($this->m_name != "action" && method_exists($this->m_ownerInstance, $method)) {
- // we can't support the override for attributes named action, because of a conflict with
- // a possible edit action override (in both cases the method is called action_edit)
- return $this->m_ownerInstance->$method($defaults, $fieldprefix, $mode);
- } else {
- return $this->edit($defaults, $fieldprefix, $mode) . (strlen($this->m_postfixlabel) > 0 ? " " . $this->m_postfixlabel : "");
- }
- }
- /**
- * Check if this attribute has errors in the specified error list.
- *
- * @param array $errors The error list is one that is stored in the
- * "atkerror" section of a record, for example
- * generated by validate() methods.
- * @return boolean
- */
- function getError($errors)
- {
- for ($i = 0; $i < count($errors); $i++) {
- if ($errors[$i]['attrib_name'] == $this->fieldName() || Adapto_in_array($this->fieldName(), $errors[$i]['attrib_name'])) {
- return true;
- }
- }
- return false;
- }
- /**
- * Adds the attribute / field to the list header. This includes the column name and search field.
- *
- * Framework method. It should not be necessary to call this method directly.
- *
- * @param String $action the action that is being performed on the entity
- * @param array $arr reference to the the recordlist array
- * @param String $fieldprefix the fieldprefix
- * @param int $flags the recordlist flags
- * @param array $atksearch the current ATK search list (if not empty)
- * @param atkColumnConfig $columnConfig Column configuration object
- * @param atkDataGrid $grid The atkDataGrid this attribute lives on.
- * @param string $column child column (null for this attribute, * for this attribute and all childs)
- */
- public function addToListArrayHeader($action, &$arr, $fieldprefix, $flags, $atksearch, $columnConfig, atkDataGrid $grid = null, $column = '*')
- {
- if ($column != null && $column != '*') {
- throw new Exception("Invalid list column {$column} for " . get_class($this) . " " . $this->getOwnerInstance()->atkEntityType() . '::'
- . $this->fieldName());
- }
- if (!$this->hasFlag(AF_HIDE_LIST) && !($this->hasFlag(AF_HIDE_SELECT) && $action == "select")) {
- $key = $fieldprefix . $this->fieldName();
- $arr["heading"][$key]["title"] = $this->label();
- if ($grid->hasFlag(atkDataGrid::SORT) && !$this->hasFlag(AF_NO_SORT)) {
- $arr["heading"][$key]["order"] = $this->listHeaderSortOrder($columnConfig, $fieldprefix);
- }
- if ($grid->hasFlag(atkDataGrid::EXTENDED_SORT)) {
- $arr["sort"][$key] = $this->extendedSort($columnConfig, $fieldprefix, $grid);
- }
- if ($grid->hasFlag(atkDataGrid::SEARCH) && $this->hasFlag(AF_SEARCHABLE)) {
- $fn = $this->fieldName() . "_search";
- if (method_exists($this->m_ownerInstance, $fn)) {
- $arr["search"][$key] = $this->m_ownerInstance->$fn($atksearch, false, $fieldprefix, $grid);
- } else {
- $arr["search"][$key] = $this->search($atksearch, false, $fieldprefix, $grid);
- }
- $arr["search"][$key] .= $this->searchMode(false, $fieldprefix);
- }
- }
- }
- /**
- * Adds the attribute / field to the list row. And if the row is totalisable also to the total.
- *
- * Framework method. It should not be necessary to call this method directly.
- *
- * @param String $action the action that is being performed on the entity
- * @param array $arr reference to the the recordlist array
- * @param int $nr the current row number
- * @param String $fieldprefix the fieldprefix
- * @param int $flags the recordlist flags
- * @param boolean $edit editing?
- * @param atkDataGrid $grid data grid
- * @param string $column child column (null for this attribute, * for this attribute and all childs)
- */
- public function addToListArrayRow($action, &$arr, $nr, $fieldprefix, $flags, $edit = false, atkDataGrid $grid = null, $column = '*')
- {
- if ($column != null && $column != '*') {
- throw new Exception("Invalid list column {$column} for " . get_class($this) . " " . $this->getOwnerInstance()->atkEntityType() . '::'
- . $this->fieldName());
- }
- if (!$this->hasFlag(AF_HIDE_LIST) && !($this->hasFlag(AF_HIDE_SELECT) && $action == "select")) {
- if ($edit) {
- $arr["rows"][$nr]["data"][$fieldprefix . $this->fieldName()] = $this
- ->getEdit('list', $arr["rows"][$nr]["record"], 'atkdatagriddata_AE_' . $nr . '_AE_');
- } else {
- $arr["rows"][$nr]["data"][$fieldprefix . $this->fieldName()] = $this->getView('list', $arr["rows"][$nr]["record"]);
- }
- /* totalisable? */
- if ($this->hasFlag(AF_TOTAL)) {
- $sum = $this->sum($arr["totalraw"], $arr["rows"][$nr]["record"], $fieldprefix);
- $arr["totalraw"][$this->fieldName()] = $sum[$this->fieldName()];
- $arr["total"][$fieldprefix . $this->fieldName()] = $this->getView('list', $sum);
- }
- }
- }
- /**
- * Returns a piece of html code that can be used to get search terms input
- * from the user.
- *
- * The framework calls this method to display the searchbox
- * in the search bar of the recordlist, and to display a more extensive
- * search in the 'extended' search screen.
- * The regular atkAttributes returns a simple text input box for entering
- * a keyword to search for.
- * @todo find a better way to search on onetomanys that does not require
- * something evil in Adapto_Attribute
- * @param array $record Array with values
- * @param boolean $extended if set to false, a simple search input is
- * returned for use in the searchbar of the
- * recordlist. If set to true, a more extended
- * search may be returned for the 'extended'
- * search page. The Adapto_Attribute does not
- * make a difference for $extended is true, but
- * derived attributes may reimplement this.
- * @param string $fieldprefix The fieldprefix of this attribute's HTML element.
- *
- * @return String A piece of html-code
- */
- public function search($record = array(), $extended = false, $fieldprefix = "", atkDataGrid $grid = null)
- {
- $id = $this->getSearchFieldName($fieldprefix);
- $value = "";
- if (is_array($record) && isset($record[$this->fieldName()])) {
- $value = $record[$this->fieldName()];
- }
- $this->registerKeyListener($id, KB_CTRLCURSOR | KB_UPDOWN);
- $result = '<input type="text" id="' . $id . '" class="' . get_class($this) . '" name="' . $id . '" value="' . atk_htmlentities($value) . '"'
- . ($this->m_searchsize > 0 ? ' size="' . $this->m_searchsize . '"' : '') . ($this->m_maxsize > 0 ? ' maxlength="' . $this->m_maxsize . '"' : '')
- . '>';
- return $result;
- }
- /**
- * Returns piece of html which is used for setting/selecting the search
- * mode for this attribute.
- *
- * It will show a pulldown if using extended search and multiple
- * searchmodes are supported otherwise the default searchmode is selected.
- *
- * @param boolean $extended using extended search?
- * @param string $fieldprefix optional fieldprefix
- * @return string html which is used for selecting searchmode
- */
- public function searchMode($extended = false, $fieldprefix = '')
- {
- $searchModes = $this->getSearchModes();
- $dbSearchModes = $this->getDb()->getSearchModes();
- $searchModes = array_values(array_intersect($searchModes, $dbSearchModes));
- $searchMode = $this->getSearchMode($extended);
- // Set current searchmode to first searchmode if not searching in extended form or no searchmode is set
- if (!$extended || empty($searchMode) || !in_array($searchMode, $searchModes))
- $searchMode = $searchModes[0];
- if ($extended && count($searchModes) > 1) {
- $field = '<select name="' . $this->getSearchModeFieldname($fieldprefix) . '">';
- foreach ($searchModes as $value) {
- $selected = $searchMode == $value ? ' selected="selected"' : '';
- $field .= '<option value="' . $value . '"' . $selected . '>' . Adapto_htmlentities($this->text("search_" . $value)) . '</option>';
- }
- $field .= '</select>';
- } else {
- $field = '<input type="hidden" name="' . $this->getSearchModeFieldname($fieldprefix) . '" value="' . $searchMode . '">'
- . ($extended ? atktext("search_" . $searchMode) : '');
- }
- return $field;
- }
- /**
- * Retrieve the current set or default searchmode of this attribute
- *
- * @param boolean $extended Whether extended search is being used
- * @return String the default searchmode for this attribute.
- */
- function getSearchMode($extended = false)
- {
- $searchmode = $this->m_ownerInstance->getSearchMode();
- if (is_array($searchmode)) {
- return $searchmode[$this->fieldName()];
- }
- return $searchmode;
- }
- /**
- * Creates a smart search condition for a given search value, and adds it
- * to the query that will be used for performing the actual search.
- *
- * @param Integer $id The unique smart search criterium identifier.
- * @param Integer $nr The element number in the path.
- * @param Array $path The remaining attribute path.
- * @param atkQuery $query The query to which the condition will be added.
- * @param String $ownerAlias The owner table alias to use.
- * @param Mixed $value The value the user has entered in the searchbox.
- * @param String $mode The searchmode to use.
- */
- function smartSearchCondition($id, $nr, $path, &$query, $ownerAlias, $value, $mode)
- {
- // default implementation doesn't supported nested paths, this method
- // should be overriden by relations etc. if they want to support this
- if (count($path) > 0) {
- Adapto_var_dump($path, 'Invalid search path for ' . $this->m_ownerInstance->atkEntityType() . '#' . $this->fieldName() . ', ignoring criterium!');
- } else {
- $this->searchCondition($query, $ownerAlias, $value, $mode);
- }
- }
- /**
- * Creates a search condition for a given search value, and adds it to the
- * query that will be used for performing the actual search.
- *
- * @param atkQuery $query The query to which the condition will be added.
- * @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 $fieldaliasprefix optional prefix for the fieldalias in the table
- */
- function searchCondition(&$query, $table, $value, $searchmode, $fieldaliasprefix = '')
- {
- $searchCondition = $this->getSearchCondition($query, $table, $value, $searchmode, $fieldaliasprefix);
- if ($searchCondition) {
- $query->addSearchCondition($searchCondition);
- }
- }
- /**
- * Creates a searchcondition for the field,
- * was once part of searchCondition, however,
- * searchcondition() also immediately adds the search condition.
- *
- * @param atkQuery $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.
- * @return String The searchcondition to use.
- */
- function getSearchCondition(&$query, $table, $value, $searchmode)
- {
- // 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 && Adapto_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)) {
- Adapto_Util_Debugger::debug("Database doesn't support searchmode '$searchmode' for " . $this->fieldName() . ", ignoring condition.");
- }
- return false;
- }
- /**
- * Sets the searchmode for an attribute
- * This will cause attributes that respect this
- * to use the attributes searchmode for that particulair attribute
- * instead of the general searchmode.
- * @param String $searchmode The searchmode we want to set on the attribute
- * @return Adapto_Attribute The instance of this Adapto_Attribute
- */
- function setAttributeSearchmode($searchmode)
- {
- $this->m_searchmode = $searchmode;
- return $this;
- }
- /**
- * Returns a displayable string for this value, to be used in HTML pages.
- *
- * The regular Adapto_Attribute uses PHP's nl2br() and htmlspecialchars()
- * methods to prepare a value for display, unless $mode is "cvs".
- *
- * @param array $record The record that holds the value for this attribute
- * @param String $mode The display mode ("view" for viewpages, or "list"
- * for displaying in recordlists, "edit" for
- * displaying in editscreens, "add" for displaying in
- * add screens. "csv" for csv files. Applications can
- * use additional modes.
- * @return String HTML String
- */
- function display($record, $mode = "")
- {
- // the next if-statement is a workaround for derived attributes which do
- // not override the display() method properly. This will not give them a
- // working display() functionality but at least it will not give error messages.
- if (!is_array($record[$this->fieldName()])) {
- // default behaviour is that we display a value 'as is'.
- if (($mode == "csv") || ($mode == "plain"))
- return $record[$this->fieldName()];
- return nl2br(htmlspecialchars($record[$this->fieldName()]));
- }
- }
- /**
- * Checks if a value is valid.
- *
- * The regular Adapto_Attribute has no specific validation. Derived attributes
- * may override this method to perform custom validation.
- * Note that obligatory and unique fields are checked by the
- * atkEntityValidator, and not by the validate() method itself.
- *
- * @param array $record The record that holds the value for this
- * attribute. If an error occurs, the error will
- * be stored in the 'atkerror' field of the record.
- * @param String $mode The mode for which should be validated ("add" or
- * "update")
- */
- function validate(&$record, $mode)
- {
- }
- /**
- * Checks if this attribute is really not null in the database.
- * This method does not look at the AF_OBLIGATORY flag, it only
- * checks in the database if the attribute's column is really not null.
- *
- * @return boolean attribute's database column not null?
- */
- function isNotNullInDb()
- {
- $db = &$this->getDb();
- $meta = $db->tableMeta($this->m_ownerInstance->m_table);
- return hasFlag($meta[$this->fieldName()]['flags'], MF_NOT_NULL);
- }
- /**
- * Adds this attribute to database queries.
- *
- * Database queries (select, insert and update) are passed to this method
- * so the attribute can 'hook' itself into the query.
- *
- * Framework method. It should not be necessary to call this method
- * directly. Derived attributes that consist of more than a single simple
- * database field (like relations for example), may have to reimplement
- * this method.
- *
- * @param atkQuery $query The SQL query object
- * @param String $tablename The name of the table of this attribute
- * @param String $fieldaliasprefix Prefix to use in front of the alias
- * in the query.
- * @param Array $rec The record that contains the value of this attribute.
- * @param int $level Recursion level if relations point to eachother, an
- * endless loop could occur if they keep loading
- * eachothers data. The $level is used to detect this
- * loop. If overriden in a derived class, any subcall to
- * an addToQuery method should pass the $level+1.
- * @param String $mode Indicates what kind of query is being processing:
- * This can be any action performed on an entity (edit,
- * add, etc) Mind you that "add" and "update" are the
- * actions that store something in the database,
- * whereas the rest are probably select queries.
- */
- function addToQuery(&$query, $tablename = "", $fieldaliasprefix = "", &$rec = "", $level, $mode)
- {
- if ($mode == "add" || $mode == "update") {
- if ($mode == 'add' && $this->hasFlag(AF_AUTO_INCREMENT)) {
- $query->addSequenceField($this->fieldName(), $rec[$this->fieldName()], $this->getOwnerInstance()->m_seq);
- return;
- }
- if ($this->isEmpty($rec) && !$this->hasFlag(AF_OBLIGATORY) && !$this->isNotNullInDb()) {
- $query->addField($this->fieldName(), 'NULL', "", "", false, true);
- } else {
- $query->addField($this->fieldName(), $this->value2db($rec), "", "", !$this->hasFlag(AF_NO_QUOTES), true);
- }
- } else
- $query->addField($this->fieldName(), "", $tablename, $fieldaliasprefix, !$this->hasFlag(AF_NO_QUOTES), true);
- }
- /**
- * The delete method is called by the framework to inform the attribute
- * that a record is deleted.
- *
- * The regular Adapto_Attribute has no implementation for this method, but
- * derived attributes may override this, to take care of cleanups, cascade
- * deletes etc.
- * Note, that the framework only calls this method if the attribute has
- * the AF_CASCADE_DELETE flag.
- *
- * @param array $record The record that is deleted.
- * @return boolean true if cleanup was successful, false otherwise.
- */
- function delete($record)
- {
- // delete is only of interest for special attributes like relations, or file attributes.
- return true;
- }
- /**
- * Calculate the sum of 2 records.
- *
- * This is called by the framework for the auto-totalling feature. Two
- * records are passed, and a record is returned. The reason that the
- * params are entire records instead of plain values, is that derived
- * classes or custom attributes may need information from other attributes
- * too.
- *
- * @param array $rec1 The first record
- * @param array $rec2 The second record
- * @param String $fieldprefix The prefix that values in $rec1
- * and $rec2 have
- * @return array A record containing the sum of $rec1 and $rec2
- */
- function sum($rec1, $rec2, $fieldprefix = "")
- {
- $value1 = (isset($rec1[$this->fieldName()]) ? $rec1[$this->fieldName()] : 0);
- $value2 = (isset($rec2[$this->fieldName()]) ? $rec2[$this->fieldName()] : 0);
- return array($this->fieldName() => ($value1 + $value2));
- }
- /**
- * Fetch the metadata about this attrib from the table metadata, and
- * process it.
- *
- * Lengths for the edit and searchboxes, and maximum lengths are retrieved
- * from the table metadata by this method.
- *
- * @param array $metadata The table metadata from the table for this
- * attribute.
- */
- function fetchMeta($metadata)
- {
- $attribname = strtolower($this->fieldName());
- // Only use meta info if size is not already set manual. (constructor or setAttribSize)
- // If both are set, use the smallest value.
- if (isset($metadata[$attribname])) {
- if ($this->m_size > 0)
- $this->m_size = min($this->m_size, $metadata[$attribname]['len'], $this->maxInputSize());
- else
- $this->m_size = min($metadata[$attribname]['len'], $this->maxInputSize());
- if ($this->m_searchsize > 0)
- $this->m_searchsize = min($this->m_searchsize, $metadata[$attribname]['len'], 20);
- else
- $this->m_searchsize = min($metadata[$attribname]['len'], 20);
- if ($this->m_maxsize > 0)
- $this->m_maxsize = min($this->m_maxsize, $metadata[$attribname]['len']);
- else
- $this->m_maxsize = $metadata[$attribname]['len'];
- }
- // TODO FIXME: The metadata contains the real field type. $this->m_dbfieldtype should be
- // set accordingly. Currently the metadata contains database specific types, so this
- // feature is not yet implemented, until metadata contains generic field types.
- }
- /**
- * This function is called right after the attribute is added to the entity.
- *
- * The regular Adapto_Attribute has no implementation for this method, but
- * derived attributes may override this method to perform custom
- * initialization.
- */
- function init()
- {
- }
- /**
- * This function is called at the end of the entity's init method.
- *
- * The regular Adapto_Attribute has no implementation for this method, but
- * derived attributes may override this method to perform custom
- * initialization.
- */
- function postInit()
- {
- }
- /**
- * This function is called to compare if two records are considered equal
- * by this attribute.
- *
- * The regular Adapto_Attribute performs a simple string match; derived
- * classes may override this method to perform more complex comparisons.
- *
- * @param array $recA The first record holding a value for this attribute.
- * @param array $recB The second record holding a value for the attribute.
- * @return boolean True if the attribute considers the records equal,
- * false if not.
- */
- function equal($recA, $recB)
- {
- return ($recA[$this->fieldName()] == $recB[$this->fieldName()]);
- }
- /**
- * Used to force an attribute to update with every addDb() call
- * @param bool $force Wether or not to force the attribute to insert
- * @return Adapto_Attribute Returns the instance of this attribute
- */
- function setForceInsert($force)
- {
- $this->m_forceinsert = $force;
- return $this;
- }
- /**
- * Getter for wether or not an attribute is forced to insert
- * @return bool Wether or not an attribute is forced to insert
- */
- function getForceInsert()
- {
- return $this->m_forceinsert;
- }
- /**
- * Used to force an attribute to update from the db regardless of the
- * attribute being present in the postvars/session
- * @param bool $force Wether or not to force the attribute to reload
- * @return Adapto_Attribute Returns the instance of this attribute
- */
- function setForceReload($force)
- {
- $this->m_forcereload = $force;
- return $this;
- }
- /**
- * Used to force an attribute to update with every updateDb() call
- * @param bool $force Wether or not to force the attribute to update
- * @return Adapto_Attribute Returns the instance of this attribute
- */
- function setForceUpdate($force)
- {
- $this->m_forceupdate = $force;
- return $this;
- }
- /**
- * Getter for wether or not an attribute is forced to update
- * @return bool Wether or not an attribute is forced to update
- */
- function getForceUpdate()
- {
- return $this->m_forceupdate;
- }
- /**
- * This function is called by the framework to determine if the attribute
- * needs to be saved to the database in an addDb call.
- *
- * The regular Adapto_Attribute returns false if the value is empty, or if
- * AF_HIDE is set; true in other cases. Exception: when AF_AUTO_INCREMENT
- * is set, the method always returns true. Derived attributes may override
- * this behavior.
- *
- * @param array $record The record that is going to be saved
- * @return boolean True if this attribute should participate in the add
- * query; false if not.
- */
- function needsInsert($record)
- {
- return (!$this->hasFlag(AF_HIDE_ADD) || $this->hasFlag(AF_AUTO_INCREMENT) || !$this->isEmpty($record) || $this->m_forceinsert);
- // If we are set to hide_add, we will only insert into the
- // db if a value has been set (for example by an initial_values
- // method). Also, autoincrement fields might be hidden, and their
- // value is still empty, but they do need to be inserted lateron.
- }
- /**
- * This function is called by the framework to determine if the attribute
- * needs to be saved to the d