PageRenderTime 74ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/class.atknode.inc

https://github.com/ibuildingsnl/ATK
PHP | 5170 lines | 2788 code | 502 blank | 1880 comment | 426 complexity | a93e335754f5b4346fe3b5a867ab3dd6 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-3.0

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

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