Dotclear

source: plugins/pollsFactory/inc/class.pollsfactory.chart.php @ 2139

Revision 2139, 8.0 KB checked in by JcDenis, 14 years ago (diff)

pollsFactory 1.0:

  • Rewrited plugin
Line 
1<?php
2# -- BEGIN LICENSE BLOCK ----------------------------------
3# This file is part of pollsFactory, a plugin for Dotclear 2.
4#
5# Copyright (c) 2009-2010 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 pollsFactoryChart
16{
17     public $core;
18     public $factory;
19     protected $cache_dir;
20     protected $prop;
21     protected $trigger;
22     public $cache_folder = 'polls';
23
24     public $api_url = 'http://chart.apis.google.com/chart';
25     
26     public function __construct($core)
27     {
28          $this->core = $core;
29          $this->factory = new pollsFactory($core);
30          # Cache directory
31          $this->cache_dir = path::real(DC_TPL_CACHE);
32          $use_cache = (boolean) $core->blog->settings->pollsFactory_graph_cache;
33          if (!$use_cache || !is_dir($this->cache_dir) || !is_writable($this->cache_dir)) {
34               $this->cache_dir = null;
35          }
36          # Image properties
37          $this->prop = @unserialize($core->blog->settings->pollsFactory_graph_options);
38          if (!is_array($this->prop) || empty($this->prop)){
39               $this->prop = self::defaultOptions();
40          } else {
41               self::cleanOptions($this->prop);
42          }
43          # Last update
44          $this->trigger = (integer) $core->blog->settings->pollsFactory_graph_trigger;
45     }
46
47     public static function defaultOptions()
48     {
49          return array(
50               'width' => '400',
51               'ttcolor' => '#000000',
52               'txcolor' => '#000000',
53               'bgcolor' => '#FFFFFF',
54               'chcolor' => '#F8F8F8',
55               'barcolor' => '#48D9F9'
56          );
57     }
58
59     public static function cleanOptions(&$prop)
60     {
61               $prop['width'] = isset($prop['width']) ? self::size($prop['width'],'400') : '400';
62               $prop['ttcolor'] = isset($prop['ttcolor']) ? self::color($prop['ttcolor'],'000000') : '000000';
63               $prop['txcolor'] = isset($prop['txcolor']) ? self::color($prop['txcolor'],'000000') : '000000';
64               $prop['bgcolor'] = isset($prop['bgcolor']) ? self::color($prop['bgcolor'],'FFFFFF') : 'FFFFFF';
65               $prop['chcolor'] = isset($prop['chcolor']) ? self::color($prop['chcolor'],'F8F8F8') : 'F8F8F8';
66               $prop['barcolor'] = isset($prop['barcolor']) ? self::color($prop['barcolor'],'4D89F9') : '4D89F9';
67     }
68
69     public function serveChart($poll_id,$query_id,$http_cache=true,$http_etag=true)
70     {
71          $poll_id = (integer) $poll_id;
72          $query_id = (integer) $query_id;
73          $now = $ts = time();
74
75          # Prepare file path
76          $file_md5 = md5($this->core->blog->id.$poll_id.$query_id);
77          $file_path = sprintf('%s/%s/%s/%s/%s.png',
78               $this->cache_dir,
79               $this->cache_folder,
80               substr($file_md5,0,2),
81               substr($file_md5,2,2),
82               $file_md5
83          );
84          # File modify time
85          clearstatcache();
86          $file_time = false;
87          if (file_exists($file_path)) {
88               $file_time = filemtime($file_path);
89               $ts = $file_time;
90          }
91          # Last admin update time
92          $trig_time = $this->trigger;
93          # Last vote time
94          $updt_params['option_type'] = 'pollsresponse';
95          $updt_params['limit'] = 1;
96          $updt_params['order'] = 'option_upddt DESC ';
97          $updt_params['post_id'] = $poll_id;
98          $updt = $this->factory->getOptions($updt_params);
99          $updt_time = $updt->isEmpty() ? 0 : strtotime($updt->option_upddt);
100
101          # Check if need update
102          if (!$file_time || $file_time < $trig_time || $file_time < $updt_time)
103          {
104               $ts = $now;
105               $content = $this->sendRequest($poll_id,$query_id);
106
107               # Use cache
108               if ($this->cache_dir !== null)
109               {
110                    files::makeDir(dirname($file_path),true);
111                   
112                    if (($fp = @fopen($file_path,'wb')) === false) {
113                         //throw new Exception('Unable to create cache file');
114                    }
115                    else {
116                         fwrite($fp,$content);
117                         fclose($fp);
118                         files::inheritChmod($file_path);
119                    }
120               }
121          }
122          else {
123               $content = file_get_contents($file_path);
124          }
125          # Parse content
126          if (!empty($content)) {
127               http::head(200,'OK');
128               header('Last-Modified: '.gmdate('D, d M Y H:i:s',$ts).' GMT');
129               header('Cache-Control: must-revalidate, max-age=7200');
130               header('Pragma:');
131               header('Date: '.gmdate('D, d M Y H:i:s',$now).' GMT');
132               header('Content-Type: image/png;');
133               echo $content;
134          }
135          # Error occured
136          else {
137               http::head(404,'Not Found');
138               header('Content-Type: text/plain;');
139               echo 'file not found';
140          }
141          exit(1);
142     }
143
144     public function sendRequest($poll_id,$query_id)
145     {
146          $poll_id = (integer) $poll_id;
147          $query_id = (integer) $query_id;
148         
149          # Get query infos
150          $query_params['option_type'] = 'pollsquery';
151          $query_params['post_id'] = $poll_id;
152          $query_params['option_id'] = $query_id;
153          $query = $this->factory->getOptions($query_params);
154          if ($query->isEmpty()) {
155               return false;
156          }
157
158          # Get responses to this query
159          $responses_params['option_type'] = 'pollsresponse';
160          $responses_params['post_id'] = $poll_id;
161          $responses_params['option_meta'] = $query_id;
162          $responses = $this->factory->getOptions($responses_params);
163          if ($responses->isEmpty()) {
164               return false;
165          }
166
167          $chd = $chxl = array();
168          $max = 0;
169          # Loop through responses and count results
170          while($responses->fetch())
171          {
172               $key = (integer) $responses->option_content;
173
174               # Bar width (values)
175               if (!isset($chd[$key])) {
176                    $chd[$key] = 0;
177               }
178               $chd[$key] += 1;
179               # Set maximal value
180               if ($max < $chd[$key]) {
181                    $max = $chd[$key];
182               }
183          }
184          # Lopp through options
185          $selections_params['option_type'] = 'pollsselection';
186          $selections_params['post_id'] = $poll_id;
187          $selections_params['option_meta'] = $query_id;
188          $selections = $this->factory->getOptions($selections_params);
189          while($selections->fetch())
190          {
191               $key = (integer) $selections->option_id;
192               # Set bars with no responses
193               $opt[$key] = $selections->option_title;
194               if (!isset($chd[$key])) {
195                    $chd[$key] = 0;
196               }
197               # Bar title
198               $chxl[$key] = $selections->option_title;
199          }
200          # go go go
201          $data = array();
202          $data['chd'] = 't:'.implode(',',$chd); // Bar values
203          $data['chxt'] = 'x,y'; // Show axis
204          $data['chxl'] = '1:|'.implode('|',$chxl); // Axis labels
205          $data['chxs'] = '0,'.$this->prop['txcolor'].'|1,'.$this->prop['txcolor'];
206          $data['chds'] = '0,'.$max; // Scale of max value
207          $data['chm'] = 'N*,'.$this->prop['txcolor'].',0,-1,11'; // Bars labels
208          $data['chs'] = $this->prop['width'].'x'.(count($chd) * 22 + 50); // Size = width x height(num_bar * bar_width + title_width)
209          $data['chbh'] = '20,2'; // Bar width and space
210          $data['chtt'] = $query->option_title; // Title = query_title
211          $data['chts'] = $this->prop['ttcolor'].',12'; // title size and color
212          $data['cht'] = 'bhs'; // Type = Horizontal bar charts
213          $data['chco'] = $this->prop['barcolor']; // Bar Color = #4D89F9
214          $data['chf'] = 'c,s,'.$this->prop['chcolor'].'|bg,s,'.$this->prop['bgcolor']; // Chart color and background color;
215
216          return $this->send($this->api_url,$data);
217     }
218
219     private static function send($url,$data)
220     {
221          try  {
222               $path = '';
223               $client = netHttp::initClient($url,$path);
224               $client->setUserAgent('pollsFactory - http://dotclear.jcdenis.com/go/pollsFactory');
225               $client->useGzip(false);
226               $client->setPersistReferers(false);
227               $client->post($url,$data);
228
229               $response = $client->getContent();
230          }
231          catch (Exception $e) {
232               throw new Exception('Failed to send request: '.$e->getMessage());
233          }
234          if ($client->getStatus() != 200) {
235               throw new Exception('Failed to get content: '.$client->getContent());
236               return false;
237          }
238          else {
239               return $response;
240          }
241     }
242
243     public static function size($s,$default=350)
244     {
245          return preg_match('/^([0-9]+)$/',$s) ? $s : $default;
246     }
247
248     public static function color($c,$default='CCCCCC')
249     {
250          if ($c === '') {
251               return $default;
252          }
253          $c = strtoupper($c);
254
255          if (preg_match('/^[A-F0-9]{6}$/',$c)) {
256               return $c;
257          }
258          if (preg_match('/^[A-F0-9]{3}$/',$c)) {
259               $e = explode('',$c);
260               return $e[0].$e[0].$e[1].$e[1].$e[2].$e[2];
261          }
262          if (preg_match('/^#[A-F0-9]{6}$/',$c)) {
263               return substr($c,1);
264          }
265          if (preg_match('/^#[A-F0-9]{3}$/',$c)) {
266               $e = explode('',$c);
267               return $e[1].$e[1].$e[2].$e[2].$e[3].$e[3];
268          }
269          return $default;
270     }
271}
272?>
Note: See TracBrowser for help on using the repository browser.

Sites map