PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Adapto/Attribute.php

http://github.com/egeniq/adapto
PHP | 1980 lines | 659 code | 214 blank | 1107 comment | 158 complexity | 3417581a86029525812ff761dc1bb95e 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. * @subpackage attributes
  10. *
  11. * @copyright (c)2000-2006 Ivo Jansch
  12. * @copyright (c)2000-2006 Ibuildings.nl BV
  13. * @license http://www.achievo.org/atk/licensing ATK Open Source License
  14. *
  15. */
  16. /**
  17. * Attributeflags. The following flags can be used for attributes
  18. * @internal WARNING: flags may *not* exceed 2^31 (2147483648), because
  19. * that's the integer limit beyond which the bitwise operators won't
  20. * work anymore!
  21. */
  22. /**
  23. * Value must be entered
  24. *
  25. * "database-level" processing flag
  26. */
  27. define("AF_OBLIGATORY", 1);
  28. /**
  29. * Value must be unique
  30. *
  31. * "database-level" processing flag
  32. */
  33. define("AF_UNIQUE", 2);
  34. /**
  35. * Part of the primary-key entity, also makes it obligatory
  36. *
  37. * "database-level" processing flag
  38. */
  39. define("AF_PRIMARY", 4 | AF_OBLIGATORY);
  40. /**
  41. * Auto-increment field
  42. *
  43. * "database-level" processing flag
  44. */
  45. define("AF_AUTO_INCREMENT", 8);
  46. /**
  47. * Alias for AF_AUTO_INCREMENT (auto-increment flag is often mistyped)
  48. *
  49. * "database-level" processing flag
  50. */
  51. define("AF_AUTOINCREMENT", AF_AUTO_INCREMENT);
  52. /**
  53. * Don't show in record lists
  54. *
  55. * hide flag
  56. */
  57. define("AF_HIDE_LIST", 16);
  58. /**
  59. * Don't show on add pages
  60. *
  61. * hide flag
  62. */
  63. define("AF_HIDE_ADD", 32);
  64. /**
  65. * Don't show on edit pages
  66. *
  67. * hide flag
  68. */
  69. define("AF_HIDE_EDIT", 64);
  70. /**
  71. * Don't show on select pages
  72. *
  73. * hide flag
  74. */
  75. define("AF_HIDE_SELECT", 128);
  76. /**
  77. * Don't show on view pages
  78. *
  79. * hide flag
  80. */
  81. define("AF_HIDE_VIEW", 256);
  82. /**
  83. * Not searchable in extended search
  84. *
  85. * hide flag
  86. */
  87. define("AF_HIDE_SEARCH", 512); // not searchable in extended search
  88. /**
  89. * Load always, even if not displayed anywhere
  90. *
  91. * hide flag
  92. */
  93. define("AF_FORCE_LOAD", 1024); // load always, even if not displayed anywhere
  94. /**
  95. * Attribute is totally hidden
  96. *
  97. * hide flag
  98. */
  99. define("AF_HIDE",
  100. AF_HIDE_EDIT | AF_HIDE_ADD | // attribute is totally hidden
  101. AF_HIDE_LIST | AF_HIDE_SEARCH | AF_HIDE_VIEW | AF_HIDE_SELECT);
  102. /**
  103. * Readonly in add
  104. *
  105. * readonly flag
  106. */
  107. define("AF_READONLY_ADD", 2048); // readonly in add
  108. /**
  109. * Readonly when edited
  110. *
  111. * readonly flag
  112. */
  113. define("AF_READONLY_EDIT", 4096); // readonly when edited
  114. /**
  115. * Always readonly
  116. *
  117. * readonly flag
  118. */
  119. define("AF_READONLY", AF_READONLY_EDIT | AF_READONLY_ADD); // always readonly
  120. /**
  121. * No label in forms
  122. *
  123. * display-related processing flag
  124. */
  125. define("AF_NO_LABEL", 8192); // no label in forms
  126. /**
  127. * Alias for AF_NO_LABEL (mistyped)
  128. *
  129. * display-related processing flag
  130. */
  131. define("AF_NOLABEL", AF_NO_LABEL); // no label (mistyped)
  132. /**
  133. * Blank label in forms
  134. *
  135. * display-related processing flag
  136. */
  137. define("AF_BLANK_LABEL", 16384); // blank label in forms
  138. /**
  139. * Alias for AF_BLANK_LABEL (mistyped)
  140. *
  141. * display-related processing flag
  142. */
  143. define("AF_BLANKLABEL", AF_BLANK_LABEL); // blank label (mistyped)
  144. /**
  145. * Cannot be sorted in recordlists
  146. *
  147. * display-related processing flag
  148. */
  149. define("AF_NO_SORT", 32768); // cannot be sorted in recordlists.
  150. /**
  151. * Alias for AF_NO_SORT (mistyped)
  152. *
  153. * display-related processing flag
  154. */
  155. define("AF_NOSORT", AF_NO_SORT); // no-sort flag is often mistyped
  156. /**
  157. * Attribute is searchable in list views
  158. *
  159. * display-related processing flag
  160. */
  161. define("AF_SEARCHABLE", 65536); // Attribute is searchable in list views
  162. /**
  163. * The attribute will have a 'total' column in lists
  164. *
  165. * display-related processing flag
  166. */
  167. define("AF_TOTAL", 131072); // The attribute will have a 'total' column in lists.
  168. /**
  169. * If supported, use pop-up window
  170. *
  171. * display-related processing flag
  172. */
  173. define("AF_POPUP", 262144); // if supported, use pop-up window
  174. /**
  175. * Delete function is called when owning entity is deleted
  176. *
  177. * miscellaneous processing flag
  178. */
  179. define("AF_CASCADE_DELETE", 524288); // delete function is called when owning entity is deleted
  180. /**
  181. * Will have a large amount of recors (relation)
  182. *
  183. * Instead of showing a listbox with all the records it will show an add link to a select page
  184. *
  185. * miscellaneous processing flag
  186. */
  187. define("AF_LARGE", 1048576); // will have a large ammount of records (relation)
  188. /**
  189. * Ignore filters when selecting records (relation)
  190. *
  191. * miscellaneous processing flag
  192. */
  193. define("AF_NO_FILTER", 2097152); // ignore filters when selecting records (relation)
  194. /**
  195. * Parent field for parent child relations (treeview)
  196. *
  197. * miscellaneous processing flag
  198. */
  199. define("AF_PARENT", 4194304); // parent field for parent child relations (treeview)
  200. /**
  201. * No quotes are used when adding to the database
  202. *
  203. * miscellaneous processing flag
  204. */
  205. define("AF_NO_QUOTES", 8388608); // no quotes are used when adding to database
  206. /**
  207. * Multi-language field
  208. *
  209. * miscellaneous processing flag
  210. */
  211. define("AF_ML", 16777216); // multi-language field
  212. /**
  213. * Alias for AF_ML (spelled out)
  214. *
  215. * miscellaneous processing flag
  216. */
  217. define("AF_MULTILANGUAGE", AF_ML);
  218. /**
  219. * Shortcut for hidden auto-incremented primary key
  220. *
  221. * miscellaneous processing flag
  222. */
  223. define("AF_AUTOKEY", AF_PRIMARY | AF_HIDE | // shortcut for hidden auto-incremented primary-key
  224. AF_AUTOINCREMENT);
  225. /*
  226. * flag (values) that can be used for attribute specific flags
  227. * NOTE: Attribute specific flags aren't good behaviour, but for
  228. * compatibility reasons we support them anyway. Newly derived attributes
  229. * should not use these specific flags, but work with extra parameters.
  230. */
  231. /**
  232. * Specific attribute flag 1
  233. */
  234. define("AF_SPECIFIC_1", 33554432); // specific attribute flag 1
  235. /**
  236. * Specific attribute flag 2
  237. */
  238. define("AF_SPECIFIC_2", 67108864); // specific attribute flag 2
  239. /**
  240. * Specific attribute flag 3
  241. */
  242. define("AF_SPECIFIC_3", 134217728); // specific attribute flag 3
  243. /**
  244. * Specific attribute flag 4
  245. */
  246. define("AF_SPECIFIC_4", 268435456); // specific attribute flag 4
  247. /**
  248. * Specific attribute flag 5
  249. */
  250. define("AF_SPECIFIC_5", 536870912); // specific attribute flag 5
  251. /**
  252. * Do not store this attribute
  253. *
  254. * Storage type flag, used by the storageType() and related methods
  255. */
  256. define("NOSTORE", 0);
  257. /**
  258. * Do not load this attribute
  259. *
  260. * Storage type flag, used by the storageType() and related methods
  261. */
  262. define("NOLOAD", 0);
  263. /**
  264. * Store before all other ('normal') attributes (?)
  265. *
  266. * Storage type flag, used by the storageType() and related methods
  267. */
  268. define("PRESTORE", 1);
  269. /**
  270. * Call load before selectDb()
  271. *
  272. * Storage type flag, used by the storageType() and related methods
  273. */
  274. define("PRELOAD", 1);
  275. /**
  276. * Store after all other ('normal') attributes (?)
  277. *
  278. * Storage type flag, used by the storageType() and related methods
  279. */
  280. define("POSTSTORE", 2);
  281. /**
  282. * Call load after selectDb()
  283. *
  284. * Storage type flag, used by the storageType() and related methods
  285. */
  286. define("POSTLOAD", 2);
  287. /**
  288. * Do addToQuery() of this attribute
  289. *
  290. * Storage type flag, used by the storageType() and related methods
  291. */
  292. define("ADDTOQUERY", 4);
  293. /**
  294. * Attribute is disable in view mode
  295. */
  296. define("DISABLED_VIEW", 1);
  297. /**
  298. * Attribute is disable in edit mode
  299. */
  300. define("DISABLED_EDIT", 2);
  301. /**
  302. * Attribute is disabled in view and edit mode
  303. */
  304. define("DISABLED_ALL", DISABLED_VIEW | DISABLED_EDIT);
  305. /**
  306. * The Adapto_Attribute class represents an attribute of an atkEntity.
  307. * An Adapto_Attribute has a name and a set of parameters that
  308. * control its behaviour, like whether an Adapto_Attribute
  309. * is obligatory, etc.
  310. *
  311. * @author ijansch
  312. * @package adapto
  313. * @subpackage attributes
  314. */
  315. class Adapto_Attribute
  316. {
  317. /**
  318. * The name of the attribute
  319. * @access private
  320. * @var String
  321. */
  322. public $m_name; // defaulted to public
  323. /**
  324. * The attribute flags (see above)
  325. * @access private
  326. * @var int
  327. */
  328. public $m_flags = 0; // defaulted to public
  329. /**
  330. * The name of the atkEntity that owns this attribute (set by atkentity)
  331. * @access private
  332. * @var String
  333. */
  334. public $m_owner = ""; // defaulted to public
  335. /**
  336. * The module of the attribute (if empty, the module from the owner entity
  337. * should be assumed).
  338. * @access private
  339. * @var String
  340. *
  341. */
  342. public $m_module = ""; // defaulted to public
  343. /**
  344. * Instance of the atkEntity that owns this attribute
  345. * @access private
  346. * @var atkEntity
  347. */
  348. public $m_ownerInstance = ""; // defaulted to public
  349. /**
  350. * The size the attribute's field.
  351. * @access private
  352. * @var int
  353. */
  354. public $m_size = 0; // defaulted to public
  355. /**
  356. * The size the attribute's search input field.
  357. * @access private
  358. * @var int
  359. */
  360. public $m_searchsize = 0; // defaulted to public
  361. /**
  362. * The maximum size the attribute's value may have in the database.
  363. * @access private
  364. * @var int
  365. */
  366. public $m_maxsize = 0; // defaulted to public
  367. /**
  368. * The database fieldtype.
  369. * @access private
  370. * @var String
  371. */
  372. public $m_dbfieldtype = ""; // defaulted to public
  373. /**
  374. * The order of the attribute within its entity.
  375. * @access private
  376. * @var int
  377. */
  378. public $m_order = 0; // defaulted to public
  379. /**
  380. * Index of the attribute within its entity.
  381. * @access private
  382. * @var int
  383. */
  384. public $m_index = 0; // defaulted to public
  385. /**
  386. * The tab(s) on which the attribute lives.
  387. * @access private
  388. * @var mixed
  389. */
  390. public $m_tabs = "*"; // defaulted to public
  391. /**
  392. * The section(s) on which the attribute lives.
  393. * @access private
  394. * @var mixed
  395. */
  396. public $m_sections = "*"; // defaulted to public
  397. /**
  398. * The id of the attribute in the HTML
  399. * @access private
  400. * @var String
  401. */
  402. public $m_htmlid; // defaulted to public
  403. /**
  404. * The css classes of the attribute
  405. * @access private
  406. * @var sttsy
  407. */
  408. public $m_cssclasses = array(); // defaulted to public
  409. /**
  410. * The label of the attribute.
  411. * @access private
  412. * @var String
  413. */
  414. public $m_label = ""; // defaulted to public
  415. /**
  416. * The postfix label of the attribute.
  417. * @access private
  418. * @var String
  419. */
  420. public $m_postfixlabel = ""; // defaulted to public
  421. /**
  422. * The searchmode for this attribute
  423. *
  424. * This var exists so that you can assign searchmodes to specific
  425. * attributes instead of having a general searchmode for the entire
  426. * search. This can be any one of the supported modes, as returned by
  427. * the attribute's getSearchModes() method.
  428. * @access private
  429. * @var String
  430. */
  431. public $m_searchmode = ""; // defaulted to public
  432. /**
  433. * Wether to force an insert of the attribute
  434. * @access private
  435. * @var bool
  436. */
  437. public $m_forceinsert = false; // defaulted to public
  438. /**
  439. * Wether to force a reload of the attribute ignoring the saved session data
  440. *
  441. * @access private
  442. * @var bool
  443. */
  444. public $m_forcereload = false; // defaulted to public
  445. /**
  446. * Wether to force an update of the attribute
  447. * @access private
  448. * @var bool
  449. */
  450. public $m_forceupdate = false; // defaulted to public
  451. /**
  452. * Array for containing onchange javascript code
  453. * @access private
  454. * @var Array
  455. */
  456. public $m_onchangecode = array(); // defaulted to public
  457. /**
  458. * Variable to store initialisation javascript code
  459. * in for the changehandler.
  460. * @access private
  461. * @var String
  462. */
  463. public $m_onchangehandler_init = ""; // defaulted to public
  464. /**
  465. * Variable to store dependency callbacks.
  466. *
  467. * @var array
  468. */
  469. private $m_dependencies = array();
  470. /**
  471. * Attribute to store disabled modes.
  472. * @access private
  473. * @var int
  474. */
  475. public $m_disabledModes = 0; // defaulted to public
  476. /**
  477. * Whether to hide initially or not
  478. * @access private
  479. * @var bool
  480. */
  481. public $m_initial_hidden = false; // defaulted to public
  482. /**
  483. * Storage type.
  484. * @access private
  485. * @var int
  486. * @see setStorageType
  487. */
  488. public $m_storageType = array(); // defaulted to public
  489. /**
  490. * Load type.
  491. * @access private
  492. * @var int
  493. * @see setLoadType
  494. */
  495. public $m_loadType = array(); // defaulted to public
  496. /**
  497. * Initial value.
  498. * @access private
  499. * @var mixed
  500. * @see setInitialValue
  501. */
  502. public $m_initialValue = NULL; // defaulted to public
  503. /**
  504. * Column.
  505. *
  506. * @var string
  507. */
  508. private $m_column;
  509. /**
  510. * JavaScript observers. Key is the event name
  511. * value is an array with event handlers.
  512. *
  513. * @var array
  514. */
  515. private $m_jsObservers = array();
  516. /**
  517. * View callback.
  518. *
  519. * @var mixed
  520. */
  521. private $m_viewCallback = null;
  522. /**
  523. * Edit callback.
  524. *
  525. * @var mixed
  526. */
  527. private $m_editCallback = null;
  528. /**
  529. * Constructor
  530. *
  531. * <b>Example:</b>
  532. * $this->add(new Adapto_Attribute("name",AF_OBLIGATORY, 30));
  533. *
  534. * Note: If you want to use the db/ddl utility class to
  535. * automatically generate the table, the $size parameter must be
  536. * set, for it will use the size specified here to determine the
  537. * field length. (Derived classes might have reasonable default
  538. * values, but the standard Adapto_Attribute doesn't.)
  539. *
  540. * @param String $name Name of the attribute (unique within an entity, and
  541. * for most attributes, corresponds to a field in
  542. * the database.
  543. * @param int $flags Flags for the attribute.
  544. * @param mixed $size The size(s) of the attribute. See the $size
  545. * parameter of the setAttribSize() method for more
  546. * information on the possible values of this
  547. * parameter.
  548. *
  549. */
  550. public function __construct($name, $flags = 0, $size = 0)
  551. {
  552. $this->m_name = $name;
  553. $this->setFlags((int) $flags);
  554. $this->setAttribSize($size);
  555. // default class
  556. $this->addCSSClass(get_class($this));
  557. }
  558. /**
  559. * Returns the owner instance.
  560. *
  561. * @return atkEntity owner instance
  562. */
  563. function &getOwnerInstance()
  564. {
  565. return $this->m_ownerInstance;
  566. }
  567. /**
  568. * Sets the owner instance.
  569. *
  570. * @param atkEntity $instance
  571. */
  572. function setOwnerInstance(&$instance)
  573. {
  574. $this->m_ownerInstance = &$instance;
  575. }
  576. /**
  577. * Check if the attribute has a certain flag.
  578. * @param int $flag The flag you want to check
  579. * @return boolean
  580. */
  581. function hasFlag($flag)
  582. {
  583. return (($this->m_flags & $flag) == $flag);
  584. }
  585. /**
  586. * Returns the full set of flags of the attribute.
  587. * @return int $m_flags The full set of flags
  588. */
  589. function getFlags()
  590. {
  591. return $this->m_flags;
  592. }
  593. /**
  594. * Adds a flag to the attribute.
  595. * Note that adding flags at any time after the constructor might not
  596. * always work. There are flags that are processed only at
  597. * constructor time.
  598. * @param int $flag The flag to add to the attribute
  599. * @return Adapto_Attribute The instance of this Adapto_Attribute
  600. */
  601. function addFlag($flag)
  602. {
  603. $this->m_flags |= $flag;
  604. if (!$this->hasFlag(AF_PRIMARY) && is_object($this->m_ownerInstance)) {
  605. if (hasFlag($flag, AF_HIDE_LIST) && !in_array($this->fieldName(), $this->m_ownerInstance->m_listExcludes)) {
  606. $this->m_ownerInstance->m_listExcludes[] = $this->fieldName();
  607. }
  608. if (hasFlag($flag, AF_HIDE_VIEW) && !in_array($this->fieldName(), $this->m_ownerInstance->m_viewExcludes)) {
  609. $this->m_ownerInstance->m_viewExcludes[] = $this->fieldName();
  610. }
  611. }
  612. return $this;
  613. }
  614. /**
  615. * Sets the flags of the attribute
  616. *
  617. * Note that if you assign nothing or 0, this will remove all the flags
  618. * from the attribute. You can assign multiple flags by using the pipe
  619. * symbol. Setting the flags will overwrite all previous flag-settings.
  620. * @param int $flags The flags to be set to the attribute.
  621. * @return Adapto_Attribute The instance of this Adapto_Attribute
  622. */
  623. function setFlags($flags = 0)
  624. {
  625. $this->m_flags = 0;
  626. $this->addFlag($flags); // always call addFlag
  627. return $this;
  628. }
  629. /**
  630. * Removes a flag from the attribute.
  631. *
  632. * Note that removing flags at any time after the constructor might not
  633. * always work. There are flags that have already been processed at
  634. * constructor time, so removing them will be futile.
  635. * @param int $flag The flag to remove from the attribute
  636. * @return Adapto_Attribute The instance of this Adapto_Attribute
  637. */
  638. function removeFlag($flag)
  639. {
  640. if ($this->hasFlag($flag)) {
  641. $this->m_flags ^= $flag;
  642. }
  643. if (!$this->hasFlag(AF_PRIMARY) && is_object($this->m_ownerInstance)) {
  644. if (hasFlag($flag, AF_HIDE_LIST) && in_array($this->fieldName(), $this->m_ownerInstance->m_listExcludes)) {
  645. $key = array_search($this->fieldName(), $this->m_ownerInstance->m_listExcludes);
  646. unset($this->m_ownerInstance->m_listExcludes[$key]);
  647. }
  648. if (hasFlag($flag, AF_HIDE_VIEW) && in_array($this->fieldName(), $this->m_ownerInstance->m_viewExcludes)) {
  649. $key = array_search($this->fieldName(), $this->m_ownerInstance->m_viewExcludes);
  650. unset($this->m_ownerInstance->m_viewExcludes[$key]);
  651. }
  652. }
  653. return $this;
  654. }
  655. /**
  656. * Adds a disabled mode flag to the attribute (use DISABLED_VIEW and DISABLED_EDIT flags).
  657. * @param int $flag The flag to add to the attribute
  658. * @return Adapto_Attribute The instance of this Adapto_Attribute
  659. */
  660. function addDisabledMode($flag)
  661. {
  662. $this->m_disabledModes |= $flag;
  663. return $this;
  664. }
  665. /**
  666. * Check if the attribute is disabled in some mode (use DISABLED_VIEW and DISABLED_EDIT flags).
  667. * @param int $flag The flag you want to check
  668. * @return boolean
  669. */
  670. function hasDisabledMode($flag)
  671. {
  672. return (($this->m_disabledModes & $flag) == $flag);
  673. }
  674. /**
  675. * Sets the disabled mode flag of the attribute
  676. *
  677. * Note that if you assign nothing or 0, this will remove all the flags
  678. * from the attribute. You can assign multiple flags by using the pipe
  679. * symbol. Setting the flags will overwrite all previous flag-settings.
  680. * @param int $flags The flags to be set to the attribute.
  681. * @return Adapto_Attribute The instance of this Adapto_Attribute
  682. */
  683. function setDisabledModes($flags = 0)
  684. {
  685. $this->m_disabledModes = $flags;
  686. return $this;
  687. }
  688. /**
  689. * Removes a disabled mode from the attribute.
  690. *
  691. * @param int $flag The flag to remove from the attribute
  692. * @return Adapto_Attribute The instance of this Adapto_Attribute
  693. */
  694. function removeDisabledMode($flag)
  695. {
  696. if ($this->hasDisabledMode($flag)) {
  697. $this->m_disabledModes ^= $flag;
  698. }
  699. return $this;
  700. }
  701. /**
  702. * Returns the name of the attribute.
  703. *
  704. * For most attributes, this corresponds to the name of the field in the
  705. * database. For some attributes though (like one2many relations), the
  706. * name is a mere identifier within an entity. This method always returns
  707. * the attribute name, despite the 'field' prefix of the method.
  708. *
  709. * @return String fieldname
  710. */
  711. function fieldName()
  712. {
  713. return $this->m_name;
  714. }
  715. /**
  716. * Check if a record has an empty value for this attribute.
  717. * @param array $record The record that holds this attribute's value.
  718. * @return boolean
  719. */
  720. function isEmpty($record)
  721. {
  722. return (!isset($record[$this->fieldName()]) || $record[$this->fieldName()] === "");
  723. }
  724. /**
  725. * Converts the internal attribute value to one that is understood by the
  726. * database.
  727. *
  728. * For the regular Adapto_Attribute, this means escaping things like
  729. * quotes and slashes. Derived attributes may reimplement this for their
  730. * own conversion.
  731. * This is the exact opposite of the db2value method.
  732. *
  733. * @param array $rec The record that holds this attribute's value.
  734. * @return String The database compatible value
  735. */
  736. function value2db($rec)
  737. {
  738. if (is_array($rec) && isset($rec[$this->fieldName()])) {
  739. return $this->escapeSQL($rec[$this->fieldName()]);
  740. }
  741. return NULL;
  742. }
  743. /**
  744. * Converts a database value to an internal value.
  745. *
  746. * For the regular Adapto_Attribute
  747. * Derived attributes may reimplement this for their own conversion.
  748. * (In which case, the return type might be 'mixed')
  749. *
  750. * This is the exact opposite of the value2db method.
  751. *
  752. * @param array $rec The database record that holds this attribute's value
  753. * @return mixed The internal value
  754. */
  755. function db2value($rec)
  756. {
  757. if (isset($rec[$this->fieldName()])) {
  758. return $rec[$this->fieldName()] === NULL ? NULL : $rec[$this->fieldName()];
  759. }
  760. return NULL;
  761. }
  762. /**
  763. * Is there a value posted for this attribute?
  764. *
  765. * @param array $postvars
  766. * @return boolean posted?
  767. */
  768. function isPosted($postvars)
  769. {
  770. return is_array($postvars) && isset($postvars[$this->fieldName()]);
  771. }
  772. /**
  773. * Set initial value for this attribute.
  774. *
  775. * NOTE: the initial value only works if there is no initial_values override
  776. * in the entity or if the override properly calls parent::initial_values!
  777. *
  778. * @param mixed $value initial value
  779. * @return Adapto_Attribute The instance of this Adapto_Attribute
  780. */
  781. function setInitialValue($value)
  782. {
  783. $this->m_initialValue = $value;
  784. return $this;
  785. }
  786. /**
  787. * Initial value. Returns the initial value for this attribute
  788. * which will be used in the add form etc.
  789. *
  790. * @return mixed initial value for this attribute
  791. */
  792. function initialValue()
  793. {
  794. return $this->m_initialValue;
  795. }
  796. /**
  797. * Convert values from an HTML form posting to an internal value for
  798. * this attribute.
  799. *
  800. * For the regular Adapto_Attribute, this means getting the field with the
  801. * same name as the attribute from the html posting.
  802. *
  803. * @param array $postvars The array with html posted values ($_POST, for
  804. * example) that holds this attribute's value.
  805. * @return String The internal value
  806. */
  807. function fetchValue($postvars)
  808. {
  809. if ($this->isPosted($postvars)) {
  810. return $postvars[$this->fieldName()];
  811. }
  812. }
  813. /**
  814. * Register JavaScript event handlers.
  815. *
  816. * @param string $fieldId field identifier
  817. */
  818. protected function registerJavaScriptObservers($fieldId)
  819. {
  820. foreach ($this->m_jsObservers as $event => $handlers) {
  821. foreach ($handlers as $handler) {
  822. $code = '$(\'' . $fieldId . '\').observe(\'' . $event . '\', function(event) { var fieldId = \'' . $fieldId . '\'; ' . $handler . ' });';
  823. $this->getOwnerInstance()->getPage()->register_loadscript($code);
  824. }
  825. }
  826. }
  827. /**
  828. * Returns a piece of html code that can be used in a form to edit this
  829. * attribute's value.
  830. *
  831. * @param array $record The record that holds the value for this attribute.
  832. * @param String $fieldprefix The fieldprefix to put in front of the name
  833. * of any html form element for this attribute.
  834. * @param String $mode The mode we're in ('add' or 'edit')
  835. * @return String A piece of htmlcode for editing this attribute
  836. */
  837. function edit($record = "", $fieldprefix = "", $mode = "")
  838. {
  839. $id = $this->getHtmlId($fieldprefix);
  840. $this->registerKeyListener($id, KB_CTRLCURSOR | KB_UPDOWN);
  841. if (count($this->m_onchangecode)) {
  842. $onchange = 'onChange="' . $id . '_onChange(this);"';
  843. $this->_renderChangeHandler($fieldprefix);
  844. } else {
  845. $onchange = '';
  846. }
  847. $this->registerJavaScriptObservers($id);
  848. $size = $this->m_size;
  849. if ($mode == 'list' && $size > 20)
  850. $size = 20;
  851. $value = (isset($record[$this->fieldName()]) && !is_array($record[$this->fieldName()]) ? htmlspecialchars($record[$this->fieldName()]) : "");
  852. $result = '<input type="text" id="' . $id . '" name="' . $id . '" ' . $this->getCSSClassAttribute() . ' value="' . $value . '"'
  853. . ($size > 0 ? ' size="' . $size . '"' : '') . ($this->m_maxsize > 0 ? ' maxlength="' . $this->m_maxsize . '"' : '') . ' ' . $onchange . ' />';
  854. return $result;
  855. }
  856. /**
  857. * Add a javascript onchange event handler.
  858. * @param string $jscode A block of valid javascript code.
  859. * @return Adapto_Attribute Returns the instance of this attribute.
  860. */
  861. function addOnChangeHandler($jscode)
  862. {
  863. if (!in_array($jscode, $this->m_onchangecode))
  864. $this->m_onchangecode[] = $jscode;
  865. return $this;
  866. }
  867. /**
  868. * Renders the onchange code on the page.
  869. *
  870. * @access private
  871. * @param String $fieldprefix The prefix to the field
  872. * @param String $elementNr The number of the element when attribute contains multiple options
  873. */
  874. function _renderChangeHandler($fieldprefix, $elementNr = "")
  875. {
  876. if (count($this->m_onchangecode)) {
  877. $page = &$this->m_ownerInstance->getPage();
  878. $page
  879. ->register_scriptcode(
  880. "
  881. function " . $this->getHtmlId($fieldprefix) . $elementNr . "_onChange(el)
  882. {
  883. {$this->m_onchangehandler_init}
  884. " . implode("\n ", $this->m_onchangecode) . "
  885. }\n");
  886. }
  887. }
  888. /**
  889. * Returns a piece of html code for hiding this attribute in an HTML form,
  890. * while still posting its value. (<input type="hidden">)
  891. *
  892. * @param array $record The record that holds the value for this attribute
  893. * @param String $fieldprefix The fieldprefix to put in front of the name
  894. * of any html form element for this attribute.
  895. * @return String A piece of htmlcode with hidden form elements that post
  896. * this attribute's value without showing it.
  897. */
  898. function hide($record = "", $fieldprefix = "")
  899. {
  900. // the next if-statement is a workaround for derived attributes which do
  901. // not override the hide() method properly. This will not give them a
  902. // working hide() functionality but at least it will not give error messages.
  903. if (!is_array($record[$this->fieldName()])) {
  904. $id = $id = $this->getHtmlId($fieldprefix);
  905. $result = '<input type="hidden" id="' . $id . '" name="' . $fieldprefix . $this->formName() . '" value="'
  906. . htmlspecialchars($record[$this->fieldName()]) . '">';
  907. return $result;
  908. } else
  909. Adapto_Util_Debugger::debug("Warning attribute " . $this->m_name . " has no proper hide method!");
  910. }
  911. /**
  912. * Return the html identifier (id="") of the attribute. (unique within a
  913. * page)
  914. * @param String $fieldprefix The fieldprefix to put in front of the name
  915. * of any html form element for this attribute.
  916. * @return String the HTML identifier.
  917. */
  918. function getHtmlId($fieldprefix)
  919. {
  920. $this->m_htmlid = $fieldprefix . $this->fieldName();
  921. return $this->m_htmlid;
  922. }
  923. /**
  924. * Returns the html identifier of the attribute without setting it
  925. * Created because getHtmlId would always SET the htmlid while getting it.
  926. * @return String The HTML id of this attribute
  927. */
  928. function getAttributeHtmlId()
  929. {
  930. if ($this->m_htmlid)
  931. return $this->m_htmlid;
  932. else
  933. return $this->fieldName();
  934. }
  935. /**
  936. * Adds the attribute's view / hide HTML code to the view array.
  937. *
  938. * This method is called by the entity if it wants the data needed to create
  939. * a view form.
  940. *
  941. * This is a framework method, it should never be called directly.
  942. *
  943. * @param String $mode the mode ("view")
  944. * @param array $arr pointer to the view array
  945. * @param array $defaults pointer to the default values array
  946. */
  947. function addToViewArray($mode, &$arr, &$defaults)
  948. {
  949. if (!$this->hasFlag(AF_HIDE_VIEW)) {
  950. $entry = array("name" => $this->m_name, "attribute" => &$this);
  951. /* label? */
  952. $entry["label"] = $this->getLabel($defaults, $mode);
  953. // on which tab?
  954. $entry["tabs"] = $this->getTabs($mode);
  955. //on which sections?
  956. $entry["sections"] = $this->getSections();
  957. /* the actual edit contents */
  958. $entry["html"] = $this->getView($mode, $defaults);
  959. $arr["fields"][] = $entry;
  960. }
  961. }
  962. /**
  963. * Prepare for edit. Is called before all attributes are added to the
  964. * edit array and allows for last minute manipulations based on the
  965. * record but also manipulations on the record itself.
  966. *
  967. * @param array $record reference to the record
  968. * @param string $fieldPrefix field prefix
  969. * @param string $mode edit mode
  970. */
  971. public function preAddToEditArray(&$record, $fieldPrefix, $mode)
  972. {
  973. }
  974. /**
  975. * Prepare for view. Is called before all attributes are added to the
  976. * view array and allows for last minute manipulations based on the
  977. * record but also manipulations on the record itself.
  978. *
  979. * @param array $record reference to the record
  980. * @param string $mode view mode
  981. */
  982. public function preAddToViewArray(&$record, $mode)
  983. {
  984. }
  985. /**
  986. * Adds the attribute's edit / hide HTML code to the edit array.
  987. *
  988. * This method is called by the entity if it wants the data needed to create
  989. * an edit form.
  990. *
  991. * This is a framework method, it should never be called directly.
  992. *
  993. * @param String $mode the edit mode ("add" or "edit")
  994. * @param array $arr pointer to the edit array
  995. * @param array $defaults pointer to the default values array
  996. * @param array $error pointer to the error array
  997. * @param String $fieldprefix the fieldprefix
  998. */
  999. function addToEditArray($mode, &$arr, &$defaults, &$error, $fieldprefix)
  1000. {
  1001. /* hide */
  1002. if (($mode == "edit" && $this->hasFlag(AF_HIDE_EDIT)) || ($mode == "add" && $this->hasFlag(AF_HIDE_ADD))) {
  1003. /* when adding, there's nothing to hide, unless we're dealing with atkHiddenAttribute... */
  1004. if ($mode == "edit" || ($mode == "add" && (!$this->isEmpty($defaults) || $this instanceof atkHiddenAttribute))) {
  1005. $arr["hide"][] = $this->hide($defaults, $fieldprefix, $mode);
  1006. }
  1007. }
  1008. /* edit */
  1009. else {
  1010. global $Adapto_VARS;
  1011. $entry = array("name" => $this->m_name, "obligatory" => $this->hasFlag(AF_OBLIGATORY), "attribute" => &$this);
  1012. $entry["id"] = $this->getHtmlId($fieldprefix);
  1013. /* label? */
  1014. $entry["label"] = $this->getLabel($defaults, $mode);
  1015. /* error? */
  1016. $entry["error"] = $this->getError($error)
  1017. || (isset($Adapto_VARS["atkerrorfields"]) && Adapto_in_array($entry['id'], $Adapto_VARS['atkerrorfields']));
  1018. // on which tab?
  1019. $entry["tabs"] = $this->getTabs($mode);
  1020. //on which sections?
  1021. $entry["sections"] = $this->getSections();
  1022. // the actual edit contents
  1023. $entry["html"] = $this->getEdit($mode, $defaults, $fieldprefix);
  1024. // initially hidden
  1025. $entry["initial_hidden"] = $this->isInitialHidden($defaults);
  1026. $arr["fields"][] = $entry;
  1027. }
  1028. }
  1029. /**
  1030. * Put the attribute on one or more tabs.
  1031. * @param array $tabs An array of tabs on which the attribute should
  1032. * be displayed.
  1033. * @return Adapto_Attribute The instance of this Adapto_Attribute
  1034. */
  1035. function setTabs($tabs)
  1036. {
  1037. if (empty($tabs) && isset($this->m_ownerInstance) && is_object($this->m_ownerInstance)) {
  1038. $tabs = array($this->m_ownerInstance->m_default_tab);
  1039. } else if (empty($tabs)) {
  1040. $tabs = array('default');
  1041. }
  1042. $this->m_tabs = $tabs;
  1043. return $this;
  1044. }
  1045. /**
  1046. * retrieve the tabs for this attribute.
  1047. * @param string $mode
  1048. * @return array
  1049. */
  1050. function getTabs($mode = "")
  1051. {
  1052. return $this->m_tabs;
  1053. }
  1054. /**
  1055. * Put the attribute on one or more tabs and/or sections.
  1056. *
  1057. * Example:
  1058. * <code>$attribute->setSections(array('tab.section','tab.othersection));</code>
  1059. *
  1060. * @param array $sections An array of tabs and/or sections on which the attribute should
  1061. * be displayed.
  1062. * @return Adapto_Attribute The instance of this Adapto_Attribute
  1063. */
  1064. function setSections($sections)
  1065. {
  1066. if ($sections == NULL) {
  1067. $this->m_sections = array();
  1068. } else {
  1069. $this->m_sections = $sections;
  1070. }
  1071. return $this;
  1072. }
  1073. /**
  1074. * retrieve the tabs and/or sections for this attribute.
  1075. *
  1076. * @return array
  1077. */
  1078. function getSections()
  1079. {
  1080. return $this->m_sections;
  1081. }
  1082. /**
  1083. * Get column.
  1084. *
  1085. * @return string column name
  1086. */
  1087. public function getColumn()
  1088. {
  1089. return $this->m_column;
  1090. }
  1091. /**
  1092. * Set column.
  1093. *
  1094. * @param string $name column name
  1095. * @return Adapto_Attribute The instance of this Adapto_Attribute
  1096. */
  1097. public function setColumn($name)
  1098. {
  1099. $this->m_column = $name;
  1100. return $this;
  1101. }
  1102. /**
  1103. * Returns the view callback (if set).
  1104. *
  1105. * @return mixed callback method
  1106. */
  1107. protected function getViewCallback()
  1108. {
  1109. return $this->m_viewCallback;
  1110. }
  1111. /**
  1112. * Sets the view callback.
  1113. *
  1114. * The callback is called instead of the regular display method of the
  1115. * attribute.
  1116. *
  1117. * @param mixed $callback callback method
  1118. */
  1119. public function setViewCallback($callback)
  1120. {
  1121. $this->m_viewCallback = $callback;
  1122. }
  1123. /**
  1124. * Retrieve the html code for placing this attribute in a view page.
  1125. *
  1126. * Method is 'smart' and can be overridden in the entity using the
  1127. * <attributename>_display() methods.
  1128. *
  1129. * Framework method, it should not be necessary to call this method
  1130. * directly.
  1131. *
  1132. * @param String $mode The mode ("view")
  1133. * @param array $defaults The record holding the values for this attribute
  1134. *
  1135. * @return String the HTML code for this attribute that can be used in a
  1136. * viewpage.
  1137. */
  1138. function getView($mode, &$defaults)
  1139. {
  1140. $method = $this->m_name . "_display";
  1141. if ($this->getViewCallback() != null) {
  1142. return call_user_func($this->getViewCallback(), $defaults, $mode, $this);
  1143. } else if (method_exists($this->m_ownerInstance, $method)) {
  1144. return $this->m_ownerInstance->$method($defaults, $mode);
  1145. } else {
  1146. return $this->display($defaults, $mode) . (strlen($this->m_postfixlabel) > 0 ? "&nbsp;" . $this->m_postfixlabel : "");
  1147. }
  1148. }
  1149. /**
  1150. * Retrieve the html/javascript code for showing the tooltip for this attribute.
  1151. *
  1152. * @return String HTML
  1153. */
  1154. function getToolTip()
  1155. {
  1156. $tooltip = $this->text($this->fieldName() . '_tooltip', false);
  1157. if (!$tooltip) {
  1158. return '';
  1159. }
  1160. $template = atkTheme::getInstance()->tplPath('tooltip.tpl', $this->getModule());
  1161. $vars = array('tooltip' => $tooltip, 'attribute' => $this);
  1162. $result = $this->getOwnerInstance()->getUi()->render($template, $vars, $this->getModule());
  1163. return $result;
  1164. }
  1165. /**
  1166. * Returns the edit callback (if set).
  1167. *
  1168. * @return mixed callback method
  1169. */
  1170. protected function getEditCallback()
  1171. {
  1172. return $this->m_editCallback;
  1173. }
  1174. /**
  1175. * Sets the edit callback.
  1176. *
  1177. * The callback is called instead of the regular display method of the
  1178. * attribute.
  1179. *
  1180. * @param mixed $callback callback method
  1181. */
  1182. public function setEditCallback($callback)
  1183. {
  1184. $this->m_editCallback = $callback;
  1185. }
  1186. /**
  1187. * Retrieve the HTML code for placing this attribute in an edit page.
  1188. *
  1189. * The difference with the edit() method is that the edit() method just
  1190. * generates the HTML code for editing the attribute, while the getEdit()
  1191. * method is 'smart', and implements a hide/readonly policy based on
  1192. * flags and/or custom override methodes in the entity.
  1193. * (<attributename>_edit() and <attributename>_display() methods)
  1194. *
  1195. * Framework method, it should not be necessary to call this method
  1196. * directly.
  1197. *
  1198. * @param String $mode The edit mode ("add" or "edit")
  1199. * @param array $defaults The record holding the values for this attribute
  1200. * @param String $fieldprefix The fieldprefix to put in front of the name
  1201. * of any html form element for this attribute.
  1202. * @return String the HTML code for this attribute that can be used in an
  1203. * editpage.
  1204. */
  1205. function getEdit($mode, &$defaults, $fieldprefix)
  1206. {
  1207. // readonly
  1208. if (($mode == "edit" && $this->hasFlag(AF_READONLY_EDIT)) || ($mode == "add" && $this->hasFlag(AF_READONLY_ADD))) {
  1209. return $this->hide($defaults, $fieldprefix) . $this->getView($mode, $defaults);
  1210. }
  1211. $method = $this->m_name . "_edit";
  1212. if ($this->getEditCallback() != null) {
  1213. return call_user_func($this->getEditCallback(), $defaults, $fieldprefix, $mode, $this);
  1214. } else if ($this->m_name != "action" && method_exists($this->m_ownerInstance, $method)) {
  1215. // we can't support the override for attributes named action, because of a conflict with
  1216. // a possible edit action override (in both cases the method is called action_edit)
  1217. return $this->m_ownerInstance->$method($defaults, $fieldprefix, $mode);
  1218. } else {
  1219. return $this->edit($defaults, $fieldprefix, $mode) . (strlen($this->m_postfixlabel) > 0 ? "&nbsp;" . $this->m_postfixlabel : "");
  1220. }
  1221. }
  1222. /**
  1223. * Check if this attribute has errors in the specified error list.
  1224. *
  1225. * @param array $errors The error list is one that is stored in the
  1226. * "atkerror" section of a record, for example
  1227. * generated by validate() methods.
  1228. * @return boolean
  1229. */
  1230. function getError($errors)
  1231. {
  1232. for ($i = 0; $i < count($errors); $i++) {
  1233. if ($errors[$i]['attrib_name'] == $this->fieldName() || Adapto_in_array($this->fieldName(), $errors[$i]['attrib_name'])) {
  1234. return true;
  1235. }
  1236. }
  1237. return false;
  1238. }
  1239. /**
  1240. * Adds the attribute / field to the list header. This includes the column name and search field.
  1241. *
  1242. * Framework method. It should not be necessary to call this method directly.
  1243. *
  1244. * @param String $action the action that is being performed on the entity
  1245. * @param array $arr reference to the the recordlist array
  1246. * @param String $fieldprefix the fieldprefix
  1247. * @param int $flags the recordlist flags
  1248. * @param array $atksearch the current ATK search list (if not empty)
  1249. * @param atkColumnConfig $columnConfig Column configuration object
  1250. * @param atkDataGrid $grid The atkDataGrid this attribute lives on.
  1251. * @param string $column child column (null for this attribute, * for this attribute and all childs)
  1252. */
  1253. public function addToListArrayHeader($action, &$arr, $fieldprefix, $flags, $atksearch, $columnConfig, atkDataGrid $grid = null, $column = '*')
  1254. {
  1255. if ($column != null && $column != '*') {
  1256. throw new Exception("Invalid list column {$column} for " . get_class($this) . " " . $this->getOwnerInstance()->atkEntityType() . '::'
  1257. . $this->fieldName());
  1258. }
  1259. if (!$this->hasFlag(AF_HIDE_LIST) && !($this->hasFlag(AF_HIDE_SELECT) && $action == "select")) {
  1260. $key = $fieldprefix . $this->fieldName();
  1261. $arr["heading"][$key]["title"] = $this->label();
  1262. if ($grid->hasFlag(atkDataGrid::SORT) && !$this->hasFlag(AF_NO_SORT)) {
  1263. $arr["heading"][$key]["order"] = $this->listHeaderSortOrder($columnConfig, $fieldprefix);
  1264. }
  1265. if ($grid->hasFlag(atkDataGrid::EXTENDED_SORT)) {
  1266. $arr["sort"][$key] = $this->extendedSort($columnConfig, $fieldprefix, $grid);
  1267. }
  1268. if ($grid->hasFlag(atkDataGrid::SEARCH) && $this->hasFlag(AF_SEARCHABLE)) {
  1269. $fn = $this->fieldName() . "_search";
  1270. if (method_exists($this->m_ownerInstance, $fn)) {
  1271. $arr["search"][$key] = $this->m_ownerInstance->$fn($atksearch, false, $fieldprefix, $grid);
  1272. } else {
  1273. $arr["search"][$key] = $this->search($atksearch, false, $fieldprefix, $grid);
  1274. }
  1275. $arr["search"][$key] .= $this->searchMode(false, $fieldprefix);
  1276. }
  1277. }
  1278. }
  1279. /**
  1280. * Adds the attribute / field to the list row. And if the row is totalisable also to the total.
  1281. *
  1282. * Framework method. It should not be necessary to call this method directly.
  1283. *
  1284. * @param String $action the action that is being performed on the entity
  1285. * @param array $arr reference to the the recordlist array
  1286. * @param int $nr the current row number
  1287. * @param String $fieldprefix the fieldprefix
  1288. * @param int $flags the recordlist flags
  1289. * @param boolean $edit editing?
  1290. * @param atkDataGrid $grid data grid
  1291. * @param string $column child column (null for this attribute, * for this attribute and all childs)
  1292. */
  1293. public function addToListArrayRow($action, &$arr, $nr, $fieldprefix, $flags, $edit = false, atkDataGrid $grid = null, $column = '*')
  1294. {
  1295. if ($column != null && $column != '*') {
  1296. throw new Exception("Invalid list column {$column} for " . get_class($this) . " " . $this->getOwnerInstance()->atkEntityType() . '::'
  1297. . $this->fieldName());
  1298. }
  1299. if (!$this->hasFlag(AF_HIDE_LIST) && !($this->hasFlag(AF_HIDE_SELECT) && $action == "select")) {
  1300. if ($edit) {
  1301. $arr["rows"][$nr]["data"][$fieldprefix . $this->fieldName()] = $this
  1302. ->getEdit('list', $arr["rows"][$nr]["record"], 'atkdatagriddata_AE_' . $nr . '_AE_');
  1303. } else {
  1304. $arr["rows"][$nr]["data"][$fieldprefix . $this->fieldName()] = $this->getView('list', $arr["rows"][$nr]["record"]);
  1305. }
  1306. /* totalisable? */
  1307. if ($this->hasFlag(AF_TOTAL)) {
  1308. $sum = $this->sum($arr["totalraw"], $arr["rows"][$nr]["record"], $fieldprefix);
  1309. $arr["totalraw"][$this->fieldName()] = $sum[$this->fieldName()];
  1310. $arr["total"][$fieldprefix . $this->fieldName()] = $this->getView('list', $sum);
  1311. }
  1312. }
  1313. }
  1314. /**
  1315. * Returns a piece of html code that can be used to get search terms input
  1316. * from the user.
  1317. *
  1318. * The framework calls this method to display the searchbox
  1319. * in the search bar of the recordlist, and to display a more extensive
  1320. * search in the 'extended' search screen.
  1321. * The regular atkAttributes returns a simple text input box for entering
  1322. * a keyword to search for.
  1323. * @todo find a better way to search on onetomanys that does not require
  1324. * something evil in Adapto_Attribute
  1325. * @param array $record Array with values
  1326. * @param boolean $extended if set to false, a simple search input is
  1327. * returned for use in the searchbar of the
  1328. * recordlist. If set to true, a more extended
  1329. * search may be returned for the 'extended'
  1330. * search page. The Adapto_Attribute does not
  1331. * make a difference for $extended is true, but
  1332. * derived attributes may reimplement this.
  1333. * @param string $fieldprefix The fieldprefix of this attribute's HTML element.
  1334. *
  1335. * @return String A piece of html-code
  1336. */
  1337. public function search($record = array(), $extended = false, $fieldprefix = "", atkDataGrid $grid = null)
  1338. {
  1339. $id = $this->getSearchFieldName($fieldprefix);
  1340. $value = "";
  1341. if (is_array($record) && isset($record[$this->fieldName()])) {
  1342. $value = $record[$this->fieldName()];
  1343. }
  1344. $this->registerKeyListener($id, KB_CTRLCURSOR | KB_UPDOWN);
  1345. $result = '<input type="text" id="' . $id . '" class="' . get_class($this) . '" name="' . $id . '" value="' . atk_htmlentities($value) . '"'
  1346. . ($this->m_searchsize > 0 ? ' size="' . $this->m_searchsize . '"' : '') . ($this->m_maxsize > 0 ? ' maxlength="' . $this->m_maxsize . '"' : '')
  1347. . '>';
  1348. return $result;
  1349. }
  1350. /**
  1351. * Returns piece of html which is used for setting/selecting the search
  1352. * mode for this attribute.
  1353. *
  1354. * It will show a pulldown if using extended search and multiple
  1355. * searchmodes are supported otherwise the default searchmode is selected.
  1356. *
  1357. * @param boolean $extended using extended search?
  1358. * @param string $fieldprefix optional fieldprefix
  1359. * @return string html which is used for selecting searchmode
  1360. */
  1361. public function searchMode($extended = false, $fieldprefix = '')
  1362. {
  1363. $searchModes = $this->getSearchModes();
  1364. $dbSearchModes = $this->getDb()->getSearchModes();
  1365. $searchModes = array_values(array_intersect($searchModes, $dbSearchModes));
  1366. $searchMode = $this->getSearchMode($extended);
  1367. // Set current searchmode to first searchmode if not searching in extended form or no searchmode is set
  1368. if (!$extended || empty($searchMode) || !in_array($searchMode, $searchModes))
  1369. $searchMode = $searchModes[0];
  1370. if ($extended && count($searchModes) > 1) {
  1371. $field = '<select name="' . $this->getSearchModeFieldname($fieldprefix) . '">';
  1372. foreach ($searchModes as $value) {
  1373. $selected = $searchMode == $value ? ' selected="selected"' : '';
  1374. $field .= '<option value="' . $value . '"' . $selected . '>' . Adapto_htmlentities($this->text("search_" . $value)) . '</option>';
  1375. }
  1376. $field .= '</select>';
  1377. } else {
  1378. $field = '<input type="hidden" name="' . $this->getSearchModeFieldname($fieldprefix) . '" value="' . $searchMode . '">'
  1379. . ($extended ? atktext("search_" . $searchMode) : '');
  1380. }
  1381. return $field;
  1382. }
  1383. /**
  1384. * Retrieve the current set or default searchmode of this attribute
  1385. *
  1386. * @param boolean $extended Whether extended search is being used
  1387. * @return String the default searchmode for this attribute.
  1388. */
  1389. function getSearchMode($extended = false)
  1390. {
  1391. $searchmode = $this->m_ownerInstance->getSearchMode();
  1392. if (is_array($searchmode)) {
  1393. return $searchmode[$this->fieldName()];
  1394. }
  1395. return $searchmode;
  1396. }
  1397. /**
  1398. * Creates a smart search condition for a given search value, and adds it
  1399. * to the query that will be used for performing the actual search.
  1400. *
  1401. * @param Integer $id The unique smart search criterium identifier.
  1402. * @param Integer $nr The element number in the path.
  1403. * @param Array $path The remaining attribute path.
  1404. * @param atkQuery $query The query to which the condition will be added.
  1405. * @param String $ownerAlias The owner table alias to use.
  1406. * @param Mixed $value The value the user has entered in the searchbox.
  1407. * @param String $mode The searchmode to use.
  1408. */
  1409. function smartSearchCondition($id, $nr, $path, &$query, $ownerAlias, $value, $mode)
  1410. {
  1411. // default implementation doesn't supported nested paths, this method
  1412. // should be overriden by relations etc. if they want to support this
  1413. if (count($path) > 0) {
  1414. Adapto_var_dump($path, 'Invalid search path for ' . $this->m_ownerInstance->atkEntityType() . '#' . $this->fieldName() . ', ignoring criterium!');
  1415. } else {
  1416. $this->searchCondition($query, $ownerAlias, $value, $mode);
  1417. }
  1418. }
  1419. /**
  1420. * Creates a search condition for a given search value, and adds it to the
  1421. * query that will be used for performing the actual search.
  1422. *
  1423. * @param atkQue…

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