/vendor/Adapto/src/Adapto/Entity.php
PHP | 4713 lines | 2431 code | 494 blank | 1788 comment | 475 complexity | 7994ef1883eb7656025eced0247d6d35 MD5 | raw file
Large files files are truncated, but you can click here to view the full 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
- *
- * @copyright (c)2000-2007 Ivo Jansch
- * @copyright (c)2000-2008 Ibuildings.nl BV
- * @license http://www.achievo.org/atk/licensing ATK Open Source License
- *
- */
- /**
- * some includes
- */
- /**
- * Define some flags for entitys. Use the constructor of the Adapto_Entity
- * class to set the flags. (concatenate multiple flags with '|')
- */
- /**
- * No new records may be added
- */
- define("EF_NO_ADD", 1);
- /**
- * Records may not be edited
- */
- define("EF_NO_EDIT", 2);
- /**
- * Records may not be deleted
- */
- define("EF_NO_DELETE", 4);
- /**
- * Immediately after you add a new record,
- * you get the editpage for that record
- */
- define("EF_EDITAFTERADD", 8);
- /**
- * Records may not be searched
- */
- define("EF_NO_SEARCH", 16);
- /**
- * Ignore addFilter filters
- */
- define("EF_NO_FILTER", 32);
- /**
- * Doesn't show an add form on the admin page
- * but a link to the form
- */
- define("EF_ADD_LINK", 64);
- /**
- * Records may not be viewed
- */
- define("EF_NO_VIEW", 128);
- /**
- * Records / trees may be copied
- */
- define("EF_COPY", 256);
- /**
- * If this flag is set and only one record is
- * present on a selectpage, atk automagically
- * selects it and moves on to the target
- */
- define("EF_AUTOSELECT", 512);
- /**
- * If set, atk stores the old values of
- * a record as ["atkorgrec"] in the $rec that
- * gets passed to the postUpdate
- */
- define("EF_TRACK_CHANGES", 1024);
- /**
- * Quick way to disable accessright checking
- * for an entire entity. (Everybody may access this entity)
- */
- define("EF_NO_SECURITY", 2048);
- /**
- * Extended search feature is turned off
- */
- define("EF_NO_EXTENDED_SEARCH", 4096);
- /**
- * Multi-selection of records is turned on
- */
- define("EF_MULTI_RECORD_ACTIONS", 8192);
- /**
- * Multi-priority-selection of records is turned on
- */
- define("EF_MRPA", 16384);
- /**
- * Add locking support to entity, if one user is editing a record,
- * no one else may edit it.
- */
- define("EF_LOCK", 32768);
- /**
- * Multi-language support
- */
- define("EF_ML", 65536);
- /**
- * Quick way to ensable the csv import feature
- */
- define("EF_IMPORT", 131072);
- /**
- * Add CSV export ability to the entity.
- */
- define("EF_EXPORT", 262144);
- /**
- * Enable extended sorting (multicolumn sort)
- */
- define("EF_EXT_SORT", 524288);
- /**
- * Makes an entity cache it's recordlist
- */
- define("EF_CACHE_RECORDLIST", 1048576);
- /**
- * After adding a new record add another one instantaniously.
- */
- define("EF_ADDAFTERADD", 2097152);
- /**
- * No sorting possible.
- */
- define("EF_NO_SORT", 4194304);
- /**
- * Use the dialog popup box when adding a new record for this entity.
- */
- define("EF_ADD_DIALOG", 8388608);
- /**
- * Use the dialog add-or-copy popup box when adding a new record for this entity.
- */
- define("EF_ADDORCOPY_DIALOG", 16777216);
- /**
- * Specific entity flag 1
- */
- define("EF_SPECIFIC_1", 33554432);
- /**
- * Specific entity flag 2
- */
- define("EF_SPECIFIC_2", 67108864);
- /**
- * Specific entity flag 3
- */
- define("EF_SPECIFIC_3", 134217728);
- /**
- * Specific entity flag 4
- */
- define("EF_SPECIFIC_4", 268435456);
- /**
- * Specific entity flag 5
- */
- define("EF_SPECIFIC_5", 536870912);
- /**
- * Records may be copied and open for editing
- */
- define("EF_EDITAFTERCOPY", 1073741824);
- /**
- * Alias for EF_MULTI_RECORD_ACTIONS flag (shortcut)
- */
- define("EF_MRA", EF_MULTI_RECORD_ACTIONS);
- /**
- * Alias for EF_ML flag (typed out)
- */
- define("EF_MULTILANGUAGE", EF_ML);
- /**
- * Aggregate flag to quickly create readonly entitys
- */
- define("EF_READONLY", EF_NO_ADD | EF_NO_DELETE | EF_NO_EDIT);
- /**
- * action status flags
- * Note that these have binary numbers, even though an action could never have
- * two statusses at the same time.
- * This is done however, so the flags can be used as a mask in the setFeedback
- * function.
- */
- /**
- * The action is cancelled
- *
- * action status flag
- */
- define("ACTION_CANCELLED", 1);
- /**
- * The action failed to accomplish it's goal
- *
- * action status flag
- */
- define("ACTION_FAILED", 2);
- /**
- * The action is a success
- *
- * action status flag
- */
- define("ACTION_SUCCESS", 4);
- /**
- * Trigger flags
- */
- define("TRIGGER_NONE", 0);
- define("TRIGGER_AUTO", 1);
- define("TRIGGER_PRE", 2);
- define("TRIGGER_POST", 4);
- define("TRIGGER_ALL", TRIGGER_PRE | TRIGGER_POST);
- /**
- * Multi-record-actions selection modes. These
- * modes are mutually exclusive.
- */
- /**
- * Multiple selections possible.
- */
- define("MRA_MULTI_SELECT", 1);
- /**
- * Only one selection possible.
- */
- define("MRA_SINGLE_SELECT", 2);
- /**
- * No selection possible (e.g. action is always for all (visible) records!).
- */
- define("MRA_NO_SELECT", 3);
- /**
- * The Adapto_Entity class represents a piece of information that is part of an
- * application. This class provides standard functionality for adding,
- * editing and deleting entitys.
- * This class must be seen as an abstract base class: For every piece of
- * information in an application, a class must be derived from this class
- * with specific implementations for that type of entity.
- *
- * @author ijansch
- * @package adapto
- */
- class Adapto_Entity
- {
- /**
- * reference to the class which is used to validate atkentitys
- * the validator is overridable by changing this variabele
- *
- * @var String
- */
- private $m_validate_class = "Adapto_EntityValidator";
- /**
- * Unique field sets of a certain entity.
- *
- * Indicates which field combinations should be unique.
- * It doesn't contain the unique fields which have been set by flag
- * AF_UNIQUE.
- *
- * @var array
- */
- private $m_uniqueFieldSets = array();
- /**
- * Entitys must be initialised using the init() function before they can be
- * used. This member indicated whether the entity has been initialised.
- * @var boolean
- */
- private $m_initialised = false;
- /**
- * Check to prevent double execution of setAttribSizes on pages with more
- * than one form.
- * @var boolean
- */
- private $m_attribsizesset = false;
- /**
- * The list of attributes of an entity. These should be of the class
- * atkAttribute or one of its derivatives.
- * @var array
- */
- private $m_attribList = array();
- /**
- * Index list containing the attributes in the order in which they will
- * appear on screen.
- * @var array
- */
- private $m_attribIndexList = array();
- /**
- * Reference to the page on which the entity is rendering its output.
- * @var atkPage
- */
- private $m_page = NULL;
- /**
- * List of available tabs. Associative array structured like this:
- * array($action=>$arrayOfTabnames)
- * @var array
- */
- private $m_tabList = array();
- /**
- * List of available sections. Associative array structured like this:
- * array($action=>$arrayOfSectionnames)
- * @var array
- */
- private $m_sectionList = array();
- /**
- * Keep track of tabs per attribute.
- * @var array
- */
- private $m_attributeTabs = array();
- /**
- * Keep track if a tab contains attribs (checkEmptyTabs function)
- * @var array
- */
- private $m_filledTabs = array();
- /**
- * The entitytype.
- * @var String
- */
- protected $m_type;
- /**
- * The module of the entity.
- * @var String
- */
- protected $m_module;
- /**
- * The database that the entity is using for storing and loading its data.
- * @var mixed
- */
- protected $m_db = NULL;
- /**
- * The table to use for data storage.
- * @var String
- */
- protected $m_table;
- /**
- * The name of the sequence used for autoincrement fields.
- * @var String
- */
- protected $m_seq;
- /**
- * Name of the attribute that contains the language of a record.
- * Used with ATK's data internationalization feature.
- * @var String
- */
- private $m_lngfield;
- /**
- * List of names of the attributes that form this entity's primary key.
- * @var array
- */
- protected $m_primaryKey = array();
- /**
- * The postvars (or getvars) that are passed to a page will be passed
- * to the class using the dispatch function. We store them in a member
- * variable for easy access.
- * @var array
- */
- protected $m_postvars = array();
- /**
- * The action that the entity is currently performing.
- * @var String
- */
- protected $m_action;
- /**
- * Contains the definition of what needs to rendered partially.
- * If set to NULL not in partial rendering mode.
- */
- public $m_partial = NULL; // defaulted to public
- /**
- * The active action handler.
- * @var atkActionHandler
- */
- protected $m_handler = NULL;
- /**
- * Default order by statement.
- * @var String
- */
- protected $m_default_order = "";
- /**
- * var used for tracking relation within this entity.
- * @todo Remove this member, it's using memory while it's used only in
- * the case of multilanguage entity, and even then only on one
- * occasion.
- * @var array
- */
- private $m_relations = array();
- /**
- * Bitwise mask of entity flags (EF_* flags).
- * @var int
- */
- public $m_flags; // defaulted to public
- /*
- * Name of the field that is used for creating an alphabetical index in
- * admin/select pages.
- * @var String
- */
- private $m_index = "";
- /**
- * Default tab being displayed in add/edit mode.
- * @var String
- */
- private $m_default_tab = "default";
- /**
- * Default sections that are expanded.
- * @var String
- */
- private $m_default_expanded_sections = array();
- /**
- * Record filters, in attributename/required value pairs.
- * @var array
- */
- private $m_filters = array();
- /**
- * Record filters, as a list of sql statements.
- * @var array
- */
- private $m_fuzzyFilters = array();
- /**
- * For speed, we keep track of a list of attributes that we don't have to
- * load in recordlists.
- * @var array
- */
- protected $m_listExcludes = array();
- /**
- * For speed, we keep track of a list of attributes that we don't have to
- * load when in view pages.
- * @todo This can probably be moved to the view handler.
- * @var array
- */
- protected $m_viewExcludes = array();
- /**
- * For speed, we keep track of a list of attributes that have the cascade
- * delete flag set.
- * @todo This should be moved to the delete handler, or should not be
- * cached at all. (caching this on each load is slower than just
- * retrieving the list when it's needed)
- * @var array
- */
- private $m_cascadingAttribs = array();
- /**
- * Actions are mapped to security units.
- *
- * For example, both actions "save" and "add" require access "add". If an
- * item is not in this list, it's treated 'as-is'. Derived entitys may add
- * more mappings to tell the systems that some custom actions require the
- * same privilege as others.
- * Structure: array($action=>$requiredPrivilege)
- * @var array
- */
- protected $m_securityMap = array("save" => "add", "update" => "edit", "multiupdate" => "edit", "copy" => "add", "import" => "add", "editcopy" => "add",
- "search" => "admin", "smartsearch" => "admin");
- /**
- * The right to execute certain actions can be implied by the fact that you
- * have some other right. For example, if you have the right to access a
- * feature (admin right), you may also view that record, and don't need
- * explicit rights to view it. So the 'view' right is said to be 'implied'
- * by the 'admin' right.
- * This is a subtle difference with m_securityMap.
- * @var array
- */
- protected $m_securityImplied = array("view" => "admin");
- /**
- * Name of the entity that is used for privilege checking.
- *
- * If a class is named 'project', then by default, if the system needs to
- * know whether a user may edit a record, the securitymanager searches
- * for 'edit' access on 'project'. However, if an alias is set here, the
- * securitymanger searches for 'edit' on that alias.
- * @var String
- */
- private $m_securityAlias = "";
- /*
- * Entitys can specify actions that require no access level
- * Note: for the moment, the "select" action is always allowed.
- * @todo This may not be correct. We have to find a way to bind the
- * select action to the action that follows after the select.
- * @var array
- */
- private $m_unsecuredActions = array("select", "multiselect", "feedback");
- /**
- * Auto search-actions; action that will be performed if only one record
- * is found.
- * @var array
- */
- private $m_search_action;
- /**
- * Priority actions
- * @todo This, and the priority_min/max members, should be moved
- * to the recordlist
- * @var array
- */
- private $m_priority_actions = array();
- /**
- * Minimum for the mra priority select
- * @var int
- */
- private $m_priority_min = 1;
- /**
- * Maximum for the mra priority select
- * @var int
- */
- private $m_priority_max = 0;
- /**
- * The lock instance
- * @var atkLock
- */
- protected $m_lock = NULL;
- /**
- * List of actions that should give success/failure feedback
- * @var array
- */
- private $m_feedback = array();
- /**
- * Default language used by Multilanguage Entitys.
- * @var String
- */
- protected $m_defaultlanguage = "";
- /**
- * Number to use with numbering
- * @var mixed
- */
- protected $m_numbering = null;
- /**
- * Descriptor template.
- * @var String
- */
- protected $m_descTemplate = NULL;
- /**
- * Descriptor handler.
- * @var Object
- */
- protected $m_descHandler = NULL;
- /**
- * List of action listeners
- * @var Array
- */
- protected $m_actionListeners = array();
- /**
- * List of trigger listeners
- * @var Array
- */
- protected $m_triggerListeners = array();
- /**
- * List of callback functions to manipulate the record actions
- *
- * @var array
- */
- protected $m_recordActionsCallbacks = array();
- /**
- * List of callback functions to add css class to row.
- * See details in atkDGList::getRecordlistData() method
- *
- * @var array
- */
- protected $m_rowClassCallback = array();
- /**
- * Tracker variable to see if we are currently in 'modifier mode' (running inside
- * the scope of a modname_entityname_modifier() method). The variable contains the
- * name of the modifying module.
- * @var String
- */
- private $m_modifier = "";
- /**
- * Extended search action. The action which is called if the user
- * wants to perform an extended search.
- *
- * @var String
- */
- private $m_extended_search_action = NULL;
- /**
- * List of editable list attributes.
- * @var Array
- */
- private $m_editableListAttributes = array();
- /**
- * Multi-record actions, selection mode.
- * @var int
- */
- private $m_mraSelectionMode = MRA_MULTI_SELECT;
- /**
- * The default edit fieldprefix to use for atk
- * @var String
- */
- private $m_edit_fieldprefix = '';
- /**
- * Lock mode.
- *
- * @var int
- */
- private $m_lockMode = 'exclusive'; // atkLock::EXCLUSIVE (would mean atkLock needs to be available!)
- /**
- * Default column name (null means across all columns)
- *
- * @var string
- */
- private $m_defaultColumn = null;
- /**
- * Current maximum attribute order value.
- *
- * @var int
- */
- private $m_attribOrder = 0;
- /**
- * Constructor.
- *
- * This initialises the entity. Derived classes should always call their
- * parent constructor ($this->Adapto_Entity($name, $flags), to initialize the
- * base class.
- * <br>
- * <b>Example:</b>
- * <code>$this->Adapto_Entity('test',EF_NO_EDIT);</code>
- * @param String $type The entitytype (by default equal to the classname)
- * @param int $flags Bitmask of entity flags (EF_*).
- */
- public function __construct($type = "", $flags = 0)
- {
- if ($type == "")
- $type = strtolower(get_class($this));
- Adapto_Util_Debugger::debug("Creating a new Adapto_Entity for $type");
- $this->m_type = $type;
- $this->m_flags = $flags;
- $this->m_module = Adapto_Module::getModuleScope();
- $this->setEditFieldPrefix(Adapto_Config::getGlobal('edit_fieldprefix', ''));
- }
- /**
- * Resolve section. If a section is only prefixed by
- * a dot this means we need to add the default tab
- * before the dot.
- *
- * @param string $section section name
- * @return resolved section name
- */
- function resolveSection($section)
- {
- list($part1, $part2) = (strpos($section, ".") !== false) ? explode('.', $section) : array($section, "");
- if ($part2 != NULL && strlen($part2) > 0 && strlen($part1) == 0)
- return $this->m_default_tab . "." . $part2;
- else if (strlen($part2) == 0 && strlen($part1) == 0)
- return $this->m_default_tab;
- else
- return $section;
- }
- /**
- * Resolve sections.
- *
- * @param array $sections section list
- * @return array resolved section list
- *
- * @see resolveSection
- */
- function resolveSections($sections)
- {
- $result = array();
- foreach ($sections as $section) {
- $result[] = $this->resolveSection($section);
- }
- return $result;
- }
- /**
- * Returns the default column name.
- *
- * @return string default column name
- */
- public function getDefaultColumn()
- {
- return $this->m_defaultColumn;
- }
- /**
- * Set default column name.
- *
- * @param string name default column name
- */
- public function setDefaultColumn($name)
- {
- $this->m_defaultColumn = $name;
- }
- /**
- * Resolve column for sections.
- *
- * If one of the sections contains something after a double
- * colon (:) than that's used as column name, else the default
- * column name will be used.
- *
- * @param array $sections sections
- *
- * @return string column name
- */
- protected function resolveColumn(&$sections)
- {
- $column = $this->getDefaultColumn();
- if (!is_array($sections)) {
- return $column;
- }
- foreach ($sections as &$section) {
- if (strpos($section, ":") !== false) {
- list($section, $column) = explode(':', $section);
- }
- }
- return $column;
- }
- /**
- * Resolve sections, tabs and the order based on the given
- * argument to the attribute add method.
- *
- * @param mixed $sections
- * @param mixed $tabs
- * @param mixed $order
- */
- function resolveSectionsTabsOrder(&$sections, &$tabs, &$column, &$order)
- {
- // Because sections/tabs will probably be used more than the order override option
- // the API for this method now favours the $sections argument. For backwards
- // compatibility we still support the old API ($attribute,$order=0).
- if ($sections !== NULL && is_int($sections)) {
- $order = $sections;
- $sections = array($this->m_default_tab);
- }
- // If no section/tab is specified or tabs are disabled, we use the current default tab
- // (specified with the setDefaultTab method, or "default" otherwise)
- elseif ($sections === NULL || (is_string($sections) && strlen($sections) == 0) || !Adapto_Config::getGlobal("tabs")) {
- $sections = array($this->m_default_tab);
- }
- // Sections should be an array.
- else if ($sections != "*" && !is_array($sections)) {
- $sections = array($sections);
- }
- $column = $this->resolveColumn($sections);
- if (is_array($sections)) {
- $sections = $this->resolveSections($sections);
- }
- // Filter tabs from section names.
- $tabs = $this->getTabsFromSections($sections);
- }
- /**
- * Add an atkAttribute (or one of its derivatives) to the entity.
- * @param atkAttribute $attribute The attribute you want to add
- * @param mixed $sections The sections/tab(s) on which the attribute should be
- * displayed. Can be a tabname (String) or a list of
- * tabs (array) or "*" if the attribute should be
- * displayed on all tabs.
- * @param int $order The order at which the attribute should be displayed.
- * If ommitted, this defaults to 100 for the first
- * attribute, and 100 more for each next attribute that
- * is added.
- * @return atkAttribute the attribute just added
- */
- public function add($attribute, $sections = NULL, $order = 0)
- {
- $tabs = null;
- $column = null;
- $attribute->m_owner = $this->m_type;
- // If we're running inside modifier scope, we have to tell the attribute
- // what module he originated from.
- if ($this->m_modifier != "")
- $attribute->m_module = $this->m_modifier;
- if (!atkReadOptimizer()) {
- $this->resolveSectionsTabsOrder($sections, $tabs, $column, $order);
- // check for parent fieldname (treeview)
- if ($attribute->hasFlag(AF_PARENT)) {
- $this->m_parent = $attribute->fieldName();
- }
- // check for cascading delete flag
- if ($attribute->hasFlag(AF_CASCADE_DELETE)) {
- $this->m_cascadingAttribs[] = $attribute->fieldName();
- }
- if ($attribute->hasFlag(AF_HIDE_LIST) && !$attribute->hasFlag(AF_PRIMARY)) {
- if (!in_array($attribute->fieldName(), $this->m_listExcludes)) {
- $this->m_listExcludes[] = $attribute->fieldName();
- }
- }
- if ($attribute->hasFlag(AF_HIDE_VIEW) && !$attribute->hasFlag(AF_PRIMARY)) {
- if (!in_array($attribute->fieldName(), $this->m_viewExcludes)) {
- $this->m_viewExcludes[] = $attribute->fieldName();
- }
- }
- } else {
- // when the read optimizer is enabled there is no active tab
- // we circument this by putting all attributes on all tabs
- if ($sections !== NULL && is_int($sections))
- $order = $sections;
- $tabs = "*";
- $sections = "*";
- $column = $this->getDefaultColumn();
- }
- // NOTE: THIS SHOULD WORK. BUT, since add() is called from inside the $this
- // constructor, m_ownerInstance ends up being a copy of $this, rather than
- // a reference. Don't ask me why, it has something to do with the way PHP
- // handles the constructor.
- // To work around this, we reassign the this pointer to the attributes as
- // soon as possible AFTER the constructor. (the dispatcher function)
- $attribute->setOwnerInstance($this);
- if ($attribute->hasFlag(AF_PRIMARY)) {
- if (!in_array($attribute->fieldName(), $this->m_primaryKey)) {
- $this->m_primaryKey[] = $attribute->fieldName();
- }
- }
- if ($attribute->hasFlag(AF_MULTILANGUAGE)) {
- $this->m_lngfield = $attribute->fieldName();
- }
- $attribute->init();
- $exist = false;
- if (isset($this->m_attribList[$attribute->fieldName()]) && is_object($this->m_attribList[$attribute->fieldName()])) {
- $exist = true;
- // if order is set, overwrite it with new order, last order will count
- if ($order != 0) {
- $this->m_attribIndexList[$this->m_attribList[$attribute->fieldName()]->m_index]["order"] = $order;
- }
- $attribute->m_index = $this->m_attribList[$attribute->fieldName()]->m_index;
- }
- if (!$exist) {
- if ($order == 0) {
- $this->m_attribOrder += 100;
- $order = $this->m_attribOrder;
- }
- if (!atkReadOptimizer()) {
- // add new tab(s) to the tab list ("*" isn't a tab!)
- if ($tabs != "*") {
- if (!$attribute->hasFlag(AF_HIDE_ADD))
- $this->m_tabList["add"] = isset($this->m_tabList["add"]) ? Adapto_array_merge($this->m_tabList["add"], $tabs) : $tabs;
- if (!$attribute->hasFlag(AF_HIDE_EDIT))
- $this->m_tabList["edit"] = isset($this->m_tabList["edit"]) ? Adapto_array_merge($this->m_tabList["edit"], $tabs) : $tabs;
- if (!$attribute->hasFlag(AF_HIDE_VIEW))
- $this->m_tabList["view"] = isset($this->m_tabList["view"]) ? Adapto_array_merge($this->m_tabList["view"], $tabs) : $tabs;
- }
- if ($sections != "*") {
- if (!$attribute->hasFlag(AF_HIDE_ADD))
- $this->m_sectionList["add"] = isset($this->m_sectionList["add"]) ? Adapto_array_merge($this->m_sectionList["add"], $sections)
- : $sections;
- if (!$attribute->hasFlag(AF_HIDE_EDIT))
- $this->m_sectionList["edit"] = isset($this->m_sectionList['edit']) ? Adapto_array_merge($this->m_sectionList["edit"], $sections)
- : $sections;
- if (!$attribute->hasFlag(AF_HIDE_VIEW))
- $this->m_sectionList["view"] = isset($this->m_sectionList['view']) ? Adapto_array_merge($this->m_sectionList["view"], $sections)
- : $sections;
- }
- }
- $attribute->m_order = $order;
- $this->m_attribIndexList[] = array("name" => $attribute->fieldName(), "tabs" => $tabs, "sections" => $sections, "order" => $attribute->m_order);
- $attribute->m_index = max(array_keys($this->m_attribIndexList)); // might contain gaps
- $attribute->setTabs($tabs);
- $attribute->setSections($sections);
- $this->m_attributeTabs[$attribute->fieldname()] = $tabs;
- }
- // Order the tablist
- $this->m_attribList[$attribute->fieldName()] = &$attribute;
- if (is_subclass_of($attribute, "atkrelation")) {
- $this->m_relations[strtolower(get_class($attribute))][$attribute->fieldName()] = &$attribute;
- }
- $attribute->setTabs($this->m_attributeTabs[$attribute->fieldName()]);
- $attribute->setSections($this->m_attribIndexList[$attribute->m_index]['sections']);
- $attribute->setColumn($column);
- return $attribute;
- }
- /**
- * Add fieldset.
- *
- * To include an attribute label use [attribute.label] inside your
- * template. To include an attribute edit/display field use
- * [attribute.field] inside your template.
- *
- * @param string $name name
- * @param string $template template string
- * @param int $flags attribute flags
- * @param mixed $sections The sections/tab(s) on which the attribute should be
- * displayed. Can be a tabname (String) or a list of
- * tabs (array) or "*" if the attribute should be
- * displayed on all tabs.
- * @param int $order The order at which the attribute should be displayed.
- * If ommitted, this defaults to 100 for the first
- * attribute, and 100 more for each next attribute that
- * is added.
- */
- public function addFieldSet($name, $template, $flags = 0, $sections = NULL, $order = 0)
- {
- useattrib('atkfieldset');
- $this->add(new Adapto_FieldSet($name, $template, $flags), $sections, $order);
- }
- /**
- * Retrieve the tabnames from the sections string (tab.section).
- *
- * @param mixed $sections An array with sections or a section string
- */
- function getTabsFromSections($sections)
- {
- if ($sections == "*" || $sections === NULL)
- return $sections;
- $tabs = array();
- if (!isset($sections))
- $section = array();
- elseif (!is_array($sections))
- $sections = array($sections);
- foreach ($sections as $section) {
- $tabs[] = $this->getTabFromSection($section);
- }
- //when using the tab.sections notation, we can have duplicate tabs
- //strip them out.
- return array_unique($tabs);
- }
- /**
- * Strip section part from a section and return the tab.
- *
- * If no tab name is provided, the default tab is returned.
- *
- * @param string $section The section to get the tab from
- */
- function getTabFromSection($section)
- {
- $tab = ($section == NULL) ? "" : $section;
- if (strstr($tab, ".") !== false)
- list($tab) = explode(".", $tab);
- return (($tab == "") ? $this->m_default_tab : $tab);
- }
- /**
- * Remove an attribute.
- *
- * Completely removes an attribute from an entity.
- * Note: Since other functionality may already depend on the attribute
- * that you are about to remove, it's often better to just hide an
- * attribute if you don't need it.
- * @param String $attribname The name of the attribute to remove.
- */
- function remove($attribname)
- {
- if (is_object($this->m_attribList[$attribname])) {
- Adapto_Util_Debugger::debug("removing attribute $attribname");
- $listindex = $this->m_attribList[$attribname]->m_index;
- unset($this->m_attribList[$attribname]);
- foreach ($this->m_listExcludes as $i => $name) {
- if ($name == $attribname)
- unset($this->m_listExcludes[$i]);
- }
- foreach ($this->m_viewExcludes as $i => $name) {
- if ($name == $attribname)
- unset($this->m_viewExcludes[$i]);
- }
- foreach ($this->m_cascadingAttribs as $i => $name) {
- if ($name == $attribname) {
- unset($this->m_cascadingAttribs[$i]);
- $this->m_cascadingAttribs = array_values($this->m_cascadingAttribs);
- }
- }
- unset($this->m_attribIndexList[$listindex]);
- unset($this->m_attributeTabs[$attribname]);
- }
- }
- /**
- * Returns the table name for this entity.
- *
- * @return string table name
- */
- function getTable()
- {
- return $this->m_table;
- }
- /**
- * Get an attribute by name.
- * @param String $name The name of the attribute to retrieve.
- * @return atkAttribute The attribute.
- */
- function &getAttribute($name)
- {
- $returnValue = isset($this->m_attribList[$name]) ? $this->m_attribList[$name] : NULL;
- return $returnValue;
- }
- /**
- * Checks if the user has filled in something:
- * return true if he has, otherwise return false
- *
- * @param -
- * @return boolean.
- */
- function &filledInForm()
- {
- if (is_null($this->getAttributes()))
- return false;
- $postvars = atkGetPostVar();
- foreach ($this->m_attribList AS $name => $value)
- if (!$value->hasFlag(AF_HIDE_LIST))
- if (!is_array($value->fetchValue($postvars)) && $value->fetchValue($postvars) !== "")
- return true;
- return false;
- }
- /**
- * Gets all the attributes.
- * @return array Array with the attributes.
- */
- function &getAttributes()
- {
- if (isset($this->m_attribList))
- return $this->m_attribList;
- else
- return NULL;
- }
- /**
- * Returns a list of attribute names.
- *
- * @return array attribute names
- */
- function getAttributeNames()
- {
- return array_keys($this->m_attribList);
- }
- /**
- * Gets the attribute order.
- *
- * @param string $name The name of the attribute
- */
- function getAttributeOrder($name)
- {
- return $this->m_attribIndexList[$this->m_attribList[$name]->m_index]["order"];
- }
- /**
- * Sets an attributes order
- *
- * @param string $name The name of the attribute
- * @param int $order The order of the attribute
- */
- function setAttributeOrder($name, $order)
- {
- $this->m_attribList[$name]->m_order = $order;
- $this->m_attribIndexList[$this->m_attribList[$name]->m_index]["order"] = $order;
- }
- /**
- * Checks if the entity has a certain flag set.
- * @param int $flag The flag to check.
- * @return boolean True if the entity has the flag.
- */
- function hasFlag($flag)
- {
- return (($this->m_flags & $flag) == $flag);
- }
- /**
- * Add a flag to the entity.
- * @param int $flag The flag to add.
- */
- function addFlag($flag)
- {
- $this->m_flags |= $flag;
- }
- /**
- * Removes a flag from the entity.
- *
- * @param int $flag The flag to remove from the attribute
- */
- function removeFlag($flag)
- {
- if ($this->hasFlag($flag))
- $this->m_flags ^= $flag;
- }
- /**
- * Returns the entity flags.
- * @return Integer entity flags
- */
- function getFlags()
- {
- return $this->m_flags;
- }
- /**
- * Set entity flags.
- *
- * @param int $flags entity flags
- */
- public function setFlags($flags)
- {
- $this->m_flags = $flags;
- }
- /**
- * Returns the current partial name.
- *
- * @return string partial name
- */
- public function getPartial()
- {
- return $this->m_partial;
- }
- /**
- * Is partial request?
- *
- * @return boolean is partial
- */
- function isPartial()
- {
- return $this->m_partial;
- }
- /**
- * Sets the editable list attributes. If you supply this method
- * with one or more string arguments, all arguments are collected in
- * an array. Else the first parameter will be used.
- *
- * @param array $attrs list of attribute names
- */
- function setEditableListAttributes($attrs)
- {
- if (is_array($attrs))
- $this->m_editableListAttributes = $attrs;
- else
- $this->m_editableListAttributes = func_get_args();
- }
- /**
- * Sets the multi-record-action selection mode. Can either be
- * MRA_MULTI_SELECT (default), MRA_SINGLE_SELECT or
- * MRA_NO_SELECT.
- *
- * @param string $mode selection mode
- */
- function setMRASelectionMode($mode)
- {
- $this->m_mraSelectionMode = $mode;
- }
- /**
- * Returns the multi-record-action selection mode.
- * @return Integer multi-record-action selection mode
- */
- function getMRASelectionMode()
- {
- return $this->m_mraSelectionMode;
- }
- /**
- * Returns the primary key sql expression of a record.
- * @param array $rec The record for which the primary key is calculated.
- * @return String the primary key of the record.
- */
- function primaryKey($rec)
- {
- $primKey = "";
- $nrOfElements = count($this->m_primaryKey);
- for ($i = 0; $i < $nrOfElements; $i++) {
- $p_attrib = &$this->m_attribList[$this->m_primaryKey[$i]];
- $primKey .= $this->m_table . "." . $this->m_primaryKey[$i] . "='" . $p_attrib->value2db($rec) . "'";
- if ($i < ($nrOfElements - 1))
- $primKey .= " AND ";
- }
- return $primKey;
- }
- /**
- * Retrieve the name of the primary key attribute.
- *
- * Note: If an entity has a primary key that consists of multiple attributes,
- * this method will retrieve only the first attribute!
- * @return String First primary key attribute
- */
- function primaryKeyField()
- {
- if (count($this->m_primaryKey) === 0) {
- atkwarning($this->atkEntityType() . "::primaryKeyField() called, but there are no primary key fields defined!");
- return null;
- }
- return $this->m_primaryKey[0];
- }
- /**
- * Returns a primary key template.
- *
- * Like primaryKey(), this method returns a sql expression, but in this
- * case, no actual data is used. Instead, template fields are inserted
- * into the expression. This is useful for rendering multiple primary
- * keys later with a record and a template parser.
- *
- * @return String Primary key template
- */
- function primaryKeyTpl()
- {
- $primKey = "";
- $nrOfElements = count($this->m_primaryKey);
- for ($i = 0; $i < $nrOfElements; $i++) {
- $primKey .= $this->m_primaryKey[$i] . "='[" . $this->m_primaryKey[$i] . "]'";
- if ($i < ($nrOfElements - 1))
- $primKey .= " AND ";
- }
- return $primKey;
- }
- /**
- * Set default sort order for the entity.
- * @param String $orderby Default order by. Can be an attribute name or a
- * SQL expression.
- */
- function setOrder($orderby)
- {
- $this->m_default_order = $orderby;
- }
- /**
- * Get default sort order for the entity.
- * @return String $orderby Default order by. Can be an attribute name or a
- * SQL expression.
- */
- function getOrder()
- {
- return $this->m_default_order;
- }
- /**
- * Set the table that the entity should use.
- *
- * Note: This should be called in the constructor of derived classes,
- * after the base class constructor is called.
- * @param String $tablename The name of the table to use.
- * @param String $seq The name of the sequence to use for autoincrement
- * attributes.
- * @param mixed $db The database connection to use. If ommitted, this
- * defaults to the default database connection.
- * So in apps using only one database, it's not necessary
- * to pass this parameter.
- * You can pass either a connection (atkDb instance), or
- * a string containing the name of the connection to use.
- */
- function setTable($tablename, $seq = "", $db = NULL)
- {
- $this->m_table = $tablename;
- if ($seq == "")
- $seq = $tablename;
- $this->m_seq = $seq;
- $this->m_db = $db;
- }
- /**
- * Sets the database connection.
- *
- * @param string|atkDb $db database name or object
- */
- public function setDb($db)
- {
- $this->m_db = $db;
- }
- /**
- * Get the database connection for this entity.
- * @return atkDb Database connection instance
- */
- function getDb()
- {
- if ($this->m_db == NULL) {
- return atkGetDb();
- } else if (is_object($this->m_db)) {
- return $this->m_db;
- } else {
- // must be a named connection
- return atkGetDb($this->m_db);
- }
- }
- /**
- * Create an alphabetical index.
- *
- * Any string- or textbased attribute can be used to create an
- * alphabetical index in admin- and selectpages.
- * @param String $attribname The name of the attribute for which to create
- * the alphabetical index.
- */
- function setIndex($attribname)
- {
- $this->m_index = $attribname;
- }
- /**
- * Set tab index
- *
- * @param string $tabname Tabname
- * @param int $index Index number
- * @param string $action Action name (add,edit,view)
- */
- function setTabIndex($tabname, $index, $action = "")
- {
- Adapto_Util_Debugger::debug("Adapto_Entity::setTabIndex($tabname,$index,$action)");
- $actionList = array("add", "edit", "view");
- if ($action != "")
- $actionList = array($action);
- foreach ($actionList as $action) {
- $new_index = $index;
- $list = &$this->m_tabList[$action];
- if ($new_index < 0)
- $new_index = 0;
- if ($new_index > count($list))
- $new_index = count($list);
- $current_index = array_search($tabname, $list);
- if ($current_index !== NULL) {
- $tmp = array_splice($list, $current_index, 1);
- array_splice($list, $new_index, 0, $tmp);
- }
- }
- }
- /**
- * Set default tab being displayed in view/add/edit mode.
- * After calling this method, all attributes which are added after the
- * method call without specification of tab will be placed on the default
- * tab. This means you should use this method before you add any
- * attributes to the entity.
- * If you accept the default name for the first tab ("default") you do not
- * need to call this method.
- * @param String $tab the name of the default tab
- */
- function setDefaultTab($tab = "default")
- {
- $this->m_default_tab = $tab;
- }
- /**
- * Get a list of tabs for a certain action.
- * @param String $action The action for which you want to retrieve the
- * list of tabs.
- * @return array The list of tabnames.
- *
- */
- function getTabs($action)
- {
- $list = &$this->m_tabList[$action];
- $disable = $this->checkTabRights($list);
- $tabCode = "";
- if (!is_array($list)) {
- // fallback to view tabs.
- $list = &$this->m_tabList["view"];
- }
- // Attributes can also add tabs to the tablist.
- $this->m_filledTabs = array();
- foreach (array_keys($this->m_attribList) as $attribname) {
- $p_attrib = &$this->m_attribList[$attribname];
- if ($p_attrib->hasFlag(AF_HIDE))
- continue;
- // attributes to which we don't have access are explicitly hidden
- // Only display the attribute if the attribute
- // resides on at least on visible tab
- for ($i = 0, $_i = sizeof($p_attrib->m_tabs); $i < $_i; $i++) {
- if ((is_array($list) && in_array($p_attrib->m_tabs[$i], $list)) || (!is_array($disable) || !in_array($p_attrib->m_tabs[$i], $disable))) {
- break;
- }
- }
- if (is_object($p_attrib)) {
- $additional = $p_attrib->getAdditionalTabs($action);
- if (is_array($additional) && count($additional) > 0) {
- $list = Adapto_array_merge($list, $additional);
- $this->m_filledTabs = Adapto_array_merge($this->m_filledTabs, $additional);
- }
- // Keep track of the tabs that containg attribs
- // so we only display none-empty tabs
- $tabCode = $this->m_attributeTabs[$attribname][0];
- if (!in_array($tabCode, $this->m_filledTabs)) {
- $this->m_filledTabs[] = $tabCode;
- }
- } else {
- Adapto_Util_Debugger::debug("atkentity::getTabs() Warning: $attribname is not an object!?");
- }
- }
- // Check if the currently known tabs all containg attributes
- // so we don't end up with empty tabs
- return $this->checkEmptyTabs($list);
- }
- /**
- * Retrieve the sections for the active tab.
- *
- * @param String $action
- * @return array The active sections.
- */
- function getSections($action)
- {
- $sections = array();
- if (is_array($this->m_sectionList[$action])) {
- foreach ($this->m_sectionList[$action] as $element) {
- list($tab, $sec) = (strpos($element, ".") !== false) ? explode(".", $element) : array($element, null);
- //if this section is on an active tab, we return it.
- if ($tab == $this->getActiveTab() && $sec !== NULL)
- $sections[] = $sec;
- }
- }
- //we do not want duplicate sections on the same tab.
- return array_unique($sections);
- }
- /**
- * Add sections that must be expanded by default.
- *
- */
- function addDefaultExpandedSections()
- {
- $sections = func_get_args();
- $sections = $this->resolveSections($sections);
- $this->m_default_expanded_sections = array_unique(array_merge($sections, $this->m_default_expanded_sections));
- }
- /**
- * Remove sections that must be expanded by default.
- *
- */
- function removeDefaultExpandedSections()
- {
- $sections = func_get_args();
- $this->m_default_expanded_sections = array_diff($this->m_default_expanded_sections, $sections);
- }
- /**
- * Check if the user has the rights to access existing tabs and
- * removes tabs from the list that may not be accessed
- *
- * @param array $tablist Array containing the current tablist
- * @return array with disable tabs
- */
- function checkTabRights(&$tablist)
- {
- global $g_entitys;
- $disable = array();
- if (empty($this->m_module))
- return $disable;
- for ($i = 0, $_i = count($tablist); $i < $_i; $i++) {
- if ($tablist[$i] == "" || $tablist[$i] == "default")
- continue;
- $secMgr = &atkGetSecurityManager();
- // load the $g_entitys array to find out what tabs are required
- if (!isset($g_entitys[$this->m_module][$this->m_type])) {
- include_once(Adapto_Config::getGlobal("atkroot") . "atk/atkentitytools.inc");
- $module = &getModule($this->m_module);
- $module->getEntitys();
- }
- $priv = "tab_" . $tablist[$i];
- if (isset($g_entitys[$this->m_module][$this->m_type]) && Adapto_in_array($priv, $g_entitys[$this->m_module][$this->m_type])) {
- // authorisation is required
- if (!$secMgr->allowed($this->m_module . "." . $this->m_type, "tab_" . $tablist[$i])) {
- Adapto_Util_Debugger::debug("Removing TAB " . $tablist[$i] . " because access to this tab was denied");
- $disable[] = $tablist[$i];
- unset($tablist[$i]);
- }
- }
- }
- if (is_array($tablist)) {
- // we might have now something like:
- // [0]=>tabA,[3]=>tabD
- // we convert this to a 'normal' array:
- // [0]=>tabA,[1]=>tabD;
- $newarray = array();
- foreach ($tablist as $tab)
- $newarray[] = $tab;
- $tablist = $newarray;
- }
- return $disable;
- }
- /**
- * Remove tabs without attribs from the tablist
- * @param array $list The list of tabnames
- * @return array The list of tabnames without the empty tabs.
- *
- */
- function checkEmptyTabs($list)
- {
- $tabList = array();
- if (is_array($list)) {
- foreach ($list AS $tabEntry) {
- if (in_array($tabEntry, $this->m_filledTabs)) {
- $tabList[] = $tabEntry;
- } else {
- Adapto_Util_Debugger::debug("Removing TAB " . $tabEntry . " because it had no attributes assigned");
- }
- }
- }
- return $tabList;
- }
- /**
- * Returns the currently active tab.
- *
- * Note that in themes which use dhtml tabs (tabs without reloads), this
- * method will always return the name of the first tab.
- * @return String The name of the currently visible tab.
- */
- function getActiveTab()
- {
- global $Adapto_VARS;
- $tablist = $this->getTabs($Adapto_VARS["atkaction"]);
- // Note: we may not read atktab from $this->m_postvars, because $this->m_postvars is not filled if this is
- // a nested entity (in a relation for example).
- if (!empty($Adapto_VARS["atktab"]) && in_array($Adapto_VARS["atktab"], $tablist))
- $tab = $Adapto_VARS["atktab"];
- elseif (!empty($this->m_default_tab) && in_array($this->m_default_tab, $tablist))
- $tab = $this->m_default_tab;
- else
- $tab = $tablist[0];
- return $tab;
- }
- /**
- * Get the active sections.
- *
- * @param string $tab The currently active tab
- * @param string $mode The current mode ("edit", "add", etc.)
- */
- function getActiveSections($tab, $mode)
- {
- $activeSections = array();
- if (is_array($this->m_sectionList[$mode])) {
- foreach ($this->m_sectionList[$mode] as $section) {
- if (substr($section, 0, strlen($tab)) == $tab) {
- $sectionName = 'section_' . str_replace('.', '_', $section);
- $key = array("entitytype" => $this->atkentitytype(), "section" => $sectionName);
- $defaultOpen = in_array($section, $this->m_default_expanded_sections);
- if (atkState::get($key, $defaultOpen ? 'opened' : 'closed') != 'closed') {
- $activeSections[] = $section;
- }
- }
- }
- }
- return $activeSections;
- }
- /**
- * Add a recordset filter.
- * @param String $filter The fieldname you want to filter OR a SQL where
- * clause expression.
- * @param String $value Required value. (Ommit this parameter if you pass
- * an SQL expression for $filter.)
- */
- function addFilter($filter, $value = "")
- {
- if ($value == "") {
- …
Large files files are truncated, but you can click here to view the full file