1<?php
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP
6 *
7 * This content is released under the MIT License (MIT)
8 *
9 * Copyright (c) 2014 - 2019, British Columbia Institute of Technology
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package	CodeIgniter
30 * @author	EllisLab Dev Team
31 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32 * @copyright	Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
33 * @license	https://opensource.org/licenses/MIT	MIT License
34 * @link	https://codeigniter.com
35 * @since	Version 1.0.0
36 * @filesource
37 */
38defined('BASEPATH') OR exit('No direct script access allowed');
39
40/**
41 * Parser Class
42 *
43 * @package		CodeIgniter
44 * @subpackage	Libraries
45 * @category	Parser
46 * @author		EllisLab Dev Team
47 * @link		https://codeigniter.com/user_guide/libraries/parser.html
48 */
49class CI_Parser {
50
51	/**
52	 * Left delimiter character for pseudo vars
53	 *
54	 * @var string
55	 */
56	public $l_delim = '{';
57
58	/**
59	 * Right delimiter character for pseudo vars
60	 *
61	 * @var string
62	 */
63	public $r_delim = '}';
64
65	/**
66	 * Reference to CodeIgniter instance
67	 *
68	 * @var object
69	 */
70	protected $CI;
71
72	// --------------------------------------------------------------------
73
74	/**
75	 * Class constructor
76	 *
77	 * @return	void
78	 */
79	public function __construct()
80	{
81		$this->CI =& get_instance();
82		log_message('info', 'Parser Class Initialized');
83	}
84
85	// --------------------------------------------------------------------
86
87	/**
88	 * Parse a template
89	 *
90	 * Parses pseudo-variables contained in the specified template view,
91	 * replacing them with the data in the second param
92	 *
93	 * @param	string
94	 * @param	array
95	 * @param	bool
96	 * @return	string
97	 */
98	public function parse($template, $data, $return = FALSE)
99	{
100		$template = $this->CI->load->view($template, $data, TRUE);
101
102		return $this->_parse($template, $data, $return);
103	}
104
105	// --------------------------------------------------------------------
106
107	/**
108	 * Parse a String
109	 *
110	 * Parses pseudo-variables contained in the specified string,
111	 * replacing them with the data in the second param
112	 *
113	 * @param	string
114	 * @param	array
115	 * @param	bool
116	 * @return	string
117	 */
118	public function parse_string($template, $data, $return = FALSE)
119	{
120		return $this->_parse($template, $data, $return);
121	}
122
123	// --------------------------------------------------------------------
124
125	/**
126	 * Parse a template
127	 *
128	 * Parses pseudo-variables contained in the specified template,
129	 * replacing them with the data in the second param
130	 *
131	 * @param	string
132	 * @param	array
133	 * @param	bool
134	 * @return	string
135	 */
136	protected function _parse($template, $data, $return = FALSE)
137	{
138		if ($template === '')
139		{
140			return FALSE;
141		}
142
143		$replace = array();
144		foreach ($data as $key => $val)
145		{
146			$replace = array_merge(
147				$replace,
148				is_array($val)
149					? $this->_parse_pair($key, $val, $template)
150					: $this->_parse_single($key, (string) $val, $template)
151			);
152		}
153
154		unset($data);
155		$template = strtr($template, $replace);
156
157		if ($return === FALSE)
158		{
159			$this->CI->output->append_output($template);
160		}
161
162		return $template;
163	}
164
165	// --------------------------------------------------------------------
166
167	/**
168	 * Set the left/right variable delimiters
169	 *
170	 * @param	string
171	 * @param	string
172	 * @return	void
173	 */
174	public function set_delimiters($l = '{', $r = '}')
175	{
176		$this->l_delim = $l;
177		$this->r_delim = $r;
178	}
179
180	// --------------------------------------------------------------------
181
182	/**
183	 * Parse a single key/value
184	 *
185	 * @param	string
186	 * @param	string
187	 * @param	string
188	 * @return	string
189	 */
190	protected function _parse_single($key, $val, $string)
191	{
192		return array($this->l_delim.$key.$this->r_delim => (string) $val);
193	}
194
195	// --------------------------------------------------------------------
196
197	/**
198	 * Parse a tag pair
199	 *
200	 * Parses tag pairs: {some_tag} string... {/some_tag}
201	 *
202	 * @param	string
203	 * @param	array
204	 * @param	string
205	 * @return	string
206	 */
207	protected function _parse_pair($variable, $data, $string)
208	{
209		$replace = array();
210		preg_match_all(
211			'#'.preg_quote($this->l_delim.$variable.$this->r_delim).'(.+?)'.preg_quote($this->l_delim.'/'.$variable.$this->r_delim).'#s',
212			$string,
213			$matches,
214			PREG_SET_ORDER
215		);
216
217		foreach ($matches as $match)
218		{
219			$str = '';
220			foreach ($data as $row)
221			{
222				$temp = array();
223				foreach ($row as $key => $val)
224				{
225					if (is_array($val))
226					{
227						$pair = $this->_parse_pair($key, $val, $match[1]);
228						if ( ! empty($pair))
229						{
230							$temp = array_merge($temp, $pair);
231						}
232
233						continue;
234					}
235
236					$temp[$this->l_delim.$key.$this->r_delim] = $val;
237				}
238
239				$str .= strtr($match[1], $temp);
240			}
241
242			$replace[$match[0]] = $str;
243		}
244
245		return $replace;
246	}
247
248}
249