PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/Adapto/src/Adapto/EntityDef/Policy.php

http://github.com/egeniq/adapto
PHP | 776 lines | 447 code | 102 blank | 227 comment | 96 complexity | 56804c50012fa325e53690ffbdbb66cd MD5 | raw file
  1. <?php
  2. namespace Adapto\EntityDef;
  3. class Policy
  4. {
  5. /**
  6. * Find destination entity for the given meta relation.
  7. * TODO: this hasn't been adapto-ized yet. Also it should go in Entity/Policy, not in
  8. * field policy.
  9. *
  10. * @param string $accessor accessor name
  11. * @param bool $toMany accessor name might be in plural form?
  12. *
  13. * @return string destination entity name for the given relation
  14. */
  15. protected function _findDestination($accessor, $toMany)
  16. {
  17. $module = getEntityModule($accessor);
  18. if ($module == "")
  19. $module = $this->m_entity->m_module;
  20. $entity = getEntityType($accessor);
  21. if ($module != "")
  22. {
  23. if (entityExists("$module.$entity"))
  24. return "$module.$entity";
  25. if ($toMany && entityExists("$module.".$this->getGrammar()->singularize($entity)))
  26. return "$module.".$this->getGrammar()->singularize($entity);
  27. if (!$toMany && entityExists("$module.".$this->getGrammar()->pluralize($entity)))
  28. return "$module.".$this->getGrammar()->pluralize($entity);
  29. if (entityExists("{$module}.{$module}_{$entity}"))
  30. return "{$module}.{$module}_{$entity}";
  31. if ($toMany && entityExists("{$module}.{$module}_".$this->getGrammar()->singularize($entity)))
  32. return "{$module}.{$module}_".$this->getGrammar()->singularize($entity);
  33. if (!$toMany && entityExists("{$module}.{$module}_".$this->getGrammar()->pluralize($entity)))
  34. return "{$module}.{$module}_".$this->getGrammar()->pluralize($entity);
  35. }
  36. if (entityExists($entity))
  37. return $entity;
  38. if ($toMany && entityExists($this->getGrammar()->singularize($entity)))
  39. return $this->getGrammar()->singularize($entity);
  40. if (!$toMany && entityExists($this->getGrammar()->pluralize($entity)))
  41. return $this->getGrammar()->pluralize($entity);
  42. return NULL;
  43. }
  44. /**
  45. * Returns a list of possible attribute name variants for relations
  46. * which reference this entity or the given destination entity.
  47. *
  48. * @param string $destination destination entity
  49. *
  50. * @return array list of attribute variants
  51. */
  52. protected function _getDestinationAttributeVariants($destination=null)
  53. {
  54. $base = array();
  55. // no destination given, self is assumed, we also add the table name
  56. // and parent classes as base for the different variants
  57. if ($destination == null)
  58. {
  59. $module = getEntityModule($this->getEntity()->atkEntityType());
  60. $base[] = $this->getEntityTable();
  61. $base[] = getEntityType($this->getEntity()->atkEntityType());
  62. for ($class = get_class($this->getEntity()); stripos($class, 'metaentity') === false; $class = get_parent_class($class))
  63. {
  64. $base[] = strtolower($class);
  65. }
  66. $base = array_unique($base);
  67. }
  68. else
  69. {
  70. $module = getEntityModule($destination);
  71. $base[] = getEntityType($destination);
  72. }
  73. if ($module != null)
  74. {
  75. // add variants for each base with the module as prefix or with the module
  76. // prefix stripped out (if it was already part of base), we explicitly
  77. // make a copy of base so that new entries don't mess up the loop
  78. foreach (array_values($base) as $entry)
  79. {
  80. // entry already contains module prefix, strip it
  81. if (substr($entry, 0, strlen($module) + 1) == $module.'_')
  82. {
  83. $base[] = substr($entry, strlen($module) + 1);
  84. }
  85. // entry doesn't contain prefix yet, add it
  86. else
  87. {
  88. $base[] = $module."_".$entry;
  89. }
  90. }
  91. }
  92. $variants = array();
  93. foreach ($base as $entry)
  94. {
  95. $variants[] = "{$entry}_id";
  96. $variants[] = $this->getGrammar()->singularize($entry)."_id";
  97. $variants[] = "{$entry}id";
  98. $variants[] = $this->getGrammar()->singularize($entry)."id";
  99. $variants[] = $entry;
  100. $variants[] = $this->getGrammar()->singularize($entry);
  101. }
  102. $variants = array_values(array_unique($variants));
  103. return $variants;
  104. }
  105. /**
  106. * Find source attribute for a many-to-one relation that point to the
  107. * given destination entity.
  108. *
  109. * @param string $destination destination entity type
  110. *
  111. * @return string source attribute name
  112. */
  113. protected function _findSourceAttribute($destination)
  114. {
  115. $module = getEntityModule($destination);
  116. $type = getEntityType($destination);
  117. $prefixes = $module == null ? array('') : array('', "{$module}_");
  118. foreach ($prefixes as $leftPrefix)
  119. {
  120. foreach ($prefixes as $rightPrefix)
  121. {
  122. foreach (array_keys($this->m_attrs) as $name)
  123. {
  124. switch ($leftPrefix.$name)
  125. {
  126. case "{$rightPrefix}{$type}_id":
  127. case "{$rightPrefix}{$type}id":
  128. case $rightPrefix.$this->getGrammar()->singularize($type)."_id":
  129. case $rightPrefix.$this->getGrammar()->singularize($type)."id":
  130. case $rightPrefix.$type:
  131. case $rightPrefix.$this->getGrammar()->singularize($type):
  132. return $name;
  133. }
  134. }
  135. }
  136. }
  137. return null;
  138. }
  139. /**
  140. * One-to-many / many-to-many relation support. You can call the hasMany
  141. * method to indicate that this entity has a one-to-many or a many-to-many
  142. * relationship with another entity. The meta policy will then try to guess,
  143. * amongst other things, which fields should be used for this relation.
  144. *
  145. * This method uses a smart name guessing scheme for the (optional
  146. * intermediate) and destination entity. If you enter the plural form of
  147. * the (singular) entity name it will still be able to find the entity.
  148. * You can ommit the module name prefix if the destination entity resides
  149. * in the same module as the source entity. Ofcourse you can also just use
  150. * the real module/entity name combination.
  151. *
  152. * The options list may contain several parameters to make more complex
  153. * relations work. The supported parameters are as follows:
  154. *
  155. * - dest(-ination) destination attribute name
  156. * - filter destination filter
  157. * - through intermediary entity name (for many-to-many relations)
  158. * - local if ATK can't determine the key in the intermediary entity
  159. * automatically, use local to tell it which key points to
  160. * the source entity.
  161. * - remote if ATK can't determine the key in the intermediary entity
  162. * use remote to tell it which key points to the
  163. * destination entity.
  164. * - type type of many-to-many relation (shuttle, select,
  165. * eshuttle, bool(ean) or list, defaults to shuttle)
  166. * - cols/columns number of columns (many-to-many bool relations only)
  167. * - rows number of rows (many-to-many list relations only)
  168. * - name name for this relation (by default getEntityType($accessor))
  169. *
  170. * @param string $accessor accessor name (complete description is given above)
  171. * @param string|array $templateOrOptions template or list of options (complete description is given above)
  172. * @param array $options list op options (complete description is given above)
  173. * @param int $flags the flags for the relation
  174. *
  175. * @return atkMetaAttributeModifier
  176. */
  177. public function hasMany($accessor, $templateOrOptions=array(), $options=array(), $flags=0)
  178. {
  179. $template = NULL;
  180. if (is_array($templateOrOptions))
  181. $options = $templateOrOptions;
  182. else $template = $templateOrOptions;
  183. if (isset($options['name']))
  184. {
  185. $name = $options['name'];
  186. }
  187. else
  188. {
  189. $name = getEntityType($accessor);
  190. }
  191. if (isset($options['source']))
  192. {
  193. $options['local'] = $options['source'];
  194. }
  195. if (isset($options['class']))
  196. {
  197. $type = $options['class'];
  198. }
  199. $destination = $this->_findDestination($accessor, true);
  200. if (empty($destination))
  201. {
  202. throw new Exception("Cannot find destination for ".$this->getEntity()->atkEntityType()."::hasMany({$accessor}, ...)");
  203. }
  204. if (isset($options['through']))
  205. {
  206. if (!isset($type))
  207. {
  208. switch (@$options['type'])
  209. {
  210. case 'bool':
  211. case 'boolean':
  212. $type = "atk.meta.relations.atkmetamanyboolrelation";
  213. break;
  214. case 'list':
  215. $type = "atk.meta.relations.atkmetamanytomanylistrelation";
  216. break;
  217. case 'select':
  218. $type = "atk.meta.relations.atkmetamanytomanyselectrelation";
  219. break;
  220. case 'eshuttle':
  221. case 'extendableshuttle':
  222. $type = "atk.meta.relations.atkmetaextendableshuttlerelation";
  223. break;
  224. case 'shuttle':
  225. default:
  226. $type = "atk.meta.relations.atkmetashuttlerelation";
  227. }
  228. }
  229. $through = $this->_findDestination($options['through'], true);
  230. if (empty($through))
  231. {
  232. throw new Exception("Cannot find intermediate entity for ".$this->getEntity()->atkEntityType()."::hasMany({$accessor}, array(through => {$options['through']}, ...))");
  233. }
  234. if (!isset($options['local']))
  235. {
  236. $options['localVariants'] = $this->_getDestinationAttributeVariants();
  237. }
  238. if (!isset($options['remote']))
  239. {
  240. $remoteVariants = $this->_getDestinationAttributeVariants($destination);
  241. if (isset($options['name']))
  242. $remoteVariants = array_merge($remoteVariants, $this->_getDestinationAttributeVariants($options['name']));
  243. $options['remoteVariants'] = $remoteVariants;
  244. }
  245. $params = array($destination, $through, $template, $options);
  246. }
  247. else
  248. {
  249. if (!isset($type))
  250. {
  251. $type = "atk.meta.relations.atkmetaonetomanyrelation";
  252. }
  253. $variants = $this->_getDestinationAttributeVariants();
  254. $options['variants'] = $variants;
  255. $params = array($destination, $template, $options);
  256. }
  257. $flags = AF_HIDE_LIST|AF_HIDE_ADD|$flags;
  258. $tabs = NULL;
  259. $order = $this->_getMaxOrder() + 100 ;
  260. return $this->add($name, $type, $params, $flags, $tabs, $order);
  261. }
  262. /**
  263. * Many-to-one / one-to-one relation support. You can call the hasOne method
  264. * to indicate that this entity has a many-to-one or a one-to-one relation with
  265. * another entity. The meta policy will then try to guess, amongst other
  266. * things, which fields should be used for this relation.
  267. *
  268. * To determine if a many-to-one or a one-to-one relation should be used
  269. * the system will check if the source entity contains an attribute for
  270. * storing the relation. If so the system will use a many-to-one relation,
  271. * else a one-to-one relation will be used.
  272. *
  273. * This method uses a smart name guessing scheme for the destination entity.
  274. * If you enter the singular form of the (plural) entity name it will still
  275. * be able to find the entity. You can ommit the module name prefix if the
  276. * destination entity resides in the same module as the source entity. Ofcourse
  277. * you can also just use the real module/entity name combination.
  278. *
  279. * The options list may contain several parameters to make more complex
  280. * relations work. The supported parameters are as follows:
  281. *
  282. * - source source attribute name (should only be used for
  283. * many-to-one relations and will act as an indicator
  284. * for whatever this is a many-to-one relation or not)
  285. * - dest(-ination) destination attribute name (should only be used for
  286. * one-to-one relations and will act as an indicator
  287. * for whatever this is a one-to-one relation or not)
  288. * - filter destination filter
  289. * - large boolean indicating if there will be lots and lots of
  290. * records in case of a many-to-one relation, same as
  291. * the AF_LARGE flag (defaults to false)
  292. *
  293. * @param string $accessor accessor name (complete description is given above)
  294. * @param string|array $templateOrOptions template or list of options (complete description is given above)
  295. * @param array $options list op options (complete description is given above)
  296. * @param int $flags the flags for the relation
  297. *
  298. * @return atkMetaAttributeModifier
  299. */
  300. public function hasOne($accessor, $templateOrOptions=array(), $options=array(), $flags=0)
  301. {
  302. $template = NULL;
  303. if (is_array($templateOrOptions))
  304. $options = $templateOrOptions;
  305. else $template = $templateOrOptions;
  306. // look-up destination entity
  307. $destination = $this->_findDestination($accessor, false);
  308. if (empty($destination))
  309. {
  310. throw new Exception("Cannot find destination for ".$this->getEntity()->atkEntityType()."::hasOne($accessor, ...)");
  311. }
  312. // explicit source given
  313. if (array_key_exists("source", $options))
  314. {
  315. // in case of multi referential key "source" is array
  316. if (is_array($options["source"]))
  317. {
  318. $attr = $options["source"][0]; // we use the first key as name of attribute
  319. }
  320. else
  321. {
  322. $attr = $options["source"];
  323. }
  324. }
  325. // no source and no destination given, still try to find a source attribute just to be sure
  326. // note that findSourceAttribute probably returns null for one-to-one relations
  327. else if (!array_key_exists("dest", $options) && !array_key_exists("destination", $options))
  328. {
  329. $attr = $this->_findSourceAttribute($destination);
  330. }
  331. // one-to-one relation, lookup possible destination attribute variants
  332. if ($attr == null && !array_key_exists("dest", $options) && !array_key_exists("destination", $options))
  333. {
  334. $options['variants'] = $this->_getDestinationAttributeVariants();
  335. }
  336. $name = $attr != NULL ? $attr : getEntityType($accessor);
  337. $type = "atk.meta.relations.atkmeta".($attr != NULL ? 'many' : 'one')."toonerelation";
  338. $params = array($destination, $template, $options);
  339. $flags = ($attr != NULL ? $this->m_attrs[$attr]["flags"] : 0) | (array_key_exists("large", $options) && $options["large"] ? AF_LARGE : 0) | $flags;
  340. $tabs = $attr != NULL ? $this->m_attrs[$attr]["tabs"] : NULL;
  341. $order = $attr != NULL ? $this->m_attrs[$attr]["order"] : $this->_getMaxOrder() + 100;
  342. return $this->add($name, $type, $params, $flags, $tabs, $order);
  343. }
  344. /**
  345. * Add / replace (custom) attribute.
  346. *
  347. * @param string|array $name attribute name or list of attributes
  348. * @param string $type attribute type
  349. * @param array $params attribute parameters, excluding flags (optional)
  350. * @param int $flags attribute flags (optional)
  351. * @param string|array $sections sections/tabs to display the attribute on
  352. * @param int $order order of the attribute
  353. * @param mixed $default default value
  354. *
  355. * @return atkMetaAttributeModifier
  356. */
  357. public function add($name, $type='atkattribute', $params=array(), $flags=0, $sections=NULL, $order=NULL, $default=self::NO_DEFAULT_VALUE)
  358. {
  359. $this->importAttribute($type);
  360. $names = is_array($name) ? $name : array($name);
  361. foreach ($names as $name)
  362. {
  363. if ($order === NULL && isset($this->m_attrs[$name]))
  364. {
  365. $order = $this->m_attrs[$name]['order'];
  366. }
  367. else if ($order === NULL)
  368. {
  369. $order = $this->_getMaxOrder() + 100;
  370. }
  371. $this->m_attrs[$name] =
  372. array(
  373. "type" => $type,
  374. "params" => $params,
  375. "flags" => $flags,
  376. "tabs" => $sections,
  377. "column" => null,
  378. "order" => $order
  379. );
  380. if ($default != self::NO_DEFAULT_VALUE)
  381. {
  382. $this->m_attrs[$name]['default'] = $default;
  383. }
  384. }
  385. $this->sortAttributes();
  386. return Adapto_ClassLoader::create('atk.meta.atkmetaattributemodifier', $this, $names);
  387. }
  388. /**
  389. * Add fieldset.
  390. *
  391. * To include an attribute label use [attribute.label] inside your
  392. * template. To include an attribute edit/display field use
  393. * [attribute.field] inside your template.
  394. *
  395. * @param string $name name
  396. * @param string $template template string
  397. * @param int $flags attribute flags
  398. * @param string|array $sections sections/tabs to display the attribute on
  399. * @param int $order order of the attribute
  400. *
  401. * @return atkMetaAttributeModifier
  402. */
  403. public function addFieldSet($name, $template, $flags=0, $sections=NULL, $order=NULL)
  404. {
  405. return $this->add($name, 'atk.attributes.atkfieldset', array($template), $flags, $sections, $order);
  406. }
  407. /**
  408. * Remove attribute.
  409. *
  410. * @param string|array $name attribute name
  411. */
  412. public function remove($name)
  413. {
  414. $names = is_array($name) ? $name : func_get_args();
  415. foreach ($names as $name)
  416. {
  417. unset($this->m_attrs[$name]);
  418. }
  419. }
  420. /**
  421. * Does the given attribute exist?
  422. *
  423. * @param string $name attribute name
  424. */
  425. public function exists($name)
  426. {
  427. return isset($this->m_attrs[$name]);
  428. }
  429. /**
  430. * Returns a reference to the attributes array.
  431. *
  432. * Be very careful when using this array, modifying it might void your warranty!
  433. *
  434. * @return array reference to the attributes array
  435. */
  436. public function &getAttributes()
  437. {
  438. return $this->m_attrs;
  439. }
  440. /**
  441. * Returns the attribute names.
  442. *
  443. * @return array string attribute names
  444. */
  445. public function getAttributeNames()
  446. {
  447. return array_keys($this->m_attrs);
  448. }
  449. /**
  450. * Translate using the entity's module and type.
  451. *
  452. * @param mixed $string string or array of strings containing the name(s) of the string to return
  453. * when an array of strings is passed, the second will be the fallback if
  454. * the first one isn't found, and so forth
  455. * @param String $module module in which the language file should be looked for,
  456. * defaults to core module with fallback to ATK
  457. * @param String $language ISO 639-1 language code, defaults to config variable
  458. * @param String $firstFallback the first module to check as part of the fallback
  459. * @param boolean $entityDefaultText if true, then it doesn't return a default text
  460. * when it can't find a translation
  461. * @return String the string from the languagefile
  462. */
  463. public function text($string, $module=NULL, $language='', $firstFallback="", $entityDefaultText=false)
  464. {
  465. return $this->getEntity()->text($string, $module, $language, $firstFallback, $entityDefaultText);
  466. }
  467. /**
  468. * Utility method to bit-or two integers.
  469. *
  470. * @param int $a integer a
  471. * @param int $b integer b
  472. *
  473. * @return int result of bit-or
  474. */
  475. public static function bitOr($a, $b)
  476. {
  477. return $a|$b;
  478. }
  479. /**
  480. * Detect entity table name.
  481. *
  482. * @return string table name
  483. */
  484. protected function _detectEntityTable()
  485. {
  486. $module = $this->getEntity()->getModule();
  487. $base = array();
  488. $base[] = $this->getEntity()->getType();
  489. $base[] = $module."_".$this->getEntity()->getType();
  490. for ($class = get_class($this->getEntity()); stripos($class, 'metaentity') === false; $class = get_parent_class($class))
  491. {
  492. $base[] = strtolower($class);
  493. $base[] = $module."_".strtolower($class);
  494. }
  495. $db = atkGetDb($this->getEntityDatabase());
  496. foreach ($base as $entry)
  497. {
  498. if ($db->tableExists($entry))
  499. {
  500. return $entry;
  501. }
  502. else if ($db->tableExists($this->getGrammar()->singularize($entry)))
  503. {
  504. return $this->getGrammar()->singularize($entry);
  505. }
  506. else if ($db->tableExists($this->getGrammar()->pluralize($entry)))
  507. {
  508. return $this->getGrammar()->pluralize($entry);
  509. }
  510. }
  511. return null;
  512. }
  513. /**
  514. * Detect entity sequence name.
  515. *
  516. * @return string sequence name
  517. */
  518. protected function _detectEntitySequence()
  519. {
  520. $cols = $this->getMetaData();
  521. $sequence = NULL;
  522. foreach ($cols as $meta)
  523. {
  524. if (isset($meta['sequence']) && strlen($meta['sequence']) > 0)
  525. {
  526. $sequence = $meta['sequence'];
  527. }
  528. }
  529. if ($sequence == NULL)
  530. {
  531. $sequence = Adapto_Config::getGlobal("database_sequenceprefix").$this->getEntityTable();
  532. }
  533. return $sequence;
  534. }
  535. /**
  536. * Intialize attribute for entity using the given column meta data.
  537. *
  538. * @param string $name column name
  539. * @param array $meta column meta data
  540. */
  541. protected function _initAttribute($name, $meta)
  542. {
  543. $typeAndParams = $this->_getTypeAndParams($name, $meta);
  544. if ($typeAndParams["type"] === NULL) return;
  545. $type = $typeAndParams['type'];
  546. $params = $typeAndParams['params'];
  547. $flags = $this->_getFlags($name, $meta);
  548. $order = $this->_getOrder($name, $meta);
  549. $default = $this->_getDefaultValue($name, $meta);
  550. $this->add($name, $type, $params, $flags, null, $order, $default);
  551. }
  552. /**
  553. * Initialize attributes using policy.
  554. */
  555. protected function _init()
  556. {
  557. $grammar = $this->getEntity()->getMetaOption('grammar');
  558. $grammar = atkMetaGrammar::get($grammar);
  559. $this->setGrammar($grammar);
  560. $compiler = $this->getEntity()->getMetaOption('compiler');
  561. $compiler = atkMetaCompiler::get($compiler);
  562. $this->setCompiler($compiler);
  563. $handler = $this->getEntity()->getMetaOption('handler');
  564. $this->setHandler($handler);
  565. $database = $this->getEntity()->getMetaOption('database', $this->getEntity()->getMetaOption('db', 'default'));
  566. $this->_setEntityDatabase($database);
  567. $table = $this->getEntity()->getMetaOption('table');
  568. if ($table == null)
  569. $table = $this->_detectEntityTable();
  570. $this->_setEntityTable($table);
  571. $db = atkGetDb($database);
  572. if ($table == null)
  573. {
  574. throw new Exception("No table found for metan entity " . $this->getEntity()->atkEntityType() . "! Are you sure you are connecting to the right database?");
  575. }
  576. else if (!$db->tableExists($table))
  577. {
  578. throw new Exception("Table {$table}, referenced by metan entity " . $this->getEntity()->atkEntityType() . ", does not exist! Are you sure you are connecting to the right database?");
  579. }
  580. $metaData = $db->tableMeta($table);
  581. $this->_setMetaData($metaData);
  582. $sequence = $this->getEntity()->getMetaOption('sequence');
  583. if ($sequence == null)
  584. $sequence = $this->_detectEntitySequence();
  585. $this->setEntitySequence($sequence);
  586. $flags = $this->getEntity()->getMetaOption('flags', 0);
  587. if (is_array($flags))
  588. $flags = array_reduce($flags, array('Adapto_Meta_Policy', 'bitOr'), 0);
  589. $this->setEntityFlags($flags);
  590. $descriptor = $this->getEntity()->getMetaOption('descriptor');
  591. $this->setEntityDescriptor($descriptor);
  592. $order = $this->getEntity()->getMetaOption('order');
  593. $this->setEntityOrder($order);
  594. $index = $this->getEntity()->getMetaOption('index');
  595. $this->setEntityIndex($index);
  596. $filter = $this->getEntity()->getMetaOption('filter');
  597. $this->setEntityFilter($filter);
  598. $securityAlias = $this->getEntity()->getMetaOption('securityAlias');
  599. $this->setEntitySecurityAlias($securityAlias);
  600. $securityMap = $this->getEntity()->getMetaOption('securityMap');
  601. $this->setEntitySecurityMap($securityMap);
  602. foreach ($metaData as $name => $meta)
  603. $this->_initAttribute($name, $meta);
  604. }
  605. /**
  606. * Modify meta policy, by default the meta method of the entity is called.
  607. */
  608. protected function _meta()
  609. {
  610. // handler / callback is set, call the handler
  611. if ($this->getHandler() != null)
  612. {
  613. call_user_func($this->getHandler(), $this);
  614. return;
  615. }
  616. // no handler set, try to call the entity's meta method if it exists
  617. if (!method_exists($this->getEntity(), 'meta')) return;
  618. $method = new ReflectionMethod($this->getEntity(), 'meta');
  619. if ($method->isStatic())
  620. {
  621. $method->invoke(get_class($this->getEntity()), $this);
  622. }
  623. else
  624. {
  625. $this->getEntity()->meta($this);
  626. }
  627. }
  628. /**
  629. * Compile policy.
  630. *
  631. * @return string code compiled code
  632. */
  633. protected function _compile()
  634. {
  635. return $this->getCompiler()->compile($this);
  636. }
  637. /**
  638. * Write compiled metan entity code to cache.
  639. *
  640. * @param string $code compiled code
  641. *
  642. * @return string file path
  643. */
  644. protected function _cache($code)
  645. {
  646. $file = new Adapto_TmpFile("meta/".$this->getEntity()->getModule()."/".$this->getEntity()->getType().".php");
  647. $file->writeFile("<?php\n$code");
  648. return $file->getPath();
  649. }
  650. /**
  651. * Build / setup entity using the collected attributes.
  652. */
  653. public function apply()
  654. {
  655. $this->_init();
  656. $this->_meta();
  657. $code = $this->_compile();
  658. if (Adapto_Config::getGlobal('debug') > 2)
  659. {
  660. Adapto_var_dump("\n\n$code", "Adapto_Meta_Policy::apply - ".$this->getEntity()->atkEntityType());
  661. }
  662. // needed for included and eval'ed code!
  663. $entity = $this->getEntity();
  664. if ($this->getEntity()->isCacheable())
  665. {
  666. $file = $this->_cache($code);
  667. include($file);
  668. }
  669. else
  670. {
  671. eval($code);
  672. }
  673. }
  674. }