PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
← All changes | admin/models/shortcode.php +407 -0 1.6.3 → 1.8.16 View file →
@@ -1,0 +1,407 @@
1 +<?php
2 +/**
3 + * @package VikBooking
4 + * @subpackage com_vikbooking
5 + * @author E4J srl
6 + * @copyright Copyright (C) e4j - Extensionsforjoomla.com. All rights reserved.
7 + * @license GNU General Public License version 2 or later; see LICENSE
8 + * @link https://vikwp.com
9 + */
10 +
11 +// No direct access
12 +defined('ABSPATH') or die('No script kiddies please!');
13 +
14 +JLoader::import('adapter.mvc.models.form');
15 +
16 +/**
17 + * VikBooking plugin Shortcode model.
18 + *
19 + * @since 1.0
20 + * @see JModelForm
21 + */
22 +class VikBookingModelShortcode extends JModelForm
23 +{
24 + /**
25 + * @override
26 + * This method should be used to pre-load an item considering
27 + * the data set in the request.
28 + *
29 + * For example, if the request owns an ID, this method may try
30 + * to retrieve the item from the database.
31 + * Otherwise it may return an empty object.
32 + *
33 + * @return object The object found.
34 + */
35 + public function loadFormData()
36 + {
37 + $input = JFactory::getApplication()->input;
38 +
39 + $id = $input->getUint('cid', array(0));
40 +
41 + return $this->getItem(array_shift($id));
42 + }
43 +
44 + /**
45 + * This method should be used to retrieve the posted data
46 + * after the form submission.
47 + *
48 + * @return object The data object.
49 + */
50 + public function getFormData()
51 + {
52 + $input = JFactory::getApplication()->input;
53 +
54 + // get data from request
55 + $data = new stdClass;
56 +
57 + $data->id = $input->getInt('id', 0);
58 + $data->title = '';
59 + $data->name = $input->getString('name');
60 + $data->type = $input->getString('type');
61 + $data->lang = $input->getString('lang');
62 + $data->parent_id = $input->getUint('parent_id', 0);
63 + $data->json = array();
64 + $data->shortcode = '';
65 +
66 + // only if we are creating the shortcode, set the creation date and user
67 + if ($data->id <= 0)
68 + {
69 + $data->createdby = JFactory::getUser()->id;
70 + $data->createdon = JFactory::getDate()->toSql();
71 + }
72 +
73 + // get layout path
74 + $path = implode(DIRECTORY_SEPARATOR, array(VBO_SITE_PATH, 'views', $data->type, 'tmpl', 'default.xml'));
75 +
76 + // if the file doesn't exist, raise an exception
77 + if (!is_file($path))
78 + {
79 + throw new Exception("Missing XML [{$data->type}] view type.", 404);
80 + }
81 +
82 + // load XML form
83 + $form = JForm::getInstance($data->type, $path);
84 +
85 + // obtain view title
86 + $data->title = (string) $form->getXml()->layout->attributes()->title;
87 +
88 + // get form data
89 + $formData = $input->get('jform', [], 'array');
90 +
91 + // get input filter
92 + $inputFilter = JInputFilter::getInstance();
93 +
94 + // iterate the layout fields
95 + foreach ($form->getFields() as $field)
96 + {
97 + $attrs = $field->attributes();
98 +
99 + $name = (string) $attrs->name;
100 + $filter = (string) $attrs->filter;
101 + $req = (string) $attrs->required;
102 +
103 + // use string if no filter
104 + if (empty($filter))
105 + {
106 + $filter = 'string';
107 + }
108 +
109 + if (isset($formData[$name]))
110 + {
111 + // clean filter in request
112 + $value = $inputFilter->clean($formData[$name], $filter);
113 + }
114 + else
115 + {
116 + // use NULL
117 + $value = null;
118 + }
119 +
120 + // raise an exception if a mandatory field is empty
121 + if (empty($value) && $req == 'true')
122 + {
123 + throw new Exception("Missing required [$name] field.", 400);
124 + }
125 +
126 + // save value only if not NULL
127 + if ($value !== null)
128 + {
129 + $data->json[$name] = $value;
130 + }
131 + }
132 +
133 + $viewData = array();
134 + $viewData['view'] = $data->type;
135 + $viewData['lang'] = $data->lang;
136 +
137 + // merge VIEW name and LANG TAG with JSON params
138 + $args = array_merge($data->json, $viewData);
139 + // generate shortcode string
140 + $data->shortcode = JFilterOutput::shortcode('vikbooking', $args);
141 +
142 + // finally encode the params in JSON
143 + $data->json = json_encode($data->json);
144 +
145 + return $data;
146 + }
147 +
148 + /**
149 + * @override
150 + * Retrieves the specified item.
151 + *
152 + * @param mixed $pk The primary key value or a list of keys.
153 + * @param boolean $create True to create an empty object.
154 + *
155 + * @return object The item found if exists, otherwise an empty object.
156 + */
157 + public function getItem($pk, $create = true)
158 + {
159 + $item = parent::getItem($pk, $create);
160 +
161 + if ($item && !$item->id)
162 + {
163 + $item->name = '';
164 + $item->type = '';
165 + $item->json = '{}';
166 + }
167 +
168 + return $item;
169 + }
170 +
171 + /**
172 + * @override
173 + * Creates or updates the specified record.
174 + *
175 + * @param object &$data The record to insert.
176 + *
177 + * @return mixed The ID of the inserted record on success, false otherwise.
178 + */
179 + public function save(&$data)
180 + {
181 + // get old item to get previous shortcode
182 + $old = ($data->id ?? 0) ? $this->getItem($data->id) : null;
183 +
184 + // save shortcode
185 + $res = parent::save($data);
186 +
187 + if ($res && $old)
188 + {
189 + // get saved item to access post ID property
190 + $item = $this->getItem($data->id);
191 +
192 + /**
193 + * Get the post object.
194 + * Obtain post only in case the shortcode is assigned
195 + * to a real ID, otherwise get_post() could retrieve
196 + * the last post used.
197 + *
198 + * @since 1.2.7
199 + */
200 + $post = $item->post_id ? get_post($item->post_id) : null;
201 +
202 + /**
203 + * Proceed only in case the post exists.
204 + *
205 + * @since 1.1.7
206 + */
207 + if ($post)
208 + {
209 + /**
210 + * Do not proceed in case the post already contains the shortcode.
211 + * Otherwise we would fall in a loop as wp_update_post() triggers
212 + * the action that invoked the current method.
213 + *
214 + * @see vikbooking.php @ action:save_post
215 + *
216 + * @since 1.0.17
217 + */
218 + if (strpos($post->post_content, $item->shortcode) === false)
219 + {
220 + // replace old shortcode with the new one from the post contents
221 + $post->post_content = str_replace($old->shortcode, $item->shortcode, $post->post_content);
222 +
223 + // finalize the update
224 + wp_update_post($post);
225 + }
226 + }
227 + }
228 +
229 + return $res;
230 + }
231 +
232 + /**
233 + * Obtains the JForm object related to the model view.
234 + *
235 + * @param object $item The data to bind.
236 + *
237 + * @return JForm The form object.
238 + */
239 + public function getTypeForm($item)
240 + {
241 + $item = (object) $item;
242 +
243 + if (!$item->type)
244 + {
245 + return null;
246 + }
247 +
248 + // inject custom vars to access the layout
249 + // file of a site view (change model name and client)
250 + $this->_name = $item->type;
251 + $this->_client = 'site';
252 +
253 + // get the form
254 + $form = parent::getForm();
255 +
256 + $form->setFormControl('jform');
257 +
258 + // reset the vars (it will be taken later if needed)
259 + $this->_name = null;
260 + $this->_client = null;
261 +
262 + return $form;
263 + }
264 +
265 + /**
266 + * Retrieves the IDs of the ancestors of a shortcode.
267 + *
268 + * @param mixed $shortcode Either a shortcode ID or an object.
269 + *
270 + * @return array Array of ancestor IDs or empty array if there are none.
271 + *
272 + * @since 1.5
273 + */
274 + public function getAncestors($shortcode)
275 + {
276 + if (is_array($shortcode))
277 + {
278 + // treat associative array as object
279 + $shortcode = (object) $shortcode;
280 + }
281 + else if (!is_object($shortcode))
282 + {
283 + // fetch shortcode details from ID
284 + $shortcode = $this->getItem($shortcode);
285 + }
286 +
287 + $ancestors = [];
288 +
289 + if (!$shortcode || empty($shortcode->parent_id) || $shortcode->parent_id == $shortcode->id)
290 + {
291 + return $ancestors;
292 + }
293 +
294 + $id = $shortcode->parent_id;
295 + $ancestors[] = $id;
296 +
297 + while ($ancestor = $this->getItem($id))
298 + {
299 + // Loop detection: If the ancestor has been seen before, break
300 + if (empty($ancestor->parent_id) || ($ancestor->parent_id == $shortcode->id ) || in_array($ancestor->parent_id, $ancestors, true))
301 + {
302 + break;
303 + }
304 +
305 + $id = $ancestor->parent_id;
306 + $ancestors[] = $id;
307 + }
308 +
309 + return $ancestors;
310 + }
311 +
312 + /**
313 + * Creates a page on WordPress with for each requested shortcode.
314 + * This is useful to automatically link Shortcodes in pages with no manual actions.
315 + *
316 + * @param mixed $ids Either an array or a shortcode ID.
317 + *
318 + * @return boolean True on success, false otherwise.
319 + *
320 + * @since 1.5
321 + */
322 + public function addPage($ids)
323 + {
324 + $ids = (array) $ids;
325 +
326 + $success = false;
327 +
328 + foreach ($ids as $id)
329 + {
330 + // get shortcode record
331 + $item = $this->getItem($id);
332 +
333 + if (empty($item->id))
334 + {
335 + // missing shortcode
336 + $this->setError(sprintf('Shortcode [%d] not found', $id));
337 +
338 + continue;
339 + }
340 +
341 + // make sure the shortcode hasn't been assigned to any pages
342 + if (empty($item->post_id))
343 + {
344 + $post_parent = 0;
345 +
346 + if ($item->parent_id)
347 + {
348 + // get parent shortcode
349 + $parent = $this->getItem($item->parent_id);
350 +
351 + if ($parent && $parent->post_id)
352 + {
353 + // in case the parent shortcode is assigned to a post, use it as parent
354 + $post_parent = $parent->post_id;
355 + }
356 + }
357 +
358 + // Add a new page (we allow a WP_ERROR to be thrown in case of failure).
359 + // This should automatically trigger the hook that we use to link the shortcode
360 + // to the new page/post ID, and so there's no need to update the item.
361 + $post_id = wp_insert_post(array(
362 + 'post_title' => (!empty($item->name) ? $item->name : JText::translate($item->title)),
363 + 'post_content' => $item->shortcode,
364 + 'post_status' => 'publish',
365 + 'post_type' => 'page',
366 + 'post_parent' => $post_parent,
367 + ), $wp_error = false, $fire_after_hooks = true);
368 +
369 + // check if we received an error
370 + if ($post_id instanceof WP_Error)
371 + {
372 + // propagate error message
373 + $this->setError($post_id);
374 +
375 + continue;
376 + }
377 +
378 + // check whether the page has been created
379 + $success = $success || (is_int($post_id) && $post_id > 0);
380 + }
381 + }
382 +
383 + return $success;
384 + }
385 +
386 + /**
387 + * Method to get a table object.
388 + *
389 + * @param string $name The table name.
390 + * @param string $prefix The class prefix.
391 + * @param array $options Configuration array for table.
392 + *
393 + * @return JTable A table object.
394 + *
395 + * @since 1.4.7
396 + */
397 + public function getTable($name = '', $prefix = 'JTable', $options = array())
398 + {
399 + if (!$name)
400 + {
401 + $name = 'shortcode';
402 + $prefix = 'VBOTable';
403 + }
404 +
405 + return parent::getTable($name, $prefix, $options);
406 + }
407 +}