1+ <?php
2+ // +----------------------------------------------------------------------+
3+ // | Anuko Time Tracker
4+ // +----------------------------------------------------------------------+
5+ // | Copyright (c) Anuko International Ltd. (https://www.anuko.com)
6+ // +----------------------------------------------------------------------+
7+ // | LIBERAL FREEWARE LICENSE: This source code document may be used
8+ // | by anyone for any purpose, and freely redistributed alone or in
9+ // | combination with other software, provided that the license is obeyed.
10+ // |
11+ // | There are only two ways to violate the license:
12+ // |
13+ // | 1. To redistribute this code in source form, with the copyright
14+ // | notice or license removed or altered. (Distributing in compiled
15+ // | forms without embedded copyright notices is permitted).
16+ // |
17+ // | 2. To redistribute modified versions of this code in *any* form
18+ // | that bears insufficient indications that the modifications are
19+ // | not the work of the original author(s).
20+ // |
21+ // | This license applies to this document only, not any other software
22+ // | that it may be combined with.
23+ // |
24+ // +----------------------------------------------------------------------+
25+ // | Contributors:
26+ // | https://www.anuko.com/time_tracker/credits.htm
27+ // +----------------------------------------------------------------------+
28+
29+ // Note: This script uses Lichart PHP library and requires GD 2.0.1 or later.
30+
31+ require_once ('initialize.php ' );
32+ import ('form.Form ' );
33+ import ('DateAndTime ' );
34+ import ('ttChartHelper ' );
35+ import ('ttSysConfig ' );
36+ import ('PieChartEx ' );
37+ import ('ttUserHelper ' );
38+ import ('ttTeamHelper ' );
39+
40+ // Access check.
41+ if (!ttAccessCheck (right_view_charts)) {
42+ header ('Location: access_denied.php ' );
43+ exit ();
44+ }
45+
46+ // Initialize and store date in session.
47+ $ cl_date = $ request ->getParameter ('date ' , @$ _SESSION ['date ' ]);
48+ if (!$ cl_date ) {
49+ $ now = new DateAndTime (DB_DATEFORMAT );
50+ $ cl_date = $ now ->toString (DB_DATEFORMAT );
51+ }
52+ $ _SESSION ['date ' ] = $ cl_date ;
53+
54+ // Initialize chart interval.
55+ $ cl_interval = $ _SESSION ['chart_interval ' ];
56+ if (!$ cl_interval ) {
57+ $ sc = new ttSysConfig ($ user ->id );
58+ $ cl_interval = $ sc ->getValue (SYSC_CHART_INTERVAL );
59+ }
60+ if (!$ cl_interval ) $ cl_interval = INTERVAL_THIS_MONTH ;
61+ $ _SESSION ['chart_interval ' ] = $ cl_interval ;
62+
63+ // Initialize chart type.
64+ $ cl_type = $ _SESSION ['chart_type ' ];
65+ if (!$ cl_type ) {
66+ $ sc = new ttSysConfig ($ user ->id );
67+ $ cl_type = $ sc ->getValue (SYSC_CHART_TYPE );
68+ }
69+ if (MODE_TIME == $ user ->tracking_mode ) {
70+ if (in_array ('cl ' , explode (', ' , $ user ->plugins )))
71+ $ cl_type = CHART_CLIENTS ;
72+ } else {
73+ if ($ cl_type == CHART_CLIENTS ) {
74+ if (!in_array ('cl ' , explode (', ' , $ user ->plugins )))
75+ $ cl_type = CHART_PROJECTS ;
76+ } else if ($ cl_type == CHART_TASKS ) {
77+ if (MODE_PROJECTS_AND_TASKS != $ user ->tracking_mode )
78+ $ cl_type = CHART_PROJECTS ;
79+ }
80+ }
81+ if (!$ cl_type ) $ cl_type = CHART_PROJECTS ;
82+ $ _SESSION ['chart_type ' ] = $ cl_type ;
83+
84+ // Who do we draw charts for?
85+ $ on_behalf_id = $ request ->getParameter ('onBehalfUser ' , (isset ($ _SESSION ['behalf_id ' ])? $ _SESSION ['behalf_id ' ] : $ user ->id ));
86+
87+ if ($ request ->getMethod ( )== 'POST ' ) {
88+ // If chart interval changed - save it.
89+ $ cl_interval = $ request ->getParameter ('interval ' );
90+ if ($ cl_interval ) {
91+ // Save in the session
92+ $ _SESSION ['chart_interval ' ] = $ cl_interval ;
93+ // and permanently.
94+ $ sc = new ttSysConfig ($ user ->id );
95+ $ sc ->setValue (SYSC_CHART_INTERVAL , $ cl_interval );
96+ }
97+ // If chart type changed - save it.
98+ $ cl_type = $ request ->getParameter ('type ' );
99+ if ($ cl_type ) {
100+ // Save in the session
101+ $ _SESSION ['chart_type ' ] = $ cl_type ;
102+ // and permanently.
103+ $ sc = new ttSysConfig ($ user ->id );
104+ $ sc ->setValue (SYSC_CHART_TYPE , $ cl_type );
105+ }
106+ // If user has changed - set behalf_id accordingly in the session.
107+ if ($ request ->getParameter ('onBehalfUser ' )) {
108+ if ($ user ->canManageTeam ()) {
109+ unset($ _SESSION ['behalf_id ' ]);
110+ unset($ _SESSION ['behalf_name ' ]);
111+
112+ if ($ on_behalf_id != $ user ->id ) {
113+ $ _SESSION ['behalf_id ' ] = $ on_behalf_id ;
114+ $ _SESSION ['behalf_name ' ] = ttUserHelper::getUserName ($ on_behalf_id );
115+ }
116+ header ('Location: charts.php ' );
117+ exit ();
118+ }
119+ }
120+ }
121+
122+ // Elements of chartForm.
123+ $ chart_form = new Form ('chartForm ' );
124+
125+ // User dropdown. Changes the user "on behalf" of whom we are working.
126+ if ($ user ->canManageTeam ()) {
127+ $ user_list = ttTeamHelper::getActiveUsers (array ('putSelfFirst ' =>true ));
128+ if (count ($ user_list ) > 1 ) {
129+ $ chart_form ->addInput (array ('type ' =>'combobox ' ,
130+ 'onchange ' =>'this.form.submit(); ' ,
131+ 'name ' =>'onBehalfUser ' ,
132+ 'value ' =>$ on_behalf_id ,
133+ 'data ' =>$ user_list ,
134+ 'datakeys ' =>array ('id ' ,'name ' ),
135+ ));
136+ $ smarty ->assign ('on_behalf_control ' , 1 );
137+ }
138+ }
139+
140+ // Chart interval options.
141+ $ intervals = array ();
142+ $ intervals [INTERVAL_THIS_DAY ] = $ i18n ->getKey ('dropdown.this_day ' );
143+ $ intervals [INTERVAL_THIS_WEEK ] = $ i18n ->getKey ('dropdown.this_week ' );
144+ $ intervals [INTERVAL_THIS_MONTH ] = $ i18n ->getKey ('dropdown.this_month ' );
145+ $ intervals [INTERVAL_THIS_YEAR ] = $ i18n ->getKey ('dropdown.this_year ' );
146+ $ intervals [INTERVAL_ALL_TIME ] = $ i18n ->getKey ('dropdown.all_time ' );
147+
148+ // Chart interval dropdown.
149+ $ chart_form ->addInput (array ('type ' => 'combobox ' ,
150+ 'onchange ' => 'if(this.form) this.form.submit(); ' ,
151+ 'name ' => 'interval ' ,
152+ 'value ' => $ cl_interval ,
153+ 'data ' => $ intervals
154+ ));
155+
156+ // Chart type options.
157+ $ chart_selector = (MODE_PROJECTS_AND_TASKS == $ user ->tracking_mode
158+ || in_array ('cl ' , explode (', ' , $ user ->plugins )));
159+ if ($ chart_selector ) {
160+ $ types = array ();
161+ if (MODE_PROJECTS == $ user ->tracking_mode || MODE_PROJECTS_AND_TASKS == $ user ->tracking_mode )
162+ $ types [CHART_PROJECTS ] = $ i18n ->getKey ('dropdown.projects ' );
163+ if (MODE_PROJECTS_AND_TASKS == $ user ->tracking_mode )
164+ $ types [CHART_TASKS ] = $ i18n ->getKey ('dropdown.tasks ' );
165+ if (in_array ('cl ' , explode (', ' , $ user ->plugins )))
166+ $ types [CHART_CLIENTS ] = $ i18n ->getKey ('dropdown.clients ' );
167+
168+ // Add chart type dropdown.
169+ $ chart_form ->addInput (array ('type ' => 'combobox ' ,
170+ 'onchange ' => 'if(this.form) this.form.submit(); ' ,
171+ 'name ' => 'type ' ,
172+ 'value ' => $ cl_type ,
173+ 'data ' => $ types
174+ ));
175+ }
176+
177+ // Calendar.
178+ $ chart_form ->addInput (array ('type ' =>'calendar ' ,'name ' =>'date ' ,'value ' =>$ cl_date )); // calendar
179+
180+ // Get data for our chart.
181+ $ totals = ttChartHelper::getTotals ($ on_behalf_id , $ cl_type , $ cl_date , $ cl_interval );
182+ $ smarty ->assign ('totals ' , $ totals );
183+
184+ // Prepare chart for drawing.
185+ /*
186+ * We use libchart.php library to draw chart images. It can draw chart labels, too (embed in the image).
187+ * But quality of such auto-scaled text is not good. Therefore, we only use libchart to draw a pie-chart picture with
188+ * auto-calculated percentage markers around it. We print labels (to the side of the picture) ourselves,
189+ * using the same colors libchart is using. For labels printout, the $totals array (which is used for picture points)
190+ * is also passed to charts.tpl Smarty template.
191+ *
192+ * To make all of the above possible with only one database call to obtain $totals we have to print the chart image
193+ * to a file here (see code below). Once the image is available as a .png file, the charts.tpl can render it.
194+ *
195+ * PieChartEx class is a little extension to libchart-provided PieChart class. It allows us to print the chart
196+ * without title, logo, and labels.
197+ */
198+ $ chart = new PieChartEx (300 , 300 );
199+ $ data_set = new XYDataSet ();
200+ foreach ($ totals as $ total ) {
201+ $ data_set ->addPoint (new Point ( $ total ['name ' ], $ total ['time ' ]));
202+ }
203+ $ chart ->setDataSet ($ data_set );
204+
205+ // Prepare a file name.
206+ $ img_dir = TEMPLATE_DIR .'_c/ ' ; // Directory.
207+ $ file_name = uniqid ('chart_ ' ).'.png ' ; // Short file name. Unique ID here is to avoid problems with browser caching.
208+ $ img_ref = 'WEB-INF/templates_c/ ' .$ file_name ; // Image reference for html.
209+ $ file_name = $ img_dir .$ file_name ; // Full file name.
210+
211+ // Clean up the file system from older images.
212+ $ img_files = glob ($ img_dir .'chart_*.png ' );
213+ foreach ($ img_files as $ file ) {
214+ // If the create time of file is older than 1 minute, delete it.
215+ if (filemtime ($ file ) < (time () - 60 )) {
216+ unlink ($ file );
217+ }
218+ }
219+
220+ // Write chart image to file system.
221+ $ chart ->renderEx (array ('fileName ' =>$ file_name ,'hideLogo ' =>true ,'hideTitle ' =>true ,'hideLabel ' =>true ));
222+ // At this point libchart usage is complete and we have chart image on disk.
223+
224+ $ smarty ->assign ('img_file_name ' , $ img_ref );
225+ $ smarty ->assign ('chart_selector ' , $ chart_selector );
226+ $ smarty ->assign ('forms ' , array ($ chart_form ->getName () => $ chart_form ->toArray ()));
227+ $ smarty ->assign ('title ' , $ i18n ->getKey ('title.charts ' ));
228+ $ smarty ->assign ('content_page_name ' , 'charts.tpl ' );
229+ $ smarty ->display ('index.tpl ' );
230+ ?>
0 commit comments