1<?php
2/**
3 * XOOPS kernel class
4 *
5 * You may not change or alter any portion of this comment or credits
6 * of supporting developers from this source code or any supporting source code
7 * which is considered copyrighted (c) material of the original comment or credit authors.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14 * @package             kernel
15 * @since               2.0.0
16 * @author              Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
17 */
18
19defined('XOOPS_ROOT_PATH') || exit('Restricted access');
20
21/**
22 * A Template File
23 *
24 * @author              Kazumi Ono <onokazu@xoops.org>
25 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
26 *
27 * @package             kernel
28 **/
29class XoopsTplfile extends XoopsObject
30{
31    /**
32     * Constructor
33     *
34     * @return XoopsTplfile
35     */
36    public function __construct()
37    {
38        parent::__construct();
39        $this->initVar('tpl_id', XOBJ_DTYPE_INT, null, false);
40        $this->initVar('tpl_refid', XOBJ_DTYPE_INT, 0, false);
41        $this->initVar('tpl_tplset', XOBJ_DTYPE_OTHER, null, false);
42        $this->initVar('tpl_file', XOBJ_DTYPE_TXTBOX, null, true, 100);
43        $this->initVar('tpl_desc', XOBJ_DTYPE_TXTBOX, null, false, 100);
44        $this->initVar('tpl_lastmodified', XOBJ_DTYPE_INT, 0, false);
45        $this->initVar('tpl_lastimported', XOBJ_DTYPE_INT, 0, false);
46        $this->initVar('tpl_module', XOBJ_DTYPE_OTHER, null, false);
47        $this->initVar('tpl_type', XOBJ_DTYPE_OTHER, null, false);
48        $this->initVar('tpl_source', XOBJ_DTYPE_SOURCE, null, false);
49    }
50
51    /**
52     * Returns Class Base Variable tpl_id
53     * @param  string $format
54     * @return mixed
55     */
56    public function id($format = 'N')
57    {
58        return $this->getVar('tpl_id', $format);
59    }
60
61    /**
62     * Returns Class Base Variable tpl_id
63     * @param  string $format
64     * @return mixed
65     */
66    public function tpl_id($format = '')
67    {
68        return $this->getVar('tpl_id', $format);
69    }
70
71    /**
72     * Returns Class Base Variable tpl_refid
73     * @param  string $format
74     * @return mixed
75     */
76    public function tpl_refid($format = '')
77    {
78        return $this->getVar('tpl_refid', $format);
79    }
80
81    /**
82     * Returns Class Base Variable tpl_tplset
83     * @param  string $format
84     * @return mixed
85     */
86    public function tpl_tplset($format = '')
87    {
88        return $this->getVar('tpl_tplset', $format);
89    }
90
91    /**
92     * Returns Class Base Variable tpl_file
93     * @param  string $format
94     * @return mixed
95     */
96    public function tpl_file($format = '')
97    {
98        return $this->getVar('tpl_file', $format);
99    }
100
101    /**
102     * Returns Class Base Variable tpl_desc
103     * @param  string $format
104     * @return mixed
105     */
106    public function tpl_desc($format = '')
107    {
108        return $this->getVar('tpl_desc', $format);
109    }
110
111    /**
112     * Returns Class Base Variable tpl_lastmodified
113     * @param  string $format
114     * @return mixed
115     */
116    public function tpl_lastmodified($format = '')
117    {
118        return $this->getVar('tpl_lastmodified', $format);
119    }
120
121    /**
122     * Returns Class Base Variable tpl_lastimported
123     * @param  string $format
124     * @return mixed
125     */
126    public function tpl_lastimported($format = '')
127    {
128        return $this->getVar('tpl_lastimported', $format);
129    }
130
131    /**
132     * Returns Class Base Variable tpl_module
133     * @param  string $format
134     * @return mixed
135     */
136    public function tpl_module($format = '')
137    {
138        return $this->getVar('tpl_module', $format);
139    }
140
141    /**
142     * Returns Class Base Variable tpl_type
143     * @param  string $format
144     * @return mixed
145     */
146    public function tpl_type($format = '')
147    {
148        return $this->getVar('tpl_type', $format);
149    }
150
151    /**
152     * Returns Class Base Variable tpl_source
153     * @param  string $format
154     * @return mixed
155     */
156    public function tpl_source($format = '')
157    {
158        return $this->getVar('tpl_source', $format);
159    }
160
161    /**
162     * getSource
163     *
164     * @return string
165     */
166    public function getSource()
167    {
168        return $this->getVar('tpl_source');
169    }
170
171    /**
172     * getLastModified
173     *
174     * @return int unixtimestamp
175     */
176    public function getLastModified()
177    {
178        return $this->getVar('tpl_lastmodified');
179    }
180}
181
182/**
183 * XOOPS template file handler class.
184 * This class is responsible for providing data access mechanisms to the data source
185 * of XOOPS template file class objects.
186 *
187 *
188 * @author  Kazumi Ono <onokazu@xoops.org>
189 *
190 * @todo this is not a XoopsPersistableObjectHandler?
191 */
192class XoopsTplfileHandler extends XoopsObjectHandler
193{
194    /**
195     * create a new Tplfile
196     *
197     * @see XoopsBlock
198     * @param  bool $isNew is the new Tplfile new??
199     * @return XoopsTplfile XoopsTplfile reference to the new Tplfile
200     **/
201    public function create($isNew = true)
202    {
203        $tplfile = new XoopsTplfile();
204        if ($isNew) {
205            $tplfile->setNew();
206        }
207
208        return $tplfile;
209    }
210
211    /**
212     * retrieve a specific {@link XoopsTplfile}
213     *
214     * @see XoopsBlock
215     *
216     * @param int  $id tpl_id of the block to retrieve
217     * @param bool $getsource
218     *
219     * @return object XoopsTplfile reference to the Tplfile
220     */
221    public function get($id, $getsource = false)
222    {
223        $tplfile = false;
224        $id      = (int)$id;
225        if ($id > 0) {
226            if (!$getsource) {
227                $sql = 'SELECT * FROM ' . $this->db->prefix('tplfile') . ' WHERE tpl_id=' . $id;
228            } else {
229                $sql = 'SELECT f.*, s.tpl_source FROM ' . $this->db->prefix('tplfile') . ' f LEFT JOIN ' . $this->db->prefix('tplsource') . ' s  ON s.tpl_id=f.tpl_id WHERE f.tpl_id=' . $id;
230            }
231            if (!$result = $this->db->query($sql)) {
232                return $tplfile;
233            }
234            $numrows = $this->db->getRowsNum($result);
235            if ($numrows == 1) {
236                $tplfile = new XoopsTplfile();
237                $tplfile->assignVars($this->db->fetchArray($result));
238            }
239        }
240
241        return $tplfile;
242    }
243
244    /**
245     * Load template source
246     *
247     * @param XoopsObject|XoopsTplfile $tplfile a XoopsTplfile object
248     *
249     * @return bool true on success, otherwise false
250     */
251    public function loadSource(XoopsObject $tplfile)
252    {
253        $className = 'XoopsTplfile';
254        if (!($tplfile instanceof $className)) {
255            return false;
256        }
257
258        if (!$tplfile->getVar('tpl_source')) {
259            $sql = 'SELECT tpl_source FROM ' . $this->db->prefix('tplsource') . ' WHERE tpl_id=' . $tplfile->getVar('tpl_id');
260            if (!$result = $this->db->query($sql)) {
261                return false;
262            }
263            $myrow = $this->db->fetchArray($result);
264            $tplfile->assignVar('tpl_source', $myrow['tpl_source']);
265        }
266
267        return true;
268    }
269
270    /**
271     * write a new Tplfile into the database
272     *
273     * @param  XoopsObject|XoopsTplfile $tplfile a XoopsTplfile object
274     *
275     * @return bool true on success, otherwise false
276     */
277    public function insert(XoopsObject $tplfile)
278    {
279        $className = 'XoopsTplfile';
280        if (!($tplfile instanceof $className)) {
281            return false;
282        }
283        if (!$tplfile->isDirty()) {
284            return true;
285        }
286        if (!$tplfile->cleanVars()) {
287            return false;
288        }
289        foreach ($tplfile->cleanVars as $k => $v) {
290            ${$k} = $v;
291        }
292        if ($tplfile->isNew()) {
293            $tpl_id = $this->db->genId('tpltpl_file_id_seq');
294            $sql    = sprintf('INSERT INTO %s (tpl_id, tpl_module, tpl_refid, tpl_tplset, tpl_file, tpl_desc, tpl_lastmodified, tpl_lastimported, tpl_type) VALUES (%u, %s, %u, %s, %s, %s, %u, %u, %s)', $this->db->prefix('tplfile'), $tpl_id, $this->db->quoteString($tpl_module), $tpl_refid, $this->db->quoteString($tpl_tplset), $this->db->quoteString($tpl_file), $this->db->quoteString($tpl_desc), $tpl_lastmodified, $tpl_lastimported, $this->db->quoteString($tpl_type));
295            if (!$result = $this->db->query($sql)) {
296                return false;
297            }
298            if (empty($tpl_id)) {
299                $tpl_id = $this->db->getInsertId();
300            }
301            if (isset($tpl_source) && $tpl_source != '') {
302                $sql = sprintf('INSERT INTO %s (tpl_id, tpl_source) VALUES (%u, %s)', $this->db->prefix('tplsource'), $tpl_id, $this->db->quoteString($tpl_source));
303                if (!$result = $this->db->query($sql)) {
304                    $this->db->query(sprintf('DELETE FROM %s WHERE tpl_id = %u', $this->db->prefix('tplfile'), $tpl_id));
305
306                    return false;
307                }
308            }
309            $tplfile->assignVar('tpl_id', $tpl_id);
310        } else {
311            $sql = sprintf('UPDATE %s SET tpl_tplset = %s, tpl_file = %s, tpl_desc = %s, tpl_lastimported = %u, tpl_lastmodified = %u WHERE tpl_id = %u', $this->db->prefix('tplfile'), $this->db->quoteString($tpl_tplset), $this->db->quoteString($tpl_file), $this->db->quoteString($tpl_desc), $tpl_lastimported, $tpl_lastmodified, $tpl_id);
312            if (!$result = $this->db->query($sql)) {
313                return false;
314            }
315            if (isset($tpl_source) && $tpl_source != '') {
316                $sql = sprintf('UPDATE %s SET tpl_source = %s WHERE tpl_id = %u', $this->db->prefix('tplsource'), $this->db->quoteString($tpl_source), $tpl_id);
317                if (!$result = $this->db->query($sql)) {
318                    return false;
319                }
320            }
321        }
322
323        return true;
324    }
325
326    /**
327     * Update Tplfile, even if a safe transaction (i.e. http get)
328     *
329     * @param  XoopsTplfile $tplfile
330     * @return bool true on success, otherwise false
331     */
332    public function forceUpdate(XoopsTplfile $tplfile)
333    {
334        $className = 'XoopsTplfile';
335        if (!($tplfile instanceof $className)) {
336            return false;
337        }
338        if (!$tplfile->isDirty()) {
339            return true;
340        }
341        if (!$tplfile->cleanVars()) {
342            return false;
343        }
344        foreach ($tplfile->cleanVars as $k => $v) {
345            ${$k} = $v;
346        }
347        if (!$tplfile->isNew()) {
348            $sql = sprintf('UPDATE %s SET tpl_tplset = %s, tpl_file = %s, tpl_desc = %s, tpl_lastimported = %u, tpl_lastmodified = %u WHERE tpl_id = %u', $this->db->prefix('tplfile'), $this->db->quoteString($tpl_tplset), $this->db->quoteString($tpl_file), $this->db->quoteString($tpl_desc), $tpl_lastimported, $tpl_lastmodified, $tpl_id);
349            if (!$result = $this->db->queryF($sql)) {
350                return false;
351            }
352            if (isset($tpl_source) && $tpl_source != '') {
353                $sql = sprintf('UPDATE %s SET tpl_source = %s WHERE tpl_id = %u', $this->db->prefix('tplsource'), $this->db->quoteString($tpl_source), $tpl_id);
354                if (!$result = $this->db->queryF($sql)) {
355                    return false;
356                }
357            }
358
359            return true;
360        } else {
361            return false;
362        }
363    }
364
365    /**
366     * delete a block from the database
367     *
368     * @param  XoopsObject|XoopsTplfile $tplfile a XoopsTplfile object
369     *
370     * @return bool true on success, otherwise false
371     */
372    public function delete(XoopsObject $tplfile)
373    {
374        $className = 'XoopsTplfile';
375        if (!($tplfile instanceof $className)) {
376            return false;
377        }
378        $id  = $tplfile->getVar('tpl_id');
379        $sql = sprintf('DELETE FROM %s WHERE tpl_id = %u', $this->db->prefix('tplfile'), $id);
380        if (!$result = $this->db->query($sql)) {
381            return false;
382        }
383        $sql = sprintf('DELETE FROM %s WHERE tpl_id = %u', $this->db->prefix('tplsource'), $id);
384        $this->db->query($sql);
385
386        return true;
387    }
388
389    /**
390     * retrieve array of {@link XoopsBlock}s meeting certain conditions
391     * @param  CriteriaElement|CriteriaCompo $criteria  {@link CriteriaElement} with conditions for the blocks
392     * @param  bool            $getsource
393     * @param  bool            $id_as_key should the blocks' bid be the key for the returned array?
394     * @return array           {@link XoopsBlock}s matching the conditions
395     */
396    public function getObjects(CriteriaElement $criteria = null, $getsource = false, $id_as_key = false)
397    {
398        $ret   = array();
399        $limit = $start = 0;
400        if ($getsource) {
401            $sql = 'SELECT f.*, s.tpl_source FROM ' . $this->db->prefix('tplfile') . ' f LEFT JOIN ' . $this->db->prefix('tplsource') . ' s ON s.tpl_id=f.tpl_id';
402        } else {
403            $sql = 'SELECT * FROM ' . $this->db->prefix('tplfile');
404        }
405        if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
406            $sql .= ' ' . $criteria->renderWhere() . ' ORDER BY tpl_refid';
407            $limit = $criteria->getLimit();
408            $start = $criteria->getStart();
409        }
410        $result = $this->db->query($sql, $limit, $start);
411        if (!$result) {
412            return $ret;
413        }
414        while (false !== ($myrow = $this->db->fetchArray($result))) {
415            $tplfile = new XoopsTplfile();
416            $tplfile->assignVars($myrow);
417            if (!$id_as_key) {
418                $ret[] =& $tplfile;
419            } else {
420                $ret[$myrow['tpl_id']] =& $tplfile;
421            }
422            unset($tplfile);
423        }
424
425        return $ret;
426    }
427
428    /**
429     * Get count
430     *
431     * @param  CriteriaElement|CriteriaCompo $criteria
432     * @return int
433     */
434    public function getCount(CriteriaElement $criteria = null)
435    {
436        $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('tplfile');
437        if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
438            $sql .= ' ' . $criteria->renderWhere();
439        }
440        if (!$result = $this->db->query($sql)) {
441            return 0;
442        }
443        list($count) = $this->db->fetchRow($result);
444
445        return $count;
446    }
447
448    /**
449     * getModuleTplCount
450     *
451     * @param  string $tplset
452     * @return array
453     */
454    public function getModuleTplCount($tplset)
455    {
456        $ret    = array();
457        $sql    = 'SELECT tpl_module, COUNT(tpl_id) AS count FROM ' . $this->db->prefix('tplfile') . " WHERE tpl_tplset='" . $tplset . "' GROUP BY tpl_module";
458        $result = $this->db->query($sql);
459        if (!$result) {
460            return $ret;
461        }
462        while (false !== ($myrow = $this->db->fetchArray($result))) {
463            if ($myrow['tpl_module'] != '') {
464                $ret[$myrow['tpl_module']] = $myrow['count'];
465            }
466        }
467
468        return $ret;
469    }
470
471    /**
472     * Find Template File
473     *
474     * @param  string       $tplset
475     * @param  string|array $type
476     * @param  string       $refid
477     * @param  string       $module
478     * @param  string       $file
479     * @param  bool|string  $getsource
480     * @return object
481     */
482    public function find($tplset = null, $type = null, $refid = null, $module = null, $file = null, $getsource = false)
483    {
484        $criteria = new CriteriaCompo();
485        if (isset($tplset)) {
486            $criteria->add(new Criteria('tpl_tplset', $tplset));
487        }
488        if (isset($module)) {
489            $criteria->add(new Criteria('tpl_module', $module));
490        }
491        if (isset($refid)) {
492            $criteria->add(new Criteria('tpl_refid', $refid));
493        }
494        if (isset($file)) {
495            $criteria->add(new Criteria('tpl_file', $file));
496        }
497        if (isset($type)) {
498            if (is_array($type)) {
499                $criteria2 = new CriteriaCompo();
500                foreach ($type as $t) {
501                    $criteria2->add(new Criteria('tpl_type', $t), 'OR');
502                }
503                $criteria->add($criteria2);
504            } else {
505                $criteria->add(new Criteria('tpl_type', $type));
506            }
507        }
508
509        return $this->getObjects($criteria, $getsource, false);
510    }
511
512    /**
513     * Template Exists
514     *
515     * @param  string $tplname
516     * @param  string $tplset_name
517     * @return bool true if template exists, otherwise false
518     */
519    public function templateExists($tplname, $tplset_name)
520    {
521        $criteria = new CriteriaCompo(new Criteria('tpl_file', trim($tplname)));
522        $criteria->add(new Criteria('tpl_tplset', trim($tplset_name)));
523        return $this->getCount($criteria) > 0;
524    }
525}
526