PageRenderTime 64ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/system/expressionengine/third_party/freeform/addon_builder/parser.addon_builder.php

https://bitbucket.org/studiobreakfast/sync
PHP | 997 lines | 567 code | 199 blank | 231 comment | 94 complexity | 50a280734ac078fbc969541c9222e35c MD5 | raw file
  1. <?php if ( ! defined('EXT')) exit('No direct script access allowed');
  2. /**
  3. * Solspace - Add-On Builder Framework
  4. *
  5. * @package Add-On Builder Framework
  6. * @author Solspace DevTeam
  7. * @copyright Copyright (c) 2008-2011, Solspace, Inc.
  8. * @link http://solspace.com/docs/
  9. * @version 1.2.4
  10. */
  11. /**
  12. * Abstracted Template Parser
  13. *
  14. * Augments EE templating capability.
  15. * Portions of this code are derived from core.template.php. They are used with the permission of EllisLab, Inc.
  16. *
  17. * @package Add-On Builder Framework
  18. * @subpackage Add-On Builder
  19. * @author Solspace DevTeam
  20. * @link http://solspace.com/docs/
  21. */
  22. /** --------------------------------------------
  23. /** Template Parser Class is Different in EE 1.x and EE 2.x
  24. /** --------------------------------------------*/
  25. $CI =& get_instance();
  26. $CI->load->library('template');
  27. if ( ! class_exists('Addon_builder_freeform'))
  28. {
  29. require_once 'addon_builder.php';
  30. }
  31. if (APP_VER < 2.0)
  32. {
  33. eval('class Addon_builder_parser_base_freeform extends Template { }');
  34. }
  35. else
  36. {
  37. eval('class Addon_builder_parser_base_freeform extends EE_Template { }');
  38. }
  39. class Addon_builder_parser_freeform extends Addon_builder_parser_base_freeform
  40. {
  41. private $old_get = '';
  42. // --------------------------------------------------------------------
  43. /**
  44. * Constructor
  45. *
  46. * @access public
  47. * @return null
  48. */
  49. public function __construct()
  50. {
  51. if (APP_VER < 2.0)
  52. {
  53. parent::Template();
  54. }
  55. else
  56. {
  57. parent::__construct();
  58. }
  59. // --------------------------------------------
  60. // Solves the problem of redirect links (?URL=) being added by Typography in a CP request
  61. // --------------------------------------------
  62. if (REQ == 'CP')
  63. {
  64. $this->old_get = (isset($_GET['M'])) ? $_GET['M'] : '';
  65. $_GET['M'] = 'send_email';
  66. }
  67. // --------------------------------------------
  68. // ExpressionEngine only loads snippets on PAGE and ACTION requests
  69. // --------------------------------------------
  70. if (APP_VER >= 2.0 && REQ == 'CP')
  71. {
  72. // load up any Snippets
  73. ee()->db->select('snippet_name, snippet_contents');
  74. ee()->db->where('(site_id = '.ee()->db->escape_str(ee()->config->item('site_id')).' OR site_id = 0)');
  75. $fresh = ee()->db->get('snippets');
  76. if ($fresh->num_rows() > 0)
  77. {
  78. $snippets = array();
  79. foreach ($fresh->result() as $var)
  80. {
  81. $snippets[$var->snippet_name] = $var->snippet_contents;
  82. }
  83. $var_keys = array();
  84. foreach (ee()->config->_global_vars as $k => $v)
  85. {
  86. $var_keys[] = LD.$k.RD;
  87. }
  88. foreach ($snippets as $name => $content)
  89. {
  90. $snippets[$name] = str_replace($var_keys,
  91. array_values(ee()->config->_global_vars), $content);
  92. }
  93. ee()->config->_global_vars = array_merge(ee()->config->_global_vars, $snippets);
  94. }
  95. unset($snippets);
  96. unset($fresh);
  97. }
  98. }
  99. /* END constructor() */
  100. // --------------------------------------------------------------------
  101. /**
  102. * Skeletor
  103. *
  104. * @access public
  105. * @return null
  106. */
  107. public function __destruct()
  108. {
  109. if (REQ == 'CP')
  110. {
  111. $_GET['M'] = $this->old_get;
  112. }
  113. }
  114. // --------------------------------------------------------------------
  115. /**
  116. * Process Template
  117. *
  118. * @access public
  119. * @param string
  120. * @param string
  121. * @param bool
  122. * @param string|integer
  123. * @return null
  124. */
  125. public function process_string_as_template($str)
  126. {
  127. // standardize newlines
  128. $str = preg_replace("/(\015\012)|(\015)|(\012)/", "\n", $str);
  129. ee()->load->helper('text');
  130. // convert high ascii
  131. $str = ( ee()->config->item('auto_convert_high_ascii') == 'y' ) ? ascii_to_entities($str): $str;
  132. /** -------------------------------------
  133. /** Prepare for Processing
  134. /** -------------------------------------*/
  135. $this->template_type = 'webpage';
  136. $this->template = $this->convert_xml_declaration($this->remove_ee_comments($str));
  137. $this->log_item("Template Type: ".$this->template_type);
  138. /** --------------------------------------------------
  139. /** Parse 'Site' variables
  140. /** --------------------------------------------------*/
  141. $this->log_item("Parsing Site Variables");
  142. foreach (array('site_id', 'site_label', 'site_short_name') as $site_var)
  143. {
  144. $this->global_vars[$site_var] = stripslashes(ee()->config->item($site_var));
  145. }
  146. // Parse {last_segment} variable
  147. $seg_array = ee()->uri->segment_array();
  148. if (APP_VER < 2.0)
  149. {
  150. $this->global_vars['last_segment'] = end($seg_array);
  151. }
  152. else
  153. {
  154. ee()->config->_global_vars['last_segment'] = end($seg_array);;
  155. }
  156. // --------------------------------------------
  157. // Parse Global Vars - EE 2.x
  158. // --------------------------------------------
  159. if (APP_VER >= 2.0 && count(ee()->config->_global_vars) > 0)
  160. {
  161. $this->log_item("Snippets (Keys): ".implode('|', array_keys(ee()->config->_global_vars)));
  162. $this->log_item("Snippets (Values): ".trim(implode('|', ee()->config->_global_vars)));
  163. foreach (ee()->config->_global_vars as $key => $val)
  164. {
  165. $this->template = str_replace(LD.$key.RD, $val, $this->template);
  166. }
  167. // in case any of these variables have EE comments of their own
  168. $this->template = $this->remove_ee_comments($this->template);
  169. }
  170. /** -------------------------------------
  171. /** Parse Global Vars - EE 1.x and Solspace Modules (which use this for setting own globals)
  172. /** -------------------------------------*/
  173. if (count($this->global_vars) > 0)
  174. {
  175. $this->log_item("Global Path.php Variables (Keys): ".implode('|', array_keys($this->global_vars)));
  176. $this->log_item("Global Path.php Variables (Values): ".trim(implode('|', $this->global_vars)));
  177. foreach ($this->global_vars as $key => $val)
  178. {
  179. $this->template = str_replace(LD.$key.RD, $val, $this->template);
  180. }
  181. }
  182. /** -------------------------------------
  183. /** Parse URI segments
  184. /** -------------------------------------*/
  185. for ($i = 1; $i < 10; $i++)
  186. {
  187. $this->template = str_replace(LD.'segment_'.$i.RD, ee()->uri->segment($i), $this->template);
  188. $this->segment_vars['segment_'.$i] = ee()->uri->segment($i);
  189. }
  190. /** -------------------------------------
  191. /** Parse date format string "constants"
  192. /** -------------------------------------*/
  193. $date_constants = array('DATE_ATOM' => '%Y-%m-%dT%H:%i:%s%Q',
  194. 'DATE_COOKIE' => '%l, %d-%M-%y %H:%i:%s UTC',
  195. 'DATE_ISO8601' => '%Y-%m-%dT%H:%i:%s%O',
  196. 'DATE_RFC822' => '%D, %d %M %y %H:%i:%s %O',
  197. 'DATE_RFC850' => '%l, %d-%M-%y %H:%m:%i UTC',
  198. 'DATE_RFC1036' => '%D, %d %M %y %H:%i:%s %O',
  199. 'DATE_RFC1123' => '%D, %d %M %Y %H:%i:%s %O',
  200. 'DATE_RFC2822' => '%D, %d %M %Y %H:%i:%s %O',
  201. 'DATE_RSS' => '%D, %d %M %Y %H:%i:%s %O',
  202. 'DATE_W3C' => '%Y-%m-%dT%H:%i:%s%Q'
  203. );
  204. $this->log_item("Parse Date Format String Constants");
  205. foreach ($date_constants as $key => $val)
  206. {
  207. $this->template = str_replace(LD.$key.RD, $val, $this->template);
  208. }
  209. /** --------------------------------------------------
  210. /** Current time {current_time format="%Y %m %d %H:%i:%s"}
  211. /** --------------------------------------------------*/
  212. $this->log_item("Parse Current Time Variables");
  213. $this->template = str_replace(LD.'current_time'.RD, ee()->localize->now, $this->template);
  214. if (strpos($this->template, LD.'current_time') !== FALSE AND preg_match_all("/".LD."current_time\s+format=([\"\'])([^\\1]*?)\\1".RD."/", $this->template, $matches))
  215. {
  216. for ($j = 0; $j < count($matches['0']); $j++)
  217. {
  218. $this->template = preg_replace("/".preg_quote($matches['0'][$j], '/')."/", ee()->localize->decode_date($matches['2'][$j], ee()->localize->now), $this->template, 1);
  219. }
  220. }
  221. /** --------------------------------------------
  222. /** Remove White Space from Variables
  223. /** - Prevents errors apparently, particularly when PHP is used in a template.
  224. /** --------------------------------------------*/
  225. $this->template = preg_replace("/".LD."\s*(\S+)\s*".RD."/U", LD."\\1".RD, $this->template);
  226. /** -------------------------------------
  227. /** Parse Input Stage PHP
  228. /** -------------------------------------*/
  229. if ($this->parse_php == TRUE AND $this->php_parse_location == 'input')
  230. {
  231. $this->log_item("Parsing PHP on Input");
  232. $this->template = $this->parse_template_php($this->template);
  233. }
  234. /** -------------------------------------
  235. /** Smite Our Enemies: Conditionals
  236. /** -------------------------------------*/
  237. $this->log_item("Parsing Segment, Embed, and Global Vars Conditionals");
  238. if (APP_VER < 2.0)
  239. {
  240. $this->template = $this->segment_conditionals($this->template);
  241. $this->template = $this->array_conditionals($this->template, $this->embed_vars);
  242. $this->template = $this->array_conditionals($this->template, $this->global_vars);
  243. }
  244. else
  245. {
  246. $this->template = $this->parse_simple_segment_conditionals($this->template);
  247. $this->template = $this->simple_conditionals($this->template, $this->embed_vars);
  248. $this->template = $this->simple_conditionals($this->template, ee()->config->_global_vars);
  249. }
  250. /** -------------------------------------
  251. /** Set global variable assignment
  252. /** -------------------------------------*/
  253. if (strpos($this->template, LD.'assign_variable:') !== FALSE AND preg_match_all("/".LD."assign_variable:(.+?)=([\"\'])([^\\2]*?)\\2".RD."/i", $this->template, $matches))
  254. {
  255. $this->log_item("Processing Assigned Variables: ".trim(implode('|', $matches['1'])));
  256. for ($j = 0; $j < count($matches['0']); $j++)
  257. {
  258. $this->template = str_replace($matches['0'][$j], "", $this->template);
  259. $this->template = str_replace(LD.$matches['1'][$j].RD, $matches['3'][$j], $this->template);
  260. }
  261. }
  262. /** -------------------------------------
  263. /** Replace Forward Slashes with Entity because of silliness about pre_replace errors.
  264. /** -------------------------------------*/
  265. // $this->template = str_replace('/', SLASH, $this->template);
  266. if (APP_VER < 2.0)
  267. {
  268. $this->template = str_replace('/', T_SLASH, $this->template);
  269. }
  270. else
  271. {
  272. if (strpos($str, '{&#47;exp:') !== FALSE)
  273. {
  274. $this->template = str_replace('&#47;', T_SLASH, $this->template);
  275. }
  276. }
  277. /** --------------------------------------------
  278. /** Fetch Installed Modules and Plugins
  279. /** --------------------------------------------*/
  280. $this->fetch_addons();
  281. /** --------------------------------------------
  282. /** Parse Template's Tags!
  283. /** --------------------------------------------*/
  284. $this->log_item(" - Beginning Tag Processing - ");
  285. while (is_int(strpos($this->template, LD.'exp:')))
  286. {
  287. // Initialize values between loops
  288. $this->tag_data = array();
  289. $this->var_single = array();
  290. $this->var_cond = array();
  291. $this->var_pair = array();
  292. $this->loop_count = 0;
  293. $this->log_item("Parsing Tags in Template");
  294. // Run the template parser
  295. if (APP_VER < 2.0)
  296. {
  297. $this->parse_template();
  298. }
  299. else
  300. {
  301. $this->parse_tags();
  302. }
  303. $this->log_item("Processing Tags");
  304. // Run the class/method handler
  305. if (APP_VER < 2.0)
  306. {
  307. $this->class_handler();
  308. }
  309. else
  310. {
  311. $this->process_tags();
  312. }
  313. if ($this->cease_processing === TRUE)
  314. {
  315. return;
  316. }
  317. }
  318. $this->log_item(" - End Tag Processing - ");
  319. /** --------------------------------------------
  320. /** Convert Slash Entity Back
  321. /** --------------------------------------------*/
  322. $this->template = str_replace(SLASH, '/', $this->template);
  323. /** -------------------------------------
  324. /** Parse Output Stage PHP
  325. /** -------------------------------------*/
  326. if ($this->parse_php == TRUE AND $this->php_parse_location == 'output')
  327. {
  328. $this->log_item("Parsing PHP on Output");
  329. $this->template = $this->parse_template_php($this->template);
  330. }
  331. /** -------------------------------------
  332. /** Parse Our Uncacheable Forms
  333. /** -------------------------------------*/
  334. $this->template = $this->parse_nocache($this->template);
  335. /** -------------------------------------
  336. /** Smite Our Enemies: Advanced Conditionals
  337. /** -------------------------------------*/
  338. if (stristr($this->template, LD.'if'))
  339. {
  340. $this->log_item("Processing Advanced Conditionals");
  341. $this->template = $this->advanced_conditionals($this->template);
  342. }
  343. /** -------------------------------------
  344. /** Build finalized template
  345. /** -------------------------------------*/
  346. // The sub-template routine will insert embedded templates into the master template
  347. $this->final_template = $this->template;
  348. $this->process_sub_templates($this->template);
  349. /** --------------------------------------------
  350. /** Finish with Global Vars and Return!
  351. /** --------------------------------------------*/
  352. return $this->parse_globals($this->final_template);
  353. }
  354. /* END process_string_as_template() */
  355. // --------------------------------------------------------------------
  356. /**
  357. * Class Handler
  358. *
  359. * @access public
  360. * @return null
  361. */
  362. public function class_handler()
  363. {
  364. $classes = array();
  365. // Fill an array with the names of all the classes that we previously extracted from the tags
  366. for ($i = 0, $s = sizeof($this->tag_data); $i < $s; $i++)
  367. {
  368. // Should we use the tag cache file?
  369. if ($this->tag_data[$i]['cache'] == 'CURRENT')
  370. {
  371. // If so, replace the marker in the tag with the cache data
  372. $this->log_item("Tag Cached and Cache is Current");
  373. $this->replace_marker($i, $this->get_cache_file($this->tag_data[$i]['cfile']));
  374. continue;
  375. }
  376. /** --------------------------------------------
  377. /** Module or Plugin Being Called?
  378. /** --------------------------------------------*/
  379. $class = $this->tag_data[$i]['class'];
  380. $method = $this->tag_data[$i]['method'];
  381. if ( ! in_array($class, $this->modules))
  382. {
  383. if ( ! in_array($class, $this->plugins))
  384. {
  385. $this->log_item("Invalid Tag");
  386. if (ee()->config->item('debug') < 1)
  387. {
  388. return FALSE;
  389. }
  390. if ($this->tag_data[$i]['tagparts'][0] == $this->tag_data[$i]['tagparts'][1] AND ! isset($this->tag_data[$i]['tagparts'][2]))
  391. {
  392. unset($this->tag_data[$i]['tagparts'][1]);
  393. }
  394. $error = ee()->lang->line('error_tag_syntax');
  395. $error .= '<br /><br />';
  396. $error .= htmlspecialchars(LD);
  397. $error .= 'exp:'.implode(':', $this->tag_data[$i]['tagparts']);
  398. $error .= htmlspecialchars(RD);
  399. $error .= '<br /><br />';
  400. $error .= ee()->lang->line('error_fix_syntax');
  401. ee()->output->fatal_error($error);
  402. }
  403. else
  404. {
  405. $classes[] = 'pi.'.$this->tag_data[$i]['class'];
  406. $this->log_item("Plugin Tag: ".ucfirst($class).'/'.$method);
  407. }
  408. }
  409. else
  410. {
  411. $classes[] = $this->tag_data[$i]['class'];
  412. $this->log_item("Module Tag: ".ucfirst($class).'/'.$method);
  413. }
  414. }
  415. /** --------------------------------------------
  416. /** Remove Duplicates and Fresh Order
  417. /** --------------------------------------------*/
  418. $classes = array_values(array_unique($classes));
  419. /** --------------------------------------------
  420. /** Load Files for Classes
  421. /** --------------------------------------------*/
  422. $this->log_item("Including Files for Tag and Modules");
  423. for ($i = 0; $i < count($classes); $i++)
  424. {
  425. if (class_exists($classes[$i]))
  426. {
  427. continue;
  428. }
  429. if (substr($classes[$i], 0, 3) == 'pi.')
  430. {
  431. require_once PATH_PI.$classes[$i].EXT;
  432. }
  433. else
  434. {
  435. require_once PATH_MOD.$classes[$i].'/mod.'.$classes[$i].EXT;
  436. }
  437. }
  438. /** -----------------------------------
  439. /** Only Retrieve Data if Not Done Before and Modules Being Called
  440. /** -----------------------------------*/
  441. if (sizeof($this->module_data) == 0 AND sizeof(array_intersect($this->modules, $classes)) > 0)
  442. {
  443. $query = ee()->db->query("SELECT module_version, module_name FROM exp_modules");
  444. foreach($query->result_array() as $row)
  445. {
  446. $this->module_data[$row['module_name']] = array('version' => $row['module_version']);
  447. }
  448. }
  449. /** --------------------------------------------
  450. /** Final Data Processing - Loop Through and Parse
  451. /** --------------------------------------------*/
  452. $this->log_item("Beginning Final Tag Data Processing");
  453. reset($this->tag_data);
  454. for ($i = 0, $s = sizeof($this->tag_data); $i < $s; $i++)
  455. {
  456. if ($this->tag_data[$i]['cache'] == 'CURRENT')
  457. {
  458. continue;
  459. }
  460. $lower_class_name = strtolower($this->tag_data[$i]['class']);
  461. $class_name = ucfirst($lower_class_name);
  462. $method = $this->tag_data[$i]['method'];
  463. $this->log_item("Calling Class/Method: ".$class_name."/".$method);
  464. /** --------------------------------------------
  465. /** Plugin as Parameter
  466. /** - Example: weblog="{exp:some_plugin}"
  467. /** - A bit of a hidden feature. Has been tested but not quite ready to say it is
  468. /** ready for prime time as I might want to move it to earlier in processing so that
  469. /** if there are multiple plugins being used as parameters it is only called
  470. /** once instead of for every single parameter. - Paul
  471. /** --------------------------------------------*/
  472. if (substr_count($this->tag_data[$i]['tag'], LD.'exp') > 1 AND isset($this->tag_data[$i]['params']['parse']) AND $this->tag_data[$i]['params']['parse'] == 'inward')
  473. {
  474. foreach($this->tag_data[$i]['params'] as $name => $param)
  475. {
  476. if (stristr($this->tag_data[$i]['params'][$name], LD.'exp'))
  477. {
  478. $this->log_item("Plugin in Parameter, Processing Plugin First");
  479. $this->tag_data[$i]['params'][$name] = $this->nested_processing($this->tag_data[$i]['params'][$name]);
  480. }
  481. }
  482. }
  483. /** --------------------------------------------
  484. /** Nested Plugins
  485. /** --------------------------------------------*/
  486. if (in_array($lower_class_name, $this->plugins) AND strpos($this->tag_data[$i]['block'], LD.'exp:') !== false)
  487. {
  488. if ( ! isset($this->tag_data[$i]['params']['parse']) OR $this->tag_data[$i]['params']['parse'] != 'inward')
  489. {
  490. $this->log_item("Nested Plugins in Tag, Parsing Outward First");
  491. $this->tag_data[$i]['block'] = $this->nested_processing($this->tag_data[$i]['block']);
  492. }
  493. }
  494. /** --------------------------------------------
  495. /** Assign Class Variables for Parsing
  496. /** --------------------------------------------*/
  497. // We moved the no_results_block here because of nested tags. The first parsed tag has priority for that conditional.
  498. $this->tagdata = str_replace($this->tag_data[$i]['no_results_block'], '', $this->tag_data[$i]['block']);
  499. $this->tagparams = $this->tag_data[$i]['params'];
  500. $this->tagchunk = $this->tag_data[$i]['chunk'];
  501. $this->tagproper = $this->tag_data[$i]['tag'];
  502. $this->tagparts = $this->tag_data[$i]['tagparts'];
  503. $this->no_results = $this->tag_data[$i]['no_results'];
  504. $this->search_fields = $this->tag_data[$i]['search_fields'];
  505. /** -------------------------------------
  506. /** Assign Sites for Tag
  507. /** -------------------------------------*/
  508. $this->_fetch_site_ids();
  509. /** -------------------------------------
  510. /** Find Relationship Data in Weblog Entries and Search Results tags
  511. /** -------------------------------------*/
  512. // NOTE: This needs to happen before extracting the variables in the tag so it doesn't
  513. // get confused as to which entry the variables belong to.
  514. if (($lower_class_name == 'weblog' AND $method == 'entries') OR ($lower_class_name == 'search' AND $method == 'search_results'))
  515. {
  516. $this->tagdata = $this->assign_relationship_data($this->tagdata);
  517. }
  518. /** --------------------------------------------
  519. /** Assign Variables for Tags - Improve!
  520. /** --------------------------------------------*/
  521. $vars = ee()->functions->assign_variables($this->tag_data[$i]['block']);
  522. // Related Fields should be a Single Variable for Tag Parsing
  523. foreach ($this->related_markers as $mkr)
  524. {
  525. $vars['var_single'][$mkr] = $mkr;
  526. }
  527. $this->var_single = $vars['var_single'];
  528. $this->var_pair = $vars['var_pair'];
  529. /** --------------------------------------------
  530. /** Assign Conditional Variables for Non-Native Modules
  531. /** --------------------------------------------*/
  532. if ( ! in_array($lower_class_name, $this->native_modules))
  533. {
  534. $this->var_cond = ee()->functions->assign_conditional_variables($this->tag_data[$i]['block'], SLASH, LD, RD);
  535. }
  536. /** --------------------------------------------
  537. /** Instantiate and Process
  538. /** --------------------------------------------*/
  539. if (in_array($lower_class_name, $this->modules) AND ! isset($this->module_data[$class_name]))
  540. {
  541. $this->log_item("Problem Processing Module: Module Not Installed: ".$class_name);
  542. }
  543. else
  544. {
  545. $this->log_item(" -> Class Called: ".$class_name);
  546. $EE = new $class_name();
  547. }
  548. /** ----------------------------------
  549. /** Send Error if Module Not Installed or Invalid Method
  550. /** ----------------------------------*/
  551. if ((in_array($lower_class_name, $this->modules) AND ! isset($this->module_data[$class_name])) OR ! method_exists($EE, $method))
  552. {
  553. $this->log_item("Tag Not Processed: Method Non-Existent or Module Not Installed");
  554. if (ee()->config->item('debug') < 1)
  555. {
  556. return FALSE;
  557. }
  558. if ($this->tag_data[$i]['tagparts']['0'] == $this->tag_data[$i]['tagparts']['1'] AND ! isset($this->tag_data[$i]['tagparts']['2']))
  559. {
  560. unset($this->tag_data[$i]['tagparts']['1']);
  561. }
  562. $error = ee()->lang->line('error_tag_module_processing');
  563. $error .= '<br /><br />';
  564. $error .= htmlspecialchars(LD);
  565. $error .= 'exp:'.implode(':', $this->tag_data[$i]['tagparts']);
  566. $error .= htmlspecialchars(RD);
  567. $error .= '<br /><br />';
  568. $error .= str_replace('%x', $lower_class_name, str_replace('%y', $method, ee()->lang->line('error_fix_module_processing')));
  569. ee()->output->fatal_error($error);
  570. }
  571. /*
  572. OK, lets grab the data returned from the class.
  573. First, however, lets determine if the tag has one or two segments.
  574. If it only has one, we don't want to call the constructor again since
  575. it was already called during instantiation.
  576. Note: If it only has one segment, only the object constructor will be called.
  577. Since constructors can't return a value just by initialializing the object
  578. the output of the class must be assigned to a variable called $this->return_data
  579. */
  580. $this->log_item(" -> Method Called: ".$method);
  581. if (strtolower($class_name) == $method)
  582. {
  583. $return_data = (isset($EE->return_data)) ? $EE->return_data : '';
  584. }
  585. else
  586. {
  587. $return_data = $EE->$method();
  588. }
  589. /** ----------------------------------
  590. /** 404 Page Triggered, Cease All Processing of Tags From Now On
  591. /** ----------------------------------*/
  592. if ($this->cease_processing === TRUE)
  593. {
  594. return;
  595. }
  596. $this->log_item(" -> Data Returned");
  597. // Write cache file if needed
  598. if ($this->tag_data[$i]['cache'] == 'EXPIRED')
  599. {
  600. $this->write_cache_file($this->tag_data[$i]['cfile'], $return_data);
  601. }
  602. // Replace the temporary markers we added earlier with the fully parsed data
  603. $this->replace_marker($i, $return_data);
  604. // Initialize data in case there are susequent loops
  605. $this->var_single = array();
  606. $this->var_cond = array();
  607. $this->var_pair = array();
  608. $this->related_markers = array();
  609. unset($lower_class_name, $return_data, $class_name, $method, $EE);
  610. }
  611. }
  612. /* END class_handler() */
  613. // --------------------------------------------------------------------
  614. /**
  615. * Fetch Add-Ons for Instllation
  616. *
  617. * @access public
  618. * @return null
  619. */
  620. public function fetch_addons()
  621. {
  622. $this->fetch_modules();
  623. $this->fetch_plugins();
  624. if (APP_VER < 2.0)
  625. {
  626. return;
  627. }
  628. ee()->load->helper('directory');
  629. $ext_len = strlen(EXT);
  630. if (($map = directory_map(PATH_THIRD)) !== FALSE)
  631. {
  632. foreach ($map as $pkg_name => $files)
  633. {
  634. if ( ! is_array($files))
  635. {
  636. $files = array($files);
  637. }
  638. foreach ($files as $file)
  639. {
  640. if (is_array($file) OR substr($file, -$ext_len) != EXT)
  641. {
  642. continue;
  643. }
  644. // Module
  645. if (strncasecmp($file, 'mod.', 4) == 0 AND strlen($file) >= 9) // strlen('mod.a.php');
  646. {
  647. $file = substr($file, 4, -$ext_len);
  648. if ($file == $pkg_name)
  649. {
  650. $this->modules[] = $file;
  651. }
  652. }
  653. // Plugin
  654. elseif (strncasecmp($file, 'pi.', 3) == 0 AND strlen($file) >= 8) // strlen('pi.a.php');
  655. {
  656. $file = substr($file, 3, -$ext_len);
  657. if ($file == $pkg_name)
  658. {
  659. $this->plugins[] = $file;
  660. }
  661. }
  662. }
  663. }
  664. }
  665. }
  666. /* END fetch_addons() */
  667. // --------------------------------------------------------------------
  668. /**
  669. * Fetch Currently Available Modules
  670. *
  671. * @access public
  672. * @return null
  673. */
  674. public function fetch_modules()
  675. {
  676. if (sizeof($this->modules) > 0)
  677. {
  678. return;
  679. }
  680. if ( isset(ee()->session->cache['modules']['morsel']['template']['fetch_modules']))
  681. {
  682. $this->modules = ee()->session->cache['modules']['morsel']['template']['fetch_modules'];
  683. return;
  684. }
  685. foreach(array(PATH_MOD) as $directory)
  686. {
  687. if ($fp = @opendir($directory))
  688. {
  689. while (false !== ($file = readdir($fp)))
  690. {
  691. if ( is_dir($directory.$file) AND ! preg_match("/[^a-z\_0-9]/", $file))
  692. {
  693. $this->modules[] = $file;
  694. }
  695. }
  696. closedir($fp);
  697. }
  698. }
  699. $this->modules = ee()->session->cache['modules']['morsel']['template']['fetch_modules']= array_unique($this->modules);
  700. }
  701. /* END fetch_modules() */
  702. // --------------------------------------------------------------------
  703. /**
  704. * Fetch Currently Available Plugins
  705. *
  706. * @access public
  707. * @return null
  708. */
  709. public function fetch_plugins()
  710. {
  711. if (sizeof($this->plugins) > 0)
  712. {
  713. return;
  714. }
  715. if ( isset(ee()->session->cache['modules']['morsel']['template']['fetch_plugins']))
  716. {
  717. $this->plugins = ee()->session->cache['modules']['morsel']['template']['fetch_plugins'];
  718. return;
  719. }
  720. foreach(array(PATH_PI) as $directory)
  721. {
  722. if ($fp = @opendir($directory))
  723. {
  724. while (false !== ($file = readdir($fp)))
  725. {
  726. if ( preg_match("/pi\.[a-z\_0-9]+?".preg_quote(EXT, '/')."$/", $file))
  727. {
  728. $this->plugins[] = substr($file, 3, -strlen(EXT));
  729. }
  730. }
  731. closedir($fp);
  732. }
  733. }
  734. $this->plugins = ee()->session->cache['modules']['morsel']['template']['fetch_plugins'] = array_unique($this->plugins);
  735. }
  736. /* END fetch_plugins() */
  737. // --------------------------------------------------------------------
  738. /**
  739. * Nested Processing Abstraction
  740. *
  741. * @access public
  742. * @param string
  743. * @return string
  744. */
  745. public function nested_processing($parse_string)
  746. {
  747. $TMPL2 = ee()->functions->clone_object($this);
  748. while (is_int(strpos($parse_string, LD.'exp:')))
  749. {
  750. unset($TMPL, $GLOBALS['TMPL']);
  751. ee()->TMPL = $GLOBALS['TMPL'] = $TMPL = new Template();
  752. ee()->TMPL->start_microtime = $this->start_microtime;
  753. ee()->TMPL->template = $parse_string;
  754. ee()->TMPL->tag_data = array();
  755. ee()->TMPL->var_single = array();
  756. ee()->TMPL->var_cond = array();
  757. ee()->TMPL->var_pair = array();
  758. ee()->TMPL->plugins = $TMPL2->plugins;
  759. ee()->TMPL->modules = $TMPL2->modules;
  760. if (APP_VER < 2.0)
  761. {
  762. ee()->TMPL->parse_template();
  763. ee()->TMPL->class_handler();
  764. }
  765. else
  766. {
  767. ee()->TMPL->parse_tags();
  768. ee()->TMPL->process_tags();
  769. }
  770. ee()->TMPL->loop_count = 0;
  771. $parse_string = ee()->TMPL->template;
  772. $TMPL2->log = array_merge($TMPL2->log, ee()->TMPL->log);
  773. }
  774. foreach (get_object_vars($TMPL2) as $key => $value)
  775. {
  776. $this->$key = $value;
  777. }
  778. unset($TMPL2);
  779. ee()->TMPL = $GLOBALS['TMPL'] = $TMPL = $this;
  780. return $parse_string;
  781. }
  782. /* END nested_processing() */
  783. }
  784. /* END Morsel_parser CLASS */
  785. ?>