Dotclear

source: plugins/activityReport/inc/class.activity.report.php @ 1457

Revision 1457, 14.5 KB checked in by JcDenis, 14 years ago (diff)

activityReport 0.2:

  • First lab release
Line 
1<?php
2# -- BEGIN LICENSE BLOCK ----------------------------------
3# This file is part of activityReport, a plugin for Dotclear 2.
4#
5# Copyright (c) 2009 JC Denis and contributors
6# jcdenis@gdwd.com
7#
8# Licensed under the GPL version 2.0 license.
9# A copy of this license is available in LICENSE file or at
10# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
11# -- END LICENSE BLOCK ------------------------------------
12
13if (!defined('DC_RC_PATH')){return;}
14
15class activityReport
16{
17     public $core;
18     public $con;
19
20     public $mailer = 'noreply@dotclearemailactivityreport.dc';
21
22     private $ns = 'activityReport';
23     private $_global = false;
24     private $blog = null;
25     private $table = '';
26     private $groups = array();
27     private $settings = array();
28
29     public function __construct($core,$ns='activityReport')
30     {
31          $this->core =& $core;
32          $this->con = $core->con;
33          $this->table = $core->prefix.'activity';
34          $this->blog = $core->con->escape($core->blog->id);
35          $this->ns = $core->con->escape($ns);
36
37          $this->getSettings();
38     }
39
40     public function setGlobal()
41     {
42          $this->_global = true;
43     }
44
45     public function unsetGlobal()
46     {
47          $this->_global = false;
48     }
49
50     public function getGroups($group=null,$action=null)
51     {
52          if ($action !== null)
53          {
54               return isset($this->groups[$group]['actions'][$action]) ? 
55                    $this->groups[$group]['actions'][$action] : null;
56          }
57          elseif ($group !== null)
58          {
59               return isset($this->groups[$group]) ? 
60                    $this->groups[$group] : null;
61          }
62          else
63          {
64               return $this->groups;
65          }
66     }
67
68     public function addGroup($group,$title)
69     {
70          $this->groups[$group] = array(
71               'title' => $title,
72               'actions'=>array()
73          );
74          return true;
75     }
76
77     public function addAction($group,$action,$title,$msg,$behavior,$function)
78     {
79          if (!isset($this->groups[$group])) return false;
80
81          $this->groups[$group]['actions'][$action] = array(
82               'title' => $title,
83               'msg' => $msg
84          );
85          $this->core->addBehavior($behavior,$function);
86          return true;
87     }
88
89     private function getSettings()
90     {
91          $settings = array();
92
93          $settings['active'] = false;
94          $settings['dashboardItem'] = false;
95          $settings['interval'] = 86400;
96          $settings['lastreport'] = 0;
97          $settings['mailinglist'] = array();
98          $settings['requests'] = array();
99          $settings['blogs'] = array();
100
101          $this->settings = $this->_global_settings = $settings;
102
103          $rs = $this->con->select(
104               'SELECT setting_id, setting_value, blog_id '.
105               'FROM '.$this->table.'_setting '.
106               "WHERE setting_type='".$this->ns."' ".
107               "AND (blog_id='".$this->blog."' OR blog_id IS NULL) ".
108               'ORDER BY setting_id DESC '
109          );
110
111          while($rs->fetch())
112          {
113               $k = $rs->f('setting_id');
114               $v = $rs->f('setting_value');
115               $b = $rs->f('blog_id');
116
117               if (isset($settings[$k]))
118               {
119                    if ($b === null)
120                    {
121                         $this->_global_settings[$k] = self::decode($v);
122                    }
123                    else
124                    {
125                         $this->settings[$k] = self::decode($v);
126                    }
127               }
128          }
129          # Force blog
130          $this->settings['blogs'] = array(1=>$this->blog);
131     }
132
133     public function getSetting($n)
134     {
135          if ($this->_global && isset($this->_global_settings[$n]))
136          {
137               return $this->_global_settings[$n];
138          }
139          elseif (!$this->_global && isset($this->settings[$n]))
140          {
141               return $this->settings[$n];
142          }
143
144          return null;
145     }
146
147     public function setSetting($n,$v)
148     {
149          if ($this->_global && !isset($this->_global_settings[$n])
150          || !$this->_global && !isset($this->settings[$n])) return null;
151
152          $c = $this->delSetting($n);
153
154          $cur = $this->con->openCursor($this->table.'_setting');
155          $this->con->writeLock($this->table.'_setting');
156
157          $cur->blog_id = $this->_global ? null : $this->blog;
158          $cur->setting_id = $this->con->escape($n);
159          $cur->setting_type = $this->ns;
160          $cur->setting_value = (string) self::encode($v);
161
162          $cur->insert();
163          $this->con->unlock();
164
165          if ($this->_global)
166          {
167               $this->_global_settings[$n] = $v;
168          }
169          else
170          {
171               $this->settings[$n] = $v;
172          }
173
174          return true;
175     }
176
177     private function delSetting($n)
178     {
179          return $this->con->execute(
180               'DELETE FROM '.$this->table.'_setting '.
181               "WHERE blog_id".($this->_global ? ' IS NULL' : "='".$this->blog."'").' '.
182               "AND setting_id='".$this->con->escape($n)."' ".
183               "AND setting_type='".$this->ns."' "
184          );
185     }
186
187     # Action params to put in params['sql']
188     public static function requests2params($requests)
189     {
190          $r = array();
191          foreach($requests as $group => $actions)
192          {
193               foreach($actions as $action => $is)
194               {
195                    $r[] = "activity_group='".$group."' AND activity_action='".$action."' ";
196               }
197          }
198          return empty($r) ? '' : 'AND ('.implode('OR ',$r).') ';
199     }
200
201     public function getLogs($p,$count_only=false)
202     {
203          if ($count_only)
204          {
205               $r = 'SELECT count(E.activity_id) ';
206          }
207          else
208          {
209               $content_r = empty($p['no_content']) ? 'activity_logs, ' : '';
210
211               if (!empty($params['columns']) && is_array($params['columns']))
212               {
213                    $content_r .= implode(', ',$params['columns']).', ';
214               }
215               
216               $r =
217               'SELECT E.activity_id, E.blog_id, '.$content_r.
218               'E.activity_group, E.activity_action, E.activity_dt, '.
219               'E.activity_blog_status, E.activity_super_status ';
220          }
221
222          $r .= 'FROM '.$this->table.' E  ';
223         
224          if (!empty($p['from']))
225          {
226               $r .= $p['from'].' ';
227          }
228
229          if ($this->_global)
230          {
231               $r .= "WHERE E.activity_super_status = 0 ";
232          }
233          else
234          {
235               $r .= "WHERE E.activity_blog_status = 0 ";
236          }
237
238          if (!empty($p['activity_type']))
239          {
240               $r .= "AND E.activity_type = '".$this->con->escape($p['activity_type'])."' ";
241          }
242          else
243          {
244               $r .= "AND E.activity_type = '".$this->ns."' ";
245          }
246
247          if (!empty($p['blog_id']))
248          {
249               if(is_array($p['blog_id']))
250               {
251                    $r .= 'AND E.blog_id'.$this->con->in($p['blog_id']);
252               }
253               elseif (!empty($p['blog_id']))
254               {
255                    $r .= "AND E.blog_id = '".$this->con->escape($p['blog_id'])."' ";
256               }
257          }
258          elseif($this->_global)
259          {
260               $r .= 'AND E.blog_id IS NOT NULL ';
261          }
262          else
263          {
264               $r .= "AND E.blog_id='".$this->blog."' ";
265          }
266
267          if (isset($p['activity_group']))
268          {
269               if (is_array($p['activity_group']) && !empty($p['activity_group']))
270               {
271                    $r .= 'AND E.activity_group '.$this->con->in($p['activity_group']);
272               }
273               elseif ($p['activity_group'] != '')
274               {
275                    $r .= "AND E.activity_group = '".$this->con->escape($p['activity_group'])."' ";
276               }
277          }
278
279          if (isset($p['activity_action']))
280          {
281               if (is_array($p['activity_action']) && !empty($p['activity_action']))
282               {
283                    $r .= 'AND E.activity_action '.$this->con->in($p['activity_action']);
284               }
285               elseif ($p['activity_action'] != '')
286               {
287                    $r .= "AND E.activity_action = '".$this->con->escape($p['activity_action'])."' ";
288               }
289          }
290
291          if (isset($p['activity_blog_status']))
292          {
293               $r .= "AND E.activity_blog_status = ".((integer) $p['activity_blog_status'])." ";
294          }
295
296          if (isset($p['activity_super_status']))
297          {
298               $r .= "AND E.activity_super_status = ".((integer) $p['activity_super_status'])." ";
299          }
300
301          if (isset($p['from_date_ts']))
302          {
303               $dt = date('Y-m-d H:i:s',$p['from_date_ts']);
304               $r .= "AND E.activity_dt >= TIMESTAMP '".$dt."' ";
305          }
306          if (isset($p['to_date_ts']))
307          {
308               $dt = date('Y-m-d H:i:s',$p['to_date_ts']);
309               $r .= "AND E.activity_dt < TIMESTAMP '".$dt."' ";
310          }
311
312          if (!empty($p['sql']))
313          {
314               $r .= $p['sql'].' ';
315          }
316
317          if (!$count_only)
318          {
319               if (!empty($p['order']))
320               {
321                    $r .= 'ORDER BY '.$this->con->escape($p['order']).' ';
322               } else {
323                    $r .= 'ORDER BY E.activity_dt DESC ';
324               }
325          }
326
327          if (!$count_only && !empty($p['limit']))
328          {
329               $r .= $this->con->limit($p['limit']);
330          }
331
332          return $this->con->select($r);
333     }
334
335     public function addLog($group,$action,$logs)
336     {
337          try
338          {
339               $cur = $this->con->openCursor($this->table);
340               $this->con->writeLock($this->table);
341
342               $cur->activity_id =      $this->getNextId();
343               $cur->activity_type =    $this->ns;
344               $cur->blog_id =          $this->blog;
345               $cur->activity_group =   $this->con->escape((string) $group);
346               $cur->activity_action = $this->con->escape((string) $action);
347               $cur->activity_logs =    self::encode($logs);
348               $cur->activity_dt =      date('Y-m-d H:i:s');
349
350               $cur->insert();
351               $this->con->unlock();
352          }
353          catch (Exception $e) {
354               $this->con->unlock();
355               $this->core->error->add($e->getMessage());
356          }
357
358          # Test if email report is needed
359          $this->needReport();
360     }
361
362     private function parseLogs($rs)
363     {
364          if ($rs->isEmpty()) return '';
365
366          $from = time();
367          $to = 0;
368          $res = $blog = $group = '';
369
370          while($rs->fetch())
371          {
372               # Blog
373               if ($rs->blog_id != $blog && $this->_global)
374               {
375                    $blog = $rs->blog_id;
376                    $group = '';
377                    $res .= "\n--- ".sprintf(__('On blog "%s"'),$blog)." ---\n";
378               }
379
380               # Type
381               if ($rs->activity_group != $group)
382               {
383                    $group = $rs->activity_group;
384                    $res .= "\n-- ".__($this->groups[$group]['title'])." --\n\n";
385               }
386
387               # Action
388               $data = self::decode($rs->activity_logs);
389
390               $res .= 
391               '- '.$rs->activity_dt.' : '.
392               vsprintf(
393                    __($this->groups[$group]['actions'][$rs->activity_action]['msg']),$data
394               )."\n";
395
396               # Period
397               if (strtotime($rs->activity_dt) < $from)
398               {
399                    $from = strtotime($rs->activity_dt);
400               }
401               if (strtotime($rs->activity_dt) > $to)
402               {
403                    $to = strtotime($rs->activity_dt);
404               }
405          }
406
407          # Top of msg
408          if (!empty($res))
409          {
410               if ($this->_global)
411               {
412                    $period = sprintf(
413                         __('Period: from %s to %s'),
414                         dt::str('%Y-%m-%d %H:%M:%S',$from),
415                         dt::str('%Y-%m-%d %H:%M:%S',$to)
416                    )."\n";
417               }
418               else
419               {
420                    $period = 
421                    sprintf(__('Blog: %s'),$this->core->blog->name)."\n".
422                    sprintf(__('Website: %s'),$this->core->blog->url)."\n".
423                    sprintf(
424                         __('Period: from %s to %s'),
425                         dt::str('%Y-%m-%d %H:%M:%S',
426                              $from,
427                              $core->blog->settings->blog_timezone
428                         ),
429                         dt::str(
430                              '%Y-%m-%d %H:%M:%S',
431                              $to,
432                              $core->blog->settings->blog_timezone
433                         )
434                    )."\n";
435               }
436               $res = $period.
437               "\n-----------------------------------------------------------\n".
438               $res;
439          }
440          return $res;
441     }
442
443     private function cleanLogs()
444     {
445          $this->con->execute(
446               'DELETE FROM '.$this->table.' '.
447               "WHERE activity_type='".$this->ns."' ".
448               "AND activity_blog_status = 1 ".
449               "AND activity_super_status = 1 "
450          );
451     }
452
453     public function deleteLogs()
454     {
455          if (!$this->core->auth->isSuperAdmin()) return;
456
457          return $this->con->execute(
458               'DELETE FROM '.$this->table.' '.
459               "WHERE activity_type='".$this->ns."' "
460          );
461     }
462
463     private function updateStatus($from_date_ts,$to_date_ts)
464     {
465          $r = 
466          'UPDATE '.$this->table.' ';
467
468          if ($this->_global)
469          {
470               $r .= 
471               "SET activity_super_status = 1 WHERE blog_id IS NOT NULL ";
472          }
473          else
474          {
475               $r .= 
476               "SET activity_blog_status = 1 WHERE blog_id = '".$this->blog."' ";
477          }
478
479          $r .=
480          "AND activity_type = '".$this->ns."' ".
481          "AND activity_dt >= TIMESTAMP '".date('Y-m-d H:i:s',$from_date_ts)."' ".
482          "AND activity_dt < TIMESTAMP '".date('Y-m-d H:i:s',$to_date_ts)."' ";
483
484          $this->con->execute($r);
485     }
486
487     public function getNextId()
488     {
489          return $this->con->select(
490               'SELECT MAX(activity_id) FROM '.$this->table
491          )->f(0) + 1;
492     }
493
494     public function needReport($force=false)
495     {
496          $now = time();
497
498          if ($this->_global)
499          {
500               $active = (boolean) $this->_global_settings['active'];
501               $mailinglist = $this->_global_settings['mailinglist'];
502               $requests = $this->_global_settings['requests'];
503               $lastreport = (integer) $this->_global_settings['lastreport'];
504               $interval = (integer) $this->_global_settings['interval'];
505               $blogs = $this->_global_settings['blogs'];
506          }
507          else
508          {
509               $active = (boolean) $this->settings['active'];
510               $mailinglist = $this->settings['mailinglist'];
511               $requests = $this->settings['requests'];
512               $lastreport = (integer) $this->settings['lastreport'];
513               $interval = (integer) $this->settings['interval'];
514               $blogs = $this->blog; // force local blog
515          }
516
517          if ($force)
518          {
519               $lastreport = 0;
520          }
521
522          # Check if report is needed
523          if ($active && !empty($mailinglist) && !empty($requests) && !empty($blogs) 
524          && ($lastreport + $interval) < $now )
525          {
526               # Get datas
527               $params = array();
528               $params['from_date_ts'] = $lastreport;
529               $params['to_date_ts'] = $now;
530               $params['blog_id'] = $blogs;
531               $params['sql'] = self::requests2params($requests);
532               $params['order'] = 'blog_id ASC, activity_group ASC, activity_action ASC ';
533
534               $send = false;
535               $logs = $this->getLogs($params);
536               if (!$logs->isEmpty())
537               {
538                    # Datas to readable text
539                    $content = $this->parseLogs($logs);
540                    if (!empty($content))
541                    {
542                         # Send mails
543                         $send = $this->sendReport($mailinglist,$content);
544                    }
545               }
546
547               # Update db
548               if ($send || $this->_global) // if global : delete all blog logs even if not selected
549               {
550                    # Update log status
551                    $this->updateStatus($lastreport,$now);
552                    # Delete old logs
553                    $this->cleanLogs();
554                    # Then set update time
555                    $this->setSetting('lastreport',$now);
556               }
557          }
558
559          # If this is on a blog, we need to test superAdmin report
560          if (!$this->_global)
561          {
562               $this->_global = true;
563               $this->needReport();
564               $this->_global = false;
565          }
566
567          return true;
568     }
569
570     private function sendReport($recipients,$content)
571     {
572          if (!is_array($recipients) || empty($content) || !text::isEmail($this->mailer)) return;
573
574          # Checks recipients addresses
575          $rc2 = array();
576          foreach ($recipients as $v)
577          {
578               $v = trim($v);
579               if (!empty($v) && text::isEmail($v))
580               {
581                    $rc2[] = $v;
582               }
583          }
584          $recipients = $rc2;
585          unset($rc2);
586
587          if (empty($recipients)) return;
588
589          # Sending mail
590          $headers = array(
591               'From: '.mail::B64Header(__('Activity report module')).' <'.$this->mailer.'>',
592               'Content-Type: text/plain; charset=UTF-8;',
593               'X-Originating-IP: '.http::realIP(),
594               'X-Mailer: Dotclear',
595               'X-Blog-Id: '.mail::B64Header($this->core->blog->id),
596               'X-Blog-Name: '.mail::B64Header($this->core->blog->name),
597               'X-Blog-Url: '.mail::B64Header($this->core->blog->url)
598          );
599
600          $subject = mail::B64Header(__('Blog activity report'));
601
602          $msg = 
603          __("You received a message from your blog's activity report module.").
604          "\n\n".$content."\n\n";
605
606          foreach ($recipients as $email)
607          {
608               try
609               {
610                    mail::sendMail($email,$subject,$msg,$headers);
611                    return true;
612               }
613               catch (Exception $e) {
614                    // don't break other codes leave it silently
615                    //$core->error->add(__('Failed to send email notification'));
616                    return false;
617               }
618          }
619     }
620
621     public static function encode($a)
622     {
623          return base64_encode(serialize($a));
624     }
625
626     public static function decode($a)
627     {
628          return unserialize(base64_decode($a));
629     }
630}
631?>
Note: See TracBrowser for help on using the repository browser.

Sites map