PageRenderTime 40ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 1ms

/library/Adapto/Entity.php

http://github.com/egeniq/adapto
PHP | 2079 lines | 847 code | 258 blank | 974 comment | 201 complexity | 7994ef1883eb7656025eced0247d6d35 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * This file is part of the Adapto Toolkit.
  4. * Detailed copyright and licensing information can be found
  5. * in the doc/COPYRIGHT and doc/LICENSE files which should be
  6. * included in the distribution.
  7. *
  8. * @package adapto
  9. *
  10. * @copyright (c)2000-2007 Ivo Jansch
  11. * @copyright (c)2000-2008 Ibuildings.nl BV
  12. * @license http://www.achievo.org/atk/licensing ATK Open Source License
  13. *
  14. */
  15. /**
  16. * some includes
  17. */
  18. /**
  19. * Define some flags for entitys. Use the constructor of the Adapto_Entity
  20. * class to set the flags. (concatenate multiple flags with '|')
  21. */
  22. /**
  23. * No new records may be added
  24. */
  25. define("EF_NO_ADD", 1);
  26. /**
  27. * Records may not be edited
  28. */
  29. define("EF_NO_EDIT", 2);
  30. /**
  31. * Records may not be deleted
  32. */
  33. define("EF_NO_DELETE", 4);
  34. /**
  35. * Immediately after you add a new record,
  36. * you get the editpage for that record
  37. */
  38. define("EF_EDITAFTERADD", 8);
  39. /**
  40. * Records may not be searched
  41. */
  42. define("EF_NO_SEARCH", 16);
  43. /**
  44. * Ignore addFilter filters
  45. */
  46. define("EF_NO_FILTER", 32);
  47. /**
  48. * Doesn't show an add form on the admin page
  49. * but a link to the form
  50. */
  51. define("EF_ADD_LINK", 64);
  52. /**
  53. * Records may not be viewed
  54. */
  55. define("EF_NO_VIEW", 128);
  56. /**
  57. * Records / trees may be copied
  58. */
  59. define("EF_COPY", 256);
  60. /**
  61. * If this flag is set and only one record is
  62. * present on a selectpage, atk automagically
  63. * selects it and moves on to the target
  64. */
  65. define("EF_AUTOSELECT", 512);
  66. /**
  67. * If set, atk stores the old values of
  68. * a record as ["atkorgrec"] in the $rec that
  69. * gets passed to the postUpdate
  70. */
  71. define("EF_TRACK_CHANGES", 1024);
  72. /**
  73. * Quick way to disable accessright checking
  74. * for an entire entity. (Everybody may access this entity)
  75. */
  76. define("EF_NO_SECURITY", 2048);
  77. /**
  78. * Extended search feature is turned off
  79. */
  80. define("EF_NO_EXTENDED_SEARCH", 4096);
  81. /**
  82. * Multi-selection of records is turned on
  83. */
  84. define("EF_MULTI_RECORD_ACTIONS", 8192);
  85. /**
  86. * Multi-priority-selection of records is turned on
  87. */
  88. define("EF_MRPA", 16384);
  89. /**
  90. * Add locking support to entity, if one user is editing a record,
  91. * no one else may edit it.
  92. */
  93. define("EF_LOCK", 32768);
  94. /**
  95. * Multi-language support
  96. */
  97. define("EF_ML", 65536);
  98. /**
  99. * Quick way to ensable the csv import feature
  100. */
  101. define("EF_IMPORT", 131072);
  102. /**
  103. * Add CSV export ability to the entity.
  104. */
  105. define("EF_EXPORT", 262144);
  106. /**
  107. * Enable extended sorting (multicolumn sort)
  108. */
  109. define("EF_EXT_SORT", 524288);
  110. /**
  111. * Makes an entity cache it's recordlist
  112. */
  113. define("EF_CACHE_RECORDLIST", 1048576);
  114. /**
  115. * After adding a new record add another one instantaniously.
  116. */
  117. define("EF_ADDAFTERADD", 2097152);
  118. /**
  119. * No sorting possible.
  120. */
  121. define("EF_NO_SORT", 4194304);
  122. /**
  123. * Use the dialog popup box when adding a new record for this entity.
  124. */
  125. define("EF_ADD_DIALOG", 8388608);
  126. /**
  127. * Use the dialog add-or-copy popup box when adding a new record for this entity.
  128. */
  129. define("EF_ADDORCOPY_DIALOG", 16777216);
  130. /**
  131. * Specific entity flag 1
  132. */
  133. define("EF_SPECIFIC_1", 33554432);
  134. /**
  135. * Specific entity flag 2
  136. */
  137. define("EF_SPECIFIC_2", 67108864);
  138. /**
  139. * Specific entity flag 3
  140. */
  141. define("EF_SPECIFIC_3", 134217728);
  142. /**
  143. * Specific entity flag 4
  144. */
  145. define("EF_SPECIFIC_4", 268435456);
  146. /**
  147. * Specific entity flag 5
  148. */
  149. define("EF_SPECIFIC_5", 536870912);
  150. /**
  151. * Records may be copied and open for editing
  152. */
  153. define("EF_EDITAFTERCOPY", 1073741824);
  154. /**
  155. * Alias for EF_MULTI_RECORD_ACTIONS flag (shortcut)
  156. */
  157. define("EF_MRA", EF_MULTI_RECORD_ACTIONS);
  158. /**
  159. * Alias for EF_ML flag (typed out)
  160. */
  161. define("EF_MULTILANGUAGE", EF_ML);
  162. /**
  163. * Aggregate flag to quickly create readonly entitys
  164. */
  165. define("EF_READONLY", EF_NO_ADD | EF_NO_DELETE | EF_NO_EDIT);
  166. /**
  167. * action status flags
  168. * Note that these have binary numbers, even though an action could never have
  169. * two statusses at the same time.
  170. * This is done however, so the flags can be used as a mask in the setFeedback
  171. * function.
  172. */
  173. /**
  174. * The action is cancelled
  175. *
  176. * action status flag
  177. */
  178. define("ACTION_CANCELLED", 1);
  179. /**
  180. * The action failed to accomplish it's goal
  181. *
  182. * action status flag
  183. */
  184. define("ACTION_FAILED", 2);
  185. /**
  186. * The action is a success
  187. *
  188. * action status flag
  189. */
  190. define("ACTION_SUCCESS", 4);
  191. /**
  192. * Trigger flags
  193. */
  194. define("TRIGGER_NONE", 0);
  195. define("TRIGGER_AUTO", 1);
  196. define("TRIGGER_PRE", 2);
  197. define("TRIGGER_POST", 4);
  198. define("TRIGGER_ALL", TRIGGER_PRE | TRIGGER_POST);
  199. /**
  200. * Multi-record-actions selection modes. These
  201. * modes are mutually exclusive.
  202. */
  203. /**
  204. * Multiple selections possible.
  205. */
  206. define("MRA_MULTI_SELECT", 1);
  207. /**
  208. * Only one selection possible.
  209. */
  210. define("MRA_SINGLE_SELECT", 2);
  211. /**
  212. * No selection possible (e.g. action is always for all (visible) records!).
  213. */
  214. define("MRA_NO_SELECT", 3);
  215. /**
  216. * The Adapto_Entity class represents a piece of information that is part of an
  217. * application. This class provides standard functionality for adding,
  218. * editing and deleting entitys.
  219. * This class must be seen as an abstract base class: For every piece of
  220. * information in an application, a class must be derived from this class
  221. * with specific implementations for that type of entity.
  222. *
  223. * @author ijansch
  224. * @package adapto
  225. */
  226. class Adapto_Entity
  227. {
  228. /**
  229. * reference to the class which is used to validate atkentitys
  230. * the validator is overridable by changing this variabele
  231. *
  232. * @var String
  233. */
  234. private $m_validate_class = "Adapto_EntityValidator";
  235. /**
  236. * Unique field sets of a certain entity.
  237. *
  238. * Indicates which field combinations should be unique.
  239. * It doesn't contain the unique fields which have been set by flag
  240. * AF_UNIQUE.
  241. *
  242. * @var array
  243. */
  244. private $m_uniqueFieldSets = array();
  245. /**
  246. * Entitys must be initialised using the init() function before they can be
  247. * used. This member indicated whether the entity has been initialised.
  248. * @var boolean
  249. */
  250. private $m_initialised = false;
  251. /**
  252. * Check to prevent double execution of setAttribSizes on pages with more
  253. * than one form.
  254. * @var boolean
  255. */
  256. private $m_attribsizesset = false;
  257. /**
  258. * The list of attributes of an entity. These should be of the class
  259. * atkAttribute or one of its derivatives.
  260. * @var array
  261. */
  262. private $m_attribList = array();
  263. /**
  264. * Index list containing the attributes in the order in which they will
  265. * appear on screen.
  266. * @var array
  267. */
  268. private $m_attribIndexList = array();
  269. /**
  270. * Reference to the page on which the entity is rendering its output.
  271. * @var atkPage
  272. */
  273. private $m_page = NULL;
  274. /**
  275. * List of available tabs. Associative array structured like this:
  276. * array($action=>$arrayOfTabnames)
  277. * @var array
  278. */
  279. private $m_tabList = array();
  280. /**
  281. * List of available sections. Associative array structured like this:
  282. * array($action=>$arrayOfSectionnames)
  283. * @var array
  284. */
  285. private $m_sectionList = array();
  286. /**
  287. * Keep track of tabs per attribute.
  288. * @var array
  289. */
  290. private $m_attributeTabs = array();
  291. /**
  292. * Keep track if a tab contains attribs (checkEmptyTabs function)
  293. * @var array
  294. */
  295. private $m_filledTabs = array();
  296. /**
  297. * The entitytype.
  298. * @var String
  299. */
  300. protected $m_type;
  301. /**
  302. * The module of the entity.
  303. * @var String
  304. */
  305. protected $m_module;
  306. /**
  307. * The database that the entity is using for storing and loading its data.
  308. * @var mixed
  309. */
  310. protected $m_db = NULL;
  311. /**
  312. * The table to use for data storage.
  313. * @var String
  314. */
  315. protected $m_table;
  316. /**
  317. * The name of the sequence used for autoincrement fields.
  318. * @var String
  319. */
  320. protected $m_seq;
  321. /**
  322. * Name of the attribute that contains the language of a record.
  323. * Used with ATK's data internationalization feature.
  324. * @var String
  325. */
  326. private $m_lngfield;
  327. /**
  328. * List of names of the attributes that form this entity's primary key.
  329. * @var array
  330. */
  331. protected $m_primaryKey = array();
  332. /**
  333. * The postvars (or getvars) that are passed to a page will be passed
  334. * to the class using the dispatch function. We store them in a member
  335. * variable for easy access.
  336. * @var array
  337. */
  338. protected $m_postvars = array();
  339. /**
  340. * The action that the entity is currently performing.
  341. * @var String
  342. */
  343. protected $m_action;
  344. /**
  345. * Contains the definition of what needs to rendered partially.
  346. * If set to NULL not in partial rendering mode.
  347. */
  348. public $m_partial = NULL; // defaulted to public
  349. /**
  350. * The active action handler.
  351. * @var atkActionHandler
  352. */
  353. protected $m_handler = NULL;
  354. /**
  355. * Default order by statement.
  356. * @var String
  357. */
  358. protected $m_default_order = "";
  359. /**
  360. * var used for tracking relation within this entity.
  361. * @todo Remove this member, it's using memory while it's used only in
  362. * the case of multilanguage entity, and even then only on one
  363. * occasion.
  364. * @var array
  365. */
  366. private $m_relations = array();
  367. /**
  368. * Bitwise mask of entity flags (EF_* flags).
  369. * @var int
  370. */
  371. public $m_flags; // defaulted to public
  372. /*
  373. * Name of the field that is used for creating an alphabetical index in
  374. * admin/select pages.
  375. * @var String
  376. */
  377. private $m_index = "";
  378. /**
  379. * Default tab being displayed in add/edit mode.
  380. * @var String
  381. */
  382. private $m_default_tab = "default";
  383. /**
  384. * Default sections that are expanded.
  385. * @var String
  386. */
  387. private $m_default_expanded_sections = array();
  388. /**
  389. * Record filters, in attributename/required value pairs.
  390. * @var array
  391. */
  392. private $m_filters = array();
  393. /**
  394. * Record filters, as a list of sql statements.
  395. * @var array
  396. */
  397. private $m_fuzzyFilters = array();
  398. /**
  399. * For speed, we keep track of a list of attributes that we don't have to
  400. * load in recordlists.
  401. * @var array
  402. */
  403. protected $m_listExcludes = array();
  404. /**
  405. * For speed, we keep track of a list of attributes that we don't have to
  406. * load when in view pages.
  407. * @todo This can probably be moved to the view handler.
  408. * @var array
  409. */
  410. protected $m_viewExcludes = array();
  411. /**
  412. * For speed, we keep track of a list of attributes that have the cascade
  413. * delete flag set.
  414. * @todo This should be moved to the delete handler, or should not be
  415. * cached at all. (caching this on each load is slower than just
  416. * retrieving the list when it's needed)
  417. * @var array
  418. */
  419. private $m_cascadingAttribs = array();
  420. /**
  421. * Actions are mapped to security units.
  422. *
  423. * For example, both actions "save" and "add" require access "add". If an
  424. * item is not in this list, it's treated 'as-is'. Derived entitys may add
  425. * more mappings to tell the systems that some custom actions require the
  426. * same privilege as others.
  427. * Structure: array($action=>$requiredPrivilege)
  428. * @var array
  429. */
  430. protected $m_securityMap = array("save" => "add", "update" => "edit", "multiupdate" => "edit", "copy" => "add", "import" => "add", "editcopy" => "add",
  431. "search" => "admin", "smartsearch" => "admin");
  432. /**
  433. * The right to execute certain actions can be implied by the fact that you
  434. * have some other right. For example, if you have the right to access a
  435. * feature (admin right), you may also view that record, and don't need
  436. * explicit rights to view it. So the 'view' right is said to be 'implied'
  437. * by the 'admin' right.
  438. * This is a subtle difference with m_securityMap.
  439. * @var array
  440. */
  441. protected $m_securityImplied = array("view" => "admin");
  442. /**
  443. * Name of the entity that is used for privilege checking.
  444. *
  445. * If a class is named 'project', then by default, if the system needs to
  446. * know whether a user may edit a record, the securitymanager searches
  447. * for 'edit' access on 'project'. However, if an alias is set here, the
  448. * securitymanger searches for 'edit' on that alias.
  449. * @var String
  450. */
  451. private $m_securityAlias = "";
  452. /*
  453. * Entitys can specify actions that require no access level
  454. * Note: for the moment, the "select" action is always allowed.
  455. * @todo This may not be correct. We have to find a way to bind the
  456. * select action to the action that follows after the select.
  457. * @var array
  458. */
  459. private $m_unsecuredActions = array("select", "multiselect", "feedback");
  460. /**
  461. * Auto search-actions; action that will be performed if only one record
  462. * is found.
  463. * @var array
  464. */
  465. private $m_search_action;
  466. /**
  467. * Priority actions
  468. * @todo This, and the priority_min/max members, should be moved
  469. * to the recordlist
  470. * @var array
  471. */
  472. private $m_priority_actions = array();
  473. /**
  474. * Minimum for the mra priority select
  475. * @var int
  476. */
  477. private $m_priority_min = 1;
  478. /**
  479. * Maximum for the mra priority select
  480. * @var int
  481. */
  482. private $m_priority_max = 0;
  483. /**
  484. * The lock instance
  485. * @var atkLock
  486. */
  487. protected $m_lock = NULL;
  488. /**
  489. * List of actions that should give success/failure feedback
  490. * @var array
  491. */
  492. private $m_feedback = array();
  493. /**
  494. * Default language used by Multilanguage Entitys.
  495. * @var String
  496. */
  497. protected $m_defaultlanguage = "";
  498. /**
  499. * Number to use with numbering
  500. * @var mixed
  501. */
  502. protected $m_numbering = null;
  503. /**
  504. * Descriptor template.
  505. * @var String
  506. */
  507. protected $m_descTemplate = NULL;
  508. /**
  509. * Descriptor handler.
  510. * @var Object
  511. */
  512. protected $m_descHandler = NULL;
  513. /**
  514. * List of action listeners
  515. * @var Array
  516. */
  517. protected $m_actionListeners = array();
  518. /**
  519. * List of trigger listeners
  520. * @var Array
  521. */
  522. protected $m_triggerListeners = array();
  523. /**
  524. * List of callback functions to manipulate the record actions
  525. *
  526. * @var array
  527. */
  528. protected $m_recordActionsCallbacks = array();
  529. /**
  530. * List of callback functions to add css class to row.
  531. * See details in atkDGList::getRecordlistData() method
  532. *
  533. * @var array
  534. */
  535. protected $m_rowClassCallback = array();
  536. /**
  537. * Tracker variable to see if we are currently in 'modifier mode' (running inside
  538. * the scope of a modname_entityname_modifier() method). The variable contains the
  539. * name of the modifying module.
  540. * @var String
  541. */
  542. private $m_modifier = "";
  543. /**
  544. * Extended search action. The action which is called if the user
  545. * wants to perform an extended search.
  546. *
  547. * @var String
  548. */
  549. private $m_extended_search_action = NULL;
  550. /**
  551. * List of editable list attributes.
  552. * @var Array
  553. */
  554. private $m_editableListAttributes = array();
  555. /**
  556. * Multi-record actions, selection mode.
  557. * @var int
  558. */
  559. private $m_mraSelectionMode = MRA_MULTI_SELECT;
  560. /**
  561. * The default edit fieldprefix to use for atk
  562. * @var String
  563. */
  564. private $m_edit_fieldprefix = '';
  565. /**
  566. * Lock mode.
  567. *
  568. * @var int
  569. */
  570. private $m_lockMode = 'exclusive'; // atkLock::EXCLUSIVE (would mean atkLock needs to be available!)
  571. /**
  572. * Default column name (null means across all columns)
  573. *
  574. * @var string
  575. */
  576. private $m_defaultColumn = null;
  577. /**
  578. * Current maximum attribute order value.
  579. *
  580. * @var int
  581. */
  582. private $m_attribOrder = 0;
  583. /**
  584. * Constructor.
  585. *
  586. * This initialises the entity. Derived classes should always call their
  587. * parent constructor ($this->Adapto_Entity($name, $flags), to initialize the
  588. * base class.
  589. * <br>
  590. * <b>Example:</b>
  591. * <code>$this->Adapto_Entity('test',EF_NO_EDIT);</code>
  592. * @param String $type The entitytype (by default equal to the classname)
  593. * @param int $flags Bitmask of entity flags (EF_*).
  594. */
  595. public function __construct($type = "", $flags = 0)
  596. {
  597. if ($type == "")
  598. $type = strtolower(get_class($this));
  599. Adapto_Util_Debugger::debug("Creating a new Adapto_Entity for $type");
  600. $this->m_type = $type;
  601. $this->m_flags = $flags;
  602. $this->m_module = Adapto_Module::getModuleScope();
  603. $this->setEditFieldPrefix(Adapto_Config::getGlobal('edit_fieldprefix', ''));
  604. }
  605. /**
  606. * Resolve section. If a section is only prefixed by
  607. * a dot this means we need to add the default tab
  608. * before the dot.
  609. *
  610. * @param string $section section name
  611. * @return resolved section name
  612. */
  613. function resolveSection($section)
  614. {
  615. list($part1, $part2) = (strpos($section, ".") !== false) ? explode('.', $section) : array($section, "");
  616. if ($part2 != NULL && strlen($part2) > 0 && strlen($part1) == 0)
  617. return $this->m_default_tab . "." . $part2;
  618. else if (strlen($part2) == 0 && strlen($part1) == 0)
  619. return $this->m_default_tab;
  620. else
  621. return $section;
  622. }
  623. /**
  624. * Resolve sections.
  625. *
  626. * @param array $sections section list
  627. * @return array resolved section list
  628. *
  629. * @see resolveSection
  630. */
  631. function resolveSections($sections)
  632. {
  633. $result = array();
  634. foreach ($sections as $section) {
  635. $result[] = $this->resolveSection($section);
  636. }
  637. return $result;
  638. }
  639. /**
  640. * Returns the default column name.
  641. *
  642. * @return string default column name
  643. */
  644. public function getDefaultColumn()
  645. {
  646. return $this->m_defaultColumn;
  647. }
  648. /**
  649. * Set default column name.
  650. *
  651. * @param string name default column name
  652. */
  653. public function setDefaultColumn($name)
  654. {
  655. $this->m_defaultColumn = $name;
  656. }
  657. /**
  658. * Resolve column for sections.
  659. *
  660. * If one of the sections contains something after a double
  661. * colon (:) than that's used as column name, else the default
  662. * column name will be used.
  663. *
  664. * @param array $sections sections
  665. *
  666. * @return string column name
  667. */
  668. protected function resolveColumn(&$sections)
  669. {
  670. $column = $this->getDefaultColumn();
  671. if (!is_array($sections)) {
  672. return $column;
  673. }
  674. foreach ($sections as &$section) {
  675. if (strpos($section, ":") !== false) {
  676. list($section, $column) = explode(':', $section);
  677. }
  678. }
  679. return $column;
  680. }
  681. /**
  682. * Resolve sections, tabs and the order based on the given
  683. * argument to the attribute add method.
  684. *
  685. * @param mixed $sections
  686. * @param mixed $tabs
  687. * @param mixed $order
  688. */
  689. function resolveSectionsTabsOrder(&$sections, &$tabs, &$column, &$order)
  690. {
  691. // Because sections/tabs will probably be used more than the order override option
  692. // the API for this method now favours the $sections argument. For backwards
  693. // compatibility we still support the old API ($attribute,$order=0).
  694. if ($sections !== NULL && is_int($sections)) {
  695. $order = $sections;
  696. $sections = array($this->m_default_tab);
  697. }
  698. // If no section/tab is specified or tabs are disabled, we use the current default tab
  699. // (specified with the setDefaultTab method, or "default" otherwise)
  700. elseif ($sections === NULL || (is_string($sections) && strlen($sections) == 0) || !Adapto_Config::getGlobal("tabs")) {
  701. $sections = array($this->m_default_tab);
  702. }
  703. // Sections should be an array.
  704. else if ($sections != "*" && !is_array($sections)) {
  705. $sections = array($sections);
  706. }
  707. $column = $this->resolveColumn($sections);
  708. if (is_array($sections)) {
  709. $sections = $this->resolveSections($sections);
  710. }
  711. // Filter tabs from section names.
  712. $tabs = $this->getTabsFromSections($sections);
  713. }
  714. /**
  715. * Add an atkAttribute (or one of its derivatives) to the entity.
  716. * @param atkAttribute $attribute The attribute you want to add
  717. * @param mixed $sections The sections/tab(s) on which the attribute should be
  718. * displayed. Can be a tabname (String) or a list of
  719. * tabs (array) or "*" if the attribute should be
  720. * displayed on all tabs.
  721. * @param int $order The order at which the attribute should be displayed.
  722. * If ommitted, this defaults to 100 for the first
  723. * attribute, and 100 more for each next attribute that
  724. * is added.
  725. * @return atkAttribute the attribute just added
  726. */
  727. public function add($attribute, $sections = NULL, $order = 0)
  728. {
  729. $tabs = null;
  730. $column = null;
  731. $attribute->m_owner = $this->m_type;
  732. // If we're running inside modifier scope, we have to tell the attribute
  733. // what module he originated from.
  734. if ($this->m_modifier != "")
  735. $attribute->m_module = $this->m_modifier;
  736. if (!atkReadOptimizer()) {
  737. $this->resolveSectionsTabsOrder($sections, $tabs, $column, $order);
  738. // check for parent fieldname (treeview)
  739. if ($attribute->hasFlag(AF_PARENT)) {
  740. $this->m_parent = $attribute->fieldName();
  741. }
  742. // check for cascading delete flag
  743. if ($attribute->hasFlag(AF_CASCADE_DELETE)) {
  744. $this->m_cascadingAttribs[] = $attribute->fieldName();
  745. }
  746. if ($attribute->hasFlag(AF_HIDE_LIST) && !$attribute->hasFlag(AF_PRIMARY)) {
  747. if (!in_array($attribute->fieldName(), $this->m_listExcludes)) {
  748. $this->m_listExcludes[] = $attribute->fieldName();
  749. }
  750. }
  751. if ($attribute->hasFlag(AF_HIDE_VIEW) && !$attribute->hasFlag(AF_PRIMARY)) {
  752. if (!in_array($attribute->fieldName(), $this->m_viewExcludes)) {
  753. $this->m_viewExcludes[] = $attribute->fieldName();
  754. }
  755. }
  756. } else {
  757. // when the read optimizer is enabled there is no active tab
  758. // we circument this by putting all attributes on all tabs
  759. if ($sections !== NULL && is_int($sections))
  760. $order = $sections;
  761. $tabs = "*";
  762. $sections = "*";
  763. $column = $this->getDefaultColumn();
  764. }
  765. // NOTE: THIS SHOULD WORK. BUT, since add() is called from inside the $this
  766. // constructor, m_ownerInstance ends up being a copy of $this, rather than
  767. // a reference. Don't ask me why, it has something to do with the way PHP
  768. // handles the constructor.
  769. // To work around this, we reassign the this pointer to the attributes as
  770. // soon as possible AFTER the constructor. (the dispatcher function)
  771. $attribute->setOwnerInstance($this);
  772. if ($attribute->hasFlag(AF_PRIMARY)) {
  773. if (!in_array($attribute->fieldName(), $this->m_primaryKey)) {
  774. $this->m_primaryKey[] = $attribute->fieldName();
  775. }
  776. }
  777. if ($attribute->hasFlag(AF_MULTILANGUAGE)) {
  778. $this->m_lngfield = $attribute->fieldName();
  779. }
  780. $attribute->init();
  781. $exist = false;
  782. if (isset($this->m_attribList[$attribute->fieldName()]) && is_object($this->m_attribList[$attribute->fieldName()])) {
  783. $exist = true;
  784. // if order is set, overwrite it with new order, last order will count
  785. if ($order != 0) {
  786. $this->m_attribIndexList[$this->m_attribList[$attribute->fieldName()]->m_index]["order"] = $order;
  787. }
  788. $attribute->m_index = $this->m_attribList[$attribute->fieldName()]->m_index;
  789. }
  790. if (!$exist) {
  791. if ($order == 0) {
  792. $this->m_attribOrder += 100;
  793. $order = $this->m_attribOrder;
  794. }
  795. if (!atkReadOptimizer()) {
  796. // add new tab(s) to the tab list ("*" isn't a tab!)
  797. if ($tabs != "*") {
  798. if (!$attribute->hasFlag(AF_HIDE_ADD))
  799. $this->m_tabList["add"] = isset($this->m_tabList["add"]) ? Adapto_array_merge($this->m_tabList["add"], $tabs) : $tabs;
  800. if (!$attribute->hasFlag(AF_HIDE_EDIT))
  801. $this->m_tabList["edit"] = isset($this->m_tabList["edit"]) ? Adapto_array_merge($this->m_tabList["edit"], $tabs) : $tabs;
  802. if (!$attribute->hasFlag(AF_HIDE_VIEW))
  803. $this->m_tabList["view"] = isset($this->m_tabList["view"]) ? Adapto_array_merge($this->m_tabList["view"], $tabs) : $tabs;
  804. }
  805. if ($sections != "*") {
  806. if (!$attribute->hasFlag(AF_HIDE_ADD))
  807. $this->m_sectionList["add"] = isset($this->m_sectionList["add"]) ? Adapto_array_merge($this->m_sectionList["add"], $sections)
  808. : $sections;
  809. if (!$attribute->hasFlag(AF_HIDE_EDIT))
  810. $this->m_sectionList["edit"] = isset($this->m_sectionList['edit']) ? Adapto_array_merge($this->m_sectionList["edit"], $sections)
  811. : $sections;
  812. if (!$attribute->hasFlag(AF_HIDE_VIEW))
  813. $this->m_sectionList["view"] = isset($this->m_sectionList['view']) ? Adapto_array_merge($this->m_sectionList["view"], $sections)
  814. : $sections;
  815. }
  816. }
  817. $attribute->m_order = $order;
  818. $this->m_attribIndexList[] = array("name" => $attribute->fieldName(), "tabs" => $tabs, "sections" => $sections, "order" => $attribute->m_order);
  819. $attribute->m_index = max(array_keys($this->m_attribIndexList)); // might contain gaps
  820. $attribute->setTabs($tabs);
  821. $attribute->setSections($sections);
  822. $this->m_attributeTabs[$attribute->fieldname()] = $tabs;
  823. }
  824. // Order the tablist
  825. $this->m_attribList[$attribute->fieldName()] = &$attribute;
  826. if (is_subclass_of($attribute, "atkrelation")) {
  827. $this->m_relations[strtolower(get_class($attribute))][$attribute->fieldName()] = &$attribute;
  828. }
  829. $attribute->setTabs($this->m_attributeTabs[$attribute->fieldName()]);
  830. $attribute->setSections($this->m_attribIndexList[$attribute->m_index]['sections']);
  831. $attribute->setColumn($column);
  832. return $attribute;
  833. }
  834. /**
  835. * Add fieldset.
  836. *
  837. * To include an attribute label use [attribute.label] inside your
  838. * template. To include an attribute edit/display field use
  839. * [attribute.field] inside your template.
  840. *
  841. * @param string $name name
  842. * @param string $template template string
  843. * @param int $flags attribute flags
  844. * @param mixed $sections The sections/tab(s) on which the attribute should be
  845. * displayed. Can be a tabname (String) or a list of
  846. * tabs (array) or "*" if the attribute should be
  847. * displayed on all tabs.
  848. * @param int $order The order at which the attribute should be displayed.
  849. * If ommitted, this defaults to 100 for the first
  850. * attribute, and 100 more for each next attribute that
  851. * is added.
  852. */
  853. public function addFieldSet($name, $template, $flags = 0, $sections = NULL, $order = 0)
  854. {
  855. useattrib('atkfieldset');
  856. $this->add(new Adapto_FieldSet($name, $template, $flags), $sections, $order);
  857. }
  858. /**
  859. * Retrieve the tabnames from the sections string (tab.section).
  860. *
  861. * @param mixed $sections An array with sections or a section string
  862. */
  863. function getTabsFromSections($sections)
  864. {
  865. if ($sections == "*" || $sections === NULL)
  866. return $sections;
  867. $tabs = array();
  868. if (!isset($sections))
  869. $section = array();
  870. elseif (!is_array($sections))
  871. $sections = array($sections);
  872. foreach ($sections as $section) {
  873. $tabs[] = $this->getTabFromSection($section);
  874. }
  875. //when using the tab.sections notation, we can have duplicate tabs
  876. //strip them out.
  877. return array_unique($tabs);
  878. }
  879. /**
  880. * Strip section part from a section and return the tab.
  881. *
  882. * If no tab name is provided, the default tab is returned.
  883. *
  884. * @param string $section The section to get the tab from
  885. */
  886. function getTabFromSection($section)
  887. {
  888. $tab = ($section == NULL) ? "" : $section;
  889. if (strstr($tab, ".") !== false)
  890. list($tab) = explode(".", $tab);
  891. return (($tab == "") ? $this->m_default_tab : $tab);
  892. }
  893. /**
  894. * Remove an attribute.
  895. *
  896. * Completely removes an attribute from an entity.
  897. * Note: Since other functionality may already depend on the attribute
  898. * that you are about to remove, it's often better to just hide an
  899. * attribute if you don't need it.
  900. * @param String $attribname The name of the attribute to remove.
  901. */
  902. function remove($attribname)
  903. {
  904. if (is_object($this->m_attribList[$attribname])) {
  905. Adapto_Util_Debugger::debug("removing attribute $attribname");
  906. $listindex = $this->m_attribList[$attribname]->m_index;
  907. unset($this->m_attribList[$attribname]);
  908. foreach ($this->m_listExcludes as $i => $name) {
  909. if ($name == $attribname)
  910. unset($this->m_listExcludes[$i]);
  911. }
  912. foreach ($this->m_viewExcludes as $i => $name) {
  913. if ($name == $attribname)
  914. unset($this->m_viewExcludes[$i]);
  915. }
  916. foreach ($this->m_cascadingAttribs as $i => $name) {
  917. if ($name == $attribname) {
  918. unset($this->m_cascadingAttribs[$i]);
  919. $this->m_cascadingAttribs = array_values($this->m_cascadingAttribs);
  920. }
  921. }
  922. unset($this->m_attribIndexList[$listindex]);
  923. unset($this->m_attributeTabs[$attribname]);
  924. }
  925. }
  926. /**
  927. * Returns the table name for this entity.
  928. *
  929. * @return string table name
  930. */
  931. function getTable()
  932. {
  933. return $this->m_table;
  934. }
  935. /**
  936. * Get an attribute by name.
  937. * @param String $name The name of the attribute to retrieve.
  938. * @return atkAttribute The attribute.
  939. */
  940. function &getAttribute($name)
  941. {
  942. $returnValue = isset($this->m_attribList[$name]) ? $this->m_attribList[$name] : NULL;
  943. return $returnValue;
  944. }
  945. /**
  946. * Checks if the user has filled in something:
  947. * return true if he has, otherwise return false
  948. *
  949. * @param -
  950. * @return boolean.
  951. */
  952. function &filledInForm()
  953. {
  954. if (is_null($this->getAttributes()))
  955. return false;
  956. $postvars = atkGetPostVar();
  957. foreach ($this->m_attribList AS $name => $value)
  958. if (!$value->hasFlag(AF_HIDE_LIST))
  959. if (!is_array($value->fetchValue($postvars)) && $value->fetchValue($postvars) !== "")
  960. return true;
  961. return false;
  962. }
  963. /**
  964. * Gets all the attributes.
  965. * @return array Array with the attributes.
  966. */
  967. function &getAttributes()
  968. {
  969. if (isset($this->m_attribList))
  970. return $this->m_attribList;
  971. else
  972. return NULL;
  973. }
  974. /**
  975. * Returns a list of attribute names.
  976. *
  977. * @return array attribute names
  978. */
  979. function getAttributeNames()
  980. {
  981. return array_keys($this->m_attribList);
  982. }
  983. /**
  984. * Gets the attribute order.
  985. *
  986. * @param string $name The name of the attribute
  987. */
  988. function getAttributeOrder($name)
  989. {
  990. return $this->m_attribIndexList[$this->m_attribList[$name]->m_index]["order"];
  991. }
  992. /**
  993. * Sets an attributes order
  994. *
  995. * @param string $name The name of the attribute
  996. * @param int $order The order of the attribute
  997. */
  998. function setAttributeOrder($name, $order)
  999. {
  1000. $this->m_attribList[$name]->m_order = $order;
  1001. $this->m_attribIndexList[$this->m_attribList[$name]->m_index]["order"] = $order;
  1002. }
  1003. /**
  1004. * Checks if the entity has a certain flag set.
  1005. * @param int $flag The flag to check.
  1006. * @return boolean True if the entity has the flag.
  1007. */
  1008. function hasFlag($flag)
  1009. {
  1010. return (($this->m_flags & $flag) == $flag);
  1011. }
  1012. /**
  1013. * Add a flag to the entity.
  1014. * @param int $flag The flag to add.
  1015. */
  1016. function addFlag($flag)
  1017. {
  1018. $this->m_flags |= $flag;
  1019. }
  1020. /**
  1021. * Removes a flag from the entity.
  1022. *
  1023. * @param int $flag The flag to remove from the attribute
  1024. */
  1025. function removeFlag($flag)
  1026. {
  1027. if ($this->hasFlag($flag))
  1028. $this->m_flags ^= $flag;
  1029. }
  1030. /**
  1031. * Returns the entity flags.
  1032. * @return Integer entity flags
  1033. */
  1034. function getFlags()
  1035. {
  1036. return $this->m_flags;
  1037. }
  1038. /**
  1039. * Set entity flags.
  1040. *
  1041. * @param int $flags entity flags
  1042. */
  1043. public function setFlags($flags)
  1044. {
  1045. $this->m_flags = $flags;
  1046. }
  1047. /**
  1048. * Returns the current partial name.
  1049. *
  1050. * @return string partial name
  1051. */
  1052. public function getPartial()
  1053. {
  1054. return $this->m_partial;
  1055. }
  1056. /**
  1057. * Is partial request?
  1058. *
  1059. * @return boolean is partial
  1060. */
  1061. function isPartial()
  1062. {
  1063. return $this->m_partial;
  1064. }
  1065. /**
  1066. * Sets the editable list attributes. If you supply this method
  1067. * with one or more string arguments, all arguments are collected in
  1068. * an array. Else the first parameter will be used.
  1069. *
  1070. * @param array $attrs list of attribute names
  1071. */
  1072. function setEditableListAttributes($attrs)
  1073. {
  1074. if (is_array($attrs))
  1075. $this->m_editableListAttributes = $attrs;
  1076. else
  1077. $this->m_editableListAttributes = func_get_args();
  1078. }
  1079. /**
  1080. * Sets the multi-record-action selection mode. Can either be
  1081. * MRA_MULTI_SELECT (default), MRA_SINGLE_SELECT or
  1082. * MRA_NO_SELECT.
  1083. *
  1084. * @param string $mode selection mode
  1085. */
  1086. function setMRASelectionMode($mode)
  1087. {
  1088. $this->m_mraSelectionMode = $mode;
  1089. }
  1090. /**
  1091. * Returns the multi-record-action selection mode.
  1092. * @return Integer multi-record-action selection mode
  1093. */
  1094. function getMRASelectionMode()
  1095. {
  1096. return $this->m_mraSelectionMode;
  1097. }
  1098. /**
  1099. * Returns the primary key sql expression of a record.
  1100. * @param array $rec The record for which the primary key is calculated.
  1101. * @return String the primary key of the record.
  1102. */
  1103. function primaryKey($rec)
  1104. {
  1105. $primKey = "";
  1106. $nrOfElements = count($this->m_primaryKey);
  1107. for ($i = 0; $i < $nrOfElements; $i++) {
  1108. $p_attrib = &$this->m_attribList[$this->m_primaryKey[$i]];
  1109. $primKey .= $this->m_table . "." . $this->m_primaryKey[$i] . "='" . $p_attrib->value2db($rec) . "'";
  1110. if ($i < ($nrOfElements - 1))
  1111. $primKey .= " AND ";
  1112. }
  1113. return $primKey;
  1114. }
  1115. /**
  1116. * Retrieve the name of the primary key attribute.
  1117. *
  1118. * Note: If an entity has a primary key that consists of multiple attributes,
  1119. * this method will retrieve only the first attribute!
  1120. * @return String First primary key attribute
  1121. */
  1122. function primaryKeyField()
  1123. {
  1124. if (count($this->m_primaryKey) === 0) {
  1125. atkwarning($this->atkEntityType() . "::primaryKeyField() called, but there are no primary key fields defined!");
  1126. return null;
  1127. }
  1128. return $this->m_primaryKey[0];
  1129. }
  1130. /**
  1131. * Returns a primary key template.
  1132. *
  1133. * Like primaryKey(), this method returns a sql expression, but in this
  1134. * case, no actual data is used. Instead, template fields are inserted
  1135. * into the expression. This is useful for rendering multiple primary
  1136. * keys later with a record and a template parser.
  1137. *
  1138. * @return String Primary key template
  1139. */
  1140. function primaryKeyTpl()
  1141. {
  1142. $primKey = "";
  1143. $nrOfElements = count($this->m_primaryKey);
  1144. for ($i = 0; $i < $nrOfElements; $i++) {
  1145. $primKey .= $this->m_primaryKey[$i] . "='[" . $this->m_primaryKey[$i] . "]'";
  1146. if ($i < ($nrOfElements - 1))
  1147. $primKey .= " AND ";
  1148. }
  1149. return $primKey;
  1150. }
  1151. /**
  1152. * Set default sort order for the entity.
  1153. * @param String $orderby Default order by. Can be an attribute name or a
  1154. * SQL expression.
  1155. */
  1156. function setOrder($orderby)
  1157. {
  1158. $this->m_default_order = $orderby;
  1159. }
  1160. /**
  1161. * Get default sort order for the entity.
  1162. * @return String $orderby Default order by. Can be an attribute name or a
  1163. * SQL expression.
  1164. */
  1165. function getOrder()
  1166. {
  1167. return $this->m_default_order;
  1168. }
  1169. /**
  1170. * Set the table that the entity should use.
  1171. *
  1172. * Note: This should be called in the constructor of derived classes,
  1173. * after the base class constructor is called.
  1174. * @param String $tablename The name of the table to use.
  1175. * @param String $seq The name of the sequence to use for autoincrement
  1176. * attributes.
  1177. * @param mixed $db The database connection to use. If ommitted, this
  1178. * defaults to the default database connection.
  1179. * So in apps using only one database, it's not necessary
  1180. * to pass this parameter.
  1181. * You can pass either a connection (atkDb instance), or
  1182. * a string containing the name of the connection to use.
  1183. */
  1184. function setTable($tablename, $seq = "", $db = NULL)
  1185. {
  1186. $this->m_table = $tablename;
  1187. if ($seq == "")
  1188. $seq = $tablename;
  1189. $this->m_seq = $seq;
  1190. $this->m_db = $db;
  1191. }
  1192. /**
  1193. * Sets the database connection.
  1194. *
  1195. * @param string|atkDb $db database name or object
  1196. */
  1197. public function setDb($db)
  1198. {
  1199. $this->m_db = $db;
  1200. }
  1201. /**
  1202. * Get the database connection for this entity.
  1203. * @return atkDb Database connection instance
  1204. */
  1205. function getDb()
  1206. {
  1207. if ($this->m_db == NULL) {
  1208. return atkGetDb();
  1209. } else if (is_object($this->m_db)) {
  1210. return $this->m_db;
  1211. } else {
  1212. // must be a named connection
  1213. return atkGetDb($this->m_db);
  1214. }
  1215. }
  1216. /**
  1217. * Create an alphabetical index.
  1218. *
  1219. * Any string- or textbased attribute can be used to create an
  1220. * alphabetical index in admin- and selectpages.
  1221. * @param String $attribname The name of the attribute for which to create
  1222. * the alphabetical index.
  1223. */
  1224. function setIndex($attribname)
  1225. {
  1226. $this->m_index = $attribname;
  1227. }
  1228. /**
  1229. * Set tab index
  1230. *
  1231. * @param string $tabname Tabname
  1232. * @param int $index Index number
  1233. * @param string $action Action name (add,edit,view)
  1234. */
  1235. function setTabIndex($tabname, $index, $action = "")
  1236. {
  1237. Adapto_Util_Debugger::debug("Adapto_Entity::setTabIndex($tabname,$index,$action)");
  1238. $actionList = array("add", "edit", "view");
  1239. if ($action != "")
  1240. $actionList = array($action);
  1241. foreach ($actionList as $action) {
  1242. $new_index = $index;
  1243. $list = &$this->m_tabList[$action];
  1244. if ($new_index < 0)
  1245. $new_index = 0;
  1246. if ($new_index > count($list))
  1247. $new_index = count($list);
  1248. $current_index = array_search($tabname, $list);
  1249. if ($current_index !== NULL) {
  1250. $tmp = array_splice($list, $current_index, 1);
  1251. array_splice($list, $new_index, 0, $tmp);
  1252. }
  1253. }
  1254. }
  1255. /**
  1256. * Set default tab being displayed in view/add/edit mode.
  1257. * After calling this method, all attributes which are added after the
  1258. * method call without specification of tab will be placed on the default
  1259. * tab. This means you should use this method before you add any
  1260. * attributes to the entity.
  1261. * If you accept the default name for the first tab ("default") you do not
  1262. * need to call this method.
  1263. * @param String $tab the name of the default tab
  1264. */
  1265. function setDefaultTab($tab = "default")
  1266. {
  1267. $this->m_default_tab = $tab;
  1268. }
  1269. /**
  1270. * Get a list of tabs for a certain action.
  1271. * @param String $action The action for which you want to retrieve the
  1272. * list of tabs.
  1273. * @return array The list of tabnames.
  1274. *
  1275. */
  1276. function getTabs($action)
  1277. {
  1278. $list = &$this->m_tabList[$action];
  1279. $disable = $this->checkTabRights($list);
  1280. $tabCode = "";
  1281. if (!is_array($list)) {
  1282. // fallback to view tabs.
  1283. $list = &$this->m_tabList["view"];
  1284. }
  1285. // Attributes can also add tabs to the tablist.
  1286. $this->m_filledTabs = array();
  1287. foreach (array_keys($this->m_attribList) as $attribname) {
  1288. $p_attrib = &$this->m_attribList[$attribname];
  1289. if ($p_attrib->hasFlag(AF_HIDE))
  1290. continue;
  1291. // attributes to which we don't have access are explicitly hidden
  1292. // Only display the attribute if the attribute
  1293. // resides on at least on visible tab
  1294. for ($i = 0, $_i = sizeof($p_attrib->m_tabs); $i < $_i; $i++) {
  1295. if ((is_array($list) && in_array($p_attrib->m_tabs[$i], $list)) || (!is_array($disable) || !in_array($p_attrib->m_tabs[$i], $disable))) {
  1296. break;
  1297. }
  1298. }
  1299. if (is_object($p_attrib)) {
  1300. $additional = $p_attrib->getAdditionalTabs($action);
  1301. if (is_array($additional) && count($additional) > 0) {
  1302. $list = Adapto_array_merge($list, $additional);
  1303. $this->m_filledTabs = Adapto_array_merge($this->m_filledTabs, $additional);
  1304. }
  1305. // Keep track of the tabs that containg attribs
  1306. // so we only display none-empty tabs
  1307. $tabCode = $this->m_attributeTabs[$attribname][0];
  1308. if (!in_array($tabCode, $this->m_filledTabs)) {
  1309. $this->m_filledTabs[] = $tabCode;
  1310. }
  1311. } else {
  1312. Adapto_Util_Debugger::debug("atkentity::getTabs() Warning: $attribname is not an object!?");
  1313. }
  1314. }
  1315. // Check if the currently known tabs all containg attributes
  1316. // so we don't end up with empty tabs
  1317. return $this->checkEmptyTabs($list);
  1318. }
  1319. /**
  1320. * Retrieve the sections for the active tab.
  1321. *
  1322. * @param String $action
  1323. * @return array The active sections.
  1324. */
  1325. function getSections($action)
  1326. {
  1327. $sections = array();
  1328. if (is_array($this->m_sectionList[$action])) {
  1329. foreach ($this->m_sectionList[$action] as $element) {
  1330. list($tab, $sec) = (strpos($element, ".") !== false) ? explode(".", $element) : array($element, null);
  1331. //if this section is on an active tab, we return it.
  1332. if ($tab == $this->getActiveTab() && $sec !== NULL)
  1333. $sections[] = $sec;
  1334. }
  1335. }
  1336. //we do not want duplicate sections on the same tab.
  1337. return array_unique($sections);
  1338. }
  1339. /**
  1340. * Add sections that must be expanded by default.
  1341. *
  1342. */
  1343. function addDefaultExpandedSections()
  1344. {
  1345. $sections = func_get_args();
  1346. $sections = $this->resolveSections($sections);
  1347. $this->m_default_expanded_sections = array_unique(array_merge($sections, $this->m_default_expanded_sections));
  1348. }
  1349. /**
  1350. * Remove sections that must be expanded by default.
  1351. *
  1352. */
  1353. function removeDefaultExpandedSections()
  1354. {
  1355. $sections = func_get_args();
  1356. $this->m_default_expanded_sections = array_diff($this->m_default_expanded_sections, $sections);
  1357. }
  1358. /**
  1359. * Check if the user has the rights to access existing tabs and
  1360. * removes tabs from the list that may not be accessed
  1361. *
  1362. * @param array $tablist Array containing the current tablist
  1363. * @return array with disable tabs
  1364. */
  1365. function checkTabRights(&$tablist)
  1366. {
  1367. global $g_entitys;
  1368. $disable = array();
  1369. if (empty($this->m_module))
  1370. return $disable;
  1371. for ($i = 0, $_i = count($tablist); $i < $_i; $i++) {
  1372. if ($tablist[$i] == "" || $tablist[$i] == "default")
  1373. continue;
  1374. $secMgr = &atkGetSecurityManager();
  1375. // load the $g_entitys array to find out what tabs are required
  1376. if (!isset($g_entitys[$this->m_module][$this->m_type])) {
  1377. include_once(Adapto_Config::getGlobal("atkroot") . "atk/atkentitytools.inc");
  1378. $module = &getModule($this->m_module);
  1379. $module->getEntitys();
  1380. }
  1381. $priv = "tab_" . $tablist[$i];
  1382. if (isset($g_entitys[$this->m_module][$this->m_type]) && Adapto_in_array($priv, $g_entitys[$this->m_module][$this->m_type])) {
  1383. // authorisation is required
  1384. if (!$secMgr->allowed($this->m_module . "." . $this->m_type, "tab_" . $tablist[$i])) {
  1385. Adapto_Util_Debugger::debug("Removing TAB " . $tablist[$i] . " because access to this tab was denied");
  1386. $disable[] = $tablist[$i];
  1387. unset($tablist[$i]);
  1388. }
  1389. }
  1390. }
  1391. if (is_array($tablist)) {
  1392. // we might have now something like:
  1393. // [0]=>tabA,[3]=>tabD
  1394. // we convert this to a 'normal' array:
  1395. // [0]=>tabA,[1]=>tabD;
  1396. $newarray = array();
  1397. foreach ($tablist as $tab)
  1398. $newarray[] = $tab;
  1399. $tablist = $newarray;
  1400. }
  1401. return $disable;
  1402. }
  1403. /**
  1404. * Remove tabs without attribs from the tablist
  1405. * @param array $list The list of tabnames
  1406. * @return array The list of tabnames without the empty tabs.
  1407. *
  1408. */
  1409. function checkEmptyTabs($list)
  1410. {
  1411. $tabList = array();
  1412. if (is_array($list)) {
  1413. foreach ($list AS $tabEntry) {
  1414. if (in_array($tabEntry, $this->m_filledTabs)) {
  1415. $tabList[] = $tabEntry;
  1416. } else {
  1417. Adapto_Util_Debugger::debug("Removing TAB " . $tabEntry . " because it had no attributes assigned");
  1418. }
  1419. }
  1420. }
  1421. return $tabList;
  1422. }
  1423. /**
  1424. * Returns the currently active tab.
  1425. *
  1426. * Note that in themes which use dhtml tabs (tabs without reloads), this
  1427. * method will always return the name of the first tab.
  1428. * @return String The name of the currently visible tab.
  1429. */
  1430. function getActiveTab()
  1431. {
  1432. global $Adapto_VARS;
  1433. $tablist = $this->getTabs($Adapto_VARS["atkaction"]);
  1434. // Note: we may not read atktab from $this->m_postvars, because $this->m_postvars is not filled if this is
  1435. // a nested entity (in a relation for example).
  1436. if (!empty($Adapto_VARS["atktab"]) && in_array($Adapto_VARS["atktab"], $tablist))
  1437. $tab = $Adapto_VARS["atktab"];
  1438. elseif (!empty($this->m_default_tab) && in_array($this->m_default_tab, $tablist))
  1439. $tab = $this->m_default_tab;
  1440. else
  1441. $tab = $tablist[0];
  1442. return $tab;
  1443. }
  1444. /**
  1445. * Get the active sections.
  1446. *
  1447. * @param string $tab The currently active tab
  1448. * @param string $mode The current mode ("edit", "add", etc.)
  1449. */
  1450. function getActiveSections($tab, $mode)
  1451. {
  1452. $activeSections = array();
  1453. if (is_array($this->m_sectionList[$mode])) {
  1454. foreach ($this->m_sectionList[$mode] as $section) {
  1455. if (substr($section, 0, strlen($tab)) == $tab) {
  1456. $sectionName = 'section_' . str_replace('.', '_', $section);
  1457. $key = array("entitytype" => $this->atkentitytype(), "section" => $sectionName);
  1458. $defaultOpen = in_array($section, $this->m_default_expanded_sections);
  1459. if (atkState::get($key, $defaultOpen ? 'opened' : 'closed') != 'closed') {
  1460. $activeSections[] = $section;
  1461. }
  1462. }
  1463. }
  1464. }
  1465. return $activeSections;
  1466. }
  1467. /**
  1468. * Add a recordset filter.
  1469. * @param String $filter The fieldname you want to filter OR a SQL where
  1470. * clause expression.
  1471. * @param String $value Required value. (Ommit this parameter if you pass
  1472. * an SQL expression for $filter.)
  1473. */
  1474. function addFilter($filter, $value = "")
  1475. {
  1476. if ($value == "") {

Large files files are truncated, but you can click here to view the full file