PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.20
VikAppointments Services Booking Calendar v1.2.20
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / site / helpers / libraries / statistics / widgets / packages / items / count.php
vikappointments / site / helpers / libraries / statistics / widgets / packages / items Last commit date
chart.php 1 month ago count.php 1 month ago index.html 1 month ago
count.php
331 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Widget used to draw a doughnut chart containing the total revenue of each
16 * supported package.
17 *
18 * @since 1.7
19 */
20 class VAPStatisticsWidgetPackagesItemsCount extends VAPStatisticsWidget
21 {
22 /**
23 * Internal flag used to check whether the current user
24 * owns enough permissions to access the financial data.
25 *
26 * Use true by default in case the widget is displayed
27 * without checking the permissions.
28 *
29 * @var boolean
30 */
31 protected $hasFinanceAccess = true;
32
33 /**
34 * Checks whether the specified group is supported by the widget.
35 *
36 * @param string $group The group to check.
37 *
38 * @return boolean True if supported, false otherwise.
39 */
40 public function isSupported($group)
41 {
42 return empty($group) || $group == '*' || $group == 'dashboard' || $group == 'packages';
43 }
44
45 /**
46 * Checks whether the specified user is capable to access this widget.
47 *
48 * @param JUser $user The user instance.
49 *
50 * @return boolean True if capable, false otherwise.
51 */
52 public function checkPermissions($user)
53 {
54 // detected finance visibility
55 $this->hasFinanceAccess = $user->authorise('core.access.analytics.finance', 'com_vikappointments');
56
57 return $user->authorise('core.access.analytics.packages', 'com_vikappointments');
58 }
59
60 /**
61 * Returns to the caller the financial rights of the user.
62 *
63 * @return boolean True if capable, false otherwise.
64 */
65 public function hasFinanceAccess()
66 {
67 return $this->hasFinanceAccess;
68 }
69
70 /**
71 * Override this method to return a configuration form of the widget.
72 *
73 * @return array
74 */
75 public function getForm()
76 {
77 $form = array(
78 /**
79 * The initial date to take when a new session starts.
80 *
81 * @var select
82 */
83 'range' => array(
84 'type' => 'select',
85 'label' => JText::translate('VAP_CHART_INITIAL_RANGE_FIELD'),
86 'help' => JText::translate('VAP_CHART_INITIAL_RANGE_FIELD_HELP'),
87 'default' => '-6 months',
88 'options' => array(
89 'all' => JText::translate('VAPMANAGECONFIGCRON4'),
90 '-1 week' => JText::plural('VAP_LAST_N_WEEKS', 1),
91 '-2 weeks' => JText::plural('VAP_LAST_N_WEEKS', 2),
92 '-1 month' => JText::plural('VAP_LAST_N_MONTHS', 1),
93 '-3 months' => JText::plural('VAP_LAST_N_MONTHS', 3),
94 '-6 months' => JText::plural('VAP_LAST_N_MONTHS', 6),
95 '-9 months' => JText::plural('VAP_LAST_N_MONTHS', 9),
96 '-12 months' => JText::plural('VAP_LAST_N_MONTHS', 12),
97 ),
98 ),
99
100 /**
101 * The initial date of the range.
102 *
103 * The parameter is VOLATILE because, every time the session
104 * ends, we need to restore the field to an empty value, just
105 * to obtain the current date.
106 *
107 * @var date
108 */
109 'datefrom' => array(
110 'type' => 'date',
111 'label' => JText::translate('VAPEXPORTRES3'),
112 'volatile' => true,
113 ),
114
115 /**
116 * The ending date of the range.
117 *
118 * The parameter is VOLATILE because, every time the session
119 * ends, we need to restore the field to an empty value, just
120 * to obtain the current date.
121 *
122 * @var date
123 */
124 'dateto' => array(
125 'type' => 'date',
126 'label' => JText::translate('VAPEXPORTRES4'),
127 'volatile' => true,
128 ),
129
130 /**
131 * The entity of the chart (reservations count or total earning).
132 *
133 * @var select
134 */
135 'valuetype' => array(
136 'type' => 'select',
137 'label' => JText::translate('VAP_CHART_VALUE_TYPE_FIELD'),
138 'help' => JText::translate('VAP_CHART_VALUE_TYPE_FIELD_HELP'),
139 'default' => 'total',
140 'options' => array(
141 'total' => JText::translate('VAPREPORTSVALUETYPEOPT1'),
142 'count' => JText::translate('VAPREPORTSVALUETYPEOPT2'),
143 ),
144 ),
145
146 /**
147 * Select a group to automatically track all the assigned packages.
148 *
149 * @var select
150 */
151 'group' => array(
152 'type' => 'select',
153 'label' => JText::translate('VAPMANAGESERVICE10'),
154 'help' => JText::translate('VAP_STATS_WIDGET_PACKAGES_ITEMS_CHART_GROUP_FIELD_HELP'),
155 'options' => JHtml::fetch('vaphtml.admin.packgroups', $blank = true),
156 ),
157
158 /**
159 * A list of packages to track.
160 *
161 * @var select
162 */
163 'packages' => array(
164 'type' => 'select',
165 'label' => JText::translate('VAPMENUPACKAGES'),
166 'multiple' => true,
167 'options' => JHtml::fetch('vaphtml.admin.packages', $strict = false, $blank = false, $group = true),
168 ),
169 );
170
171 // check whether the user owns enough permissions to see financial data
172 if (!$this->hasFinanceAccess)
173 {
174 // change type to hidden to avoid its selection
175 $form['valuetype']['type'] = 'hidden';
176 // display by default the total number of packages
177 $form['valuetype']['default'] = 'count';
178 }
179
180 $packages = array();
181
182 // ungroup packages and merge them all at the same level
183 foreach ($form['packages']['options'] as $group)
184 {
185 $packages = array_merge($packages, $group);
186 }
187
188 // update options attribute
189 $form['packages']['options'] = $packages;
190
191 // make sure we have a list of groups
192 if (count($form['group']['options']) == 1)
193 {
194 // nope, the list contains only the placeholder, unset parameter
195 unset($form['group']);
196 }
197
198 return $form;
199 }
200
201 /**
202 * Checks whether the widget is able to export the fetched data.
203 *
204 * @return array A list of supported exportable functions.
205 */
206 public function isExportable()
207 {
208 return ['print'];
209 }
210
211 /**
212 * Loads the dataset(s) that will be recovered asynchronously
213 * for being displayed within the widget.
214 *
215 * It is possible to return an array of records to be passed
216 * to a chart or directly the HTML to replace.
217 *
218 * @return mixed
219 */
220 public function getData()
221 {
222 $filters = array();
223 $filters['group'] = $this->getOption('group');
224 $filters['packages'] = array_values(array_filter($this->getOption('packages', [])));
225 $filters['valuetype'] = $this->getOption('valuetype', 'total');
226 $filters['datefrom'] = $this->getOption('datefrom');
227 $filters['dateto'] = $this->getOption('dateto');
228 $filters['range'] = $this->getOption('range', '-6 months');
229
230 if ($filters['group'])
231 {
232 $dbo = JFactory::getDbo();
233
234 // filter specified, take all packages under this group
235 $q = $dbo->getQuery(true)
236 ->select($dbo->qn('id'))
237 ->from($dbo->qn('#__vikappointments_package'))
238 ->where($dbo->qn('id_group') . ' = ' . (int) $filters['group']);
239
240 $dbo->setQuery($q);
241
242 if ($packages = $dbo->loadColumn())
243 {
244 // merge with selected packages
245 $filters['packages'] = array_merge($filters['packages'], $packages);
246 // get rid of duplicates
247 $filters['packages'] = array_values(array_unique($filters['packages']));
248 }
249 }
250
251 if (!$this->hasFinanceAccess)
252 {
253 // always display the total number of packages in case
254 // the user cannot access financial data
255 $filters['valuetype'] = 'count';
256 }
257
258 $tz = JFactory::getUser()->getTimezone();
259
260 // use default range in case both the specified dates are empty
261 if (VAPDateHelper::isNull($filters['datefrom']) && VAPDateHelper::isNull($filters['dateto']))
262 {
263 if ($filters['range'] != 'all')
264 {
265 // create current date by using the timezone of the logged-in user
266 $filters['dateto'] = JFactory::getDate('now', $tz);
267 // set ending date to current one, 1 second before tomorrow
268 $filters['dateto']->modify('23:59:59');
269
270 if (strpos($filters['range'], 'months') !== false)
271 {
272 // set ending date to the end of the month
273 $filters['dateto']->modify($filters['dateto']->format('Y-m-t'));
274 }
275
276 // set starting date to current one at midnight
277 $filters['datefrom'] = clone $filters['dateto'];
278 // go to next day to properly calculate the starting date
279 $filters['datefrom']->modify('tomorrow 00:00:00');
280 // subtract given range
281 $filters['datefrom']->modify($filters['range']);
282 }
283 }
284 else
285 {
286 if (!VAPDateHelper::isNull($filters['datefrom']))
287 {
288 // convert specified dates to SQL format
289 $filters['datefrom'] = JFactory::getDate(VAPDateHelper::getDate($filters['datefrom'], 0, 0, 0), $tz);
290 }
291
292 if (!VAPDateHelper::isNull($filters['dateto']))
293 {
294 // convert specified dates to SQL format
295 $filters['dateto'] = JFactory::getDate(VAPDateHelper::getDate($filters['dateto'], 23, 59, 59), $tz);
296 }
297 }
298
299 // import packages helper
300 VAPLoader::import('libraries.statistics.helpers.packages');
301 // fetch count of packages
302 $data = VAPStatisticsHelperPackages::getItemsCount($filters['datefrom'], $filters['dateto'], $filters['valuetype'], $filters['packages']);
303
304 return $data;
305 }
306
307 /**
308 * Create adapter for export method.
309 * This widget only supports "print" export function.
310 *
311 * @param mixed $rule The requested export type.
312 *
313 * @return void
314 */
315 public function export($rule = null)
316 {
317 // auto-print the document
318 JHtml::fetch('vaphtml.sitescripts.winprint', 256);
319
320 $data = array(
321 // auto-fetch the widget data
322 'data' => $this->getData(),
323 // always display chart legend
324 'legend' => true,
325 );
326
327 // display widget with fetched data
328 echo $this->display($data);
329 }
330 }
331