Fixed stuff in treeview
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_iconworks.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2003 Kasper Skaarhoj (kasper@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for icon generation in the backend
29 *
30 * $Id$
31 * Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
32 * XHTML compliant
33 *
34 * @author Kasper Skaarhoj <kasper@typo3.com>
35 */
36 /**
37 * [CLASS/FUNCTION INDEX of SCRIPT]
38 *
39 *
40 *
41 * 85: class t3lib_iconWorks
42 * 99: function getIconImage($table,$row=array(),$backPath,$params='',$shaded=0)
43 * 116: function getIcon($table,$row=array(),$shaded=0)
44 * 198: function skinImg($backPath,$src,$wHattribs='',$outputMode=0)
45 *
46 * SECTION: Other functions
47 * 267: function makeIcon($iconfile,$mode, $user, $protectSection=0,$absFile='')
48 * 370: function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)
49 * 403: function imagecreatefrom($file)
50 * 420: function imagemake($im, $path)
51 *
52 * TOTAL FUNCTIONS: 7
53 * (This index is automatically created/updated by the extension "extdeveval")
54 *
55 */
56
57
58
59
60
61
62
63
64
65
66 /**
67 * Icon generation, backend
68 * This library has functions that returns - and if necessary creates - the icon for an element in TYPO3
69 *
70 * Expects global vars:
71 * - $BACK_PATH
72 * - PATH_typo3
73 * - $TCA, $PAGES_TYPES
74 *
75 *
76 * Notes:
77 * These functions are strongly related to the interface of TYPO3.
78 * The class is included in eg. init.php
79 * ALL functions called without making a class instance, eg. "t3lib_iconWorks::getIconImage()"
80 *
81 * @author Kasper Skaarhoj <kasper@typo3.com>
82 * @package TYPO3
83 * @subpackage t3lib
84 */
85 class t3lib_iconWorks {
86
87 /**
88 * Returns an icon image tag, 18x16 pixels, based on input information.
89 * This function is recommended to use in your backend modules.
90 *
91 * @param string The table name
92 * @param array The table row ("enablefields" are at least needed for correct icon display and for pages records some more fields in addition!)
93 * @param string The backpath to the main TYPO3 directory (relative path back to PATH_typo3)
94 * @param string Additional attributes for the image tag
95 * @param boolean If set, the icon will be grayed/shaded
96 * @return string <img>-tag
97 * @see getIcon()
98 */
99 function getIconImage($table,$row=array(),$backPath,$params='',$shaded=FALSE) {
100 $str='<img'.t3lib_iconWorks::skinImg($backPath,t3lib_iconWorks::getIcon($table,$row,$shaded),'width="18" height="16"').(trim($params)?' '.trim($params):'');
101 if (!stristr($str,'alt="')) $str.=' alt=""';
102 $str.=' />';
103 return $str;
104 }
105
106 /**
107 * Creates the icon for input table/row
108 * Returns filename for the image icon, relative to PATH_typo3
109 *
110 * @param string The table name
111 * @param array The table row ("enablefields" are at least needed for correct icon display and for pages records some more fields in addition!)
112 * @param boolean If set, the icon will be grayed/shaded
113 * @return string Icon filename
114 * @see getIconImage()
115 */
116 function getIcon($table,$row=array(),$shaded=FALSE) {
117 global $TCA, $PAGES_TYPES, $ICON_TYPES;
118
119 // Flags:
120 $doNotGenerateIcon = $GLOBALS['TYPO3_CONF_VARS']['GFX']['noIconProc']; // If set, the icon will NOT be generated with GDlib. Rather the icon will be looked for as [iconfilename]_X.[extension]
121 $doNotRenderUserGroupNumber = TRUE; // If set, then the usergroup number will NOT be printed unto the icon. NOTICE. the icon is generated only if a default icon for groups is not found... So effectively this is ineffective...
122
123 // First, find the icon file name. This can depend on configuration in TCA, field values and more:
124 if ($table=='pages') {
125 if (!$iconfile = $PAGES_TYPES[$row['doktype']]['icon']) {
126 $iconfile = $PAGES_TYPES['default']['icon'];
127 }
128 if ($row['module'] && $ICON_TYPES[$row['module']]['icon']) {
129 $iconfile = $ICON_TYPES[$row['module']]['icon'];
130 }
131 } else {
132 if (!$iconfile = $TCA[$table]['ctrl']['typeicons'][$row[$TCA[$table]['ctrl']['typeicon_column']]]) {
133 $iconfile = (($TCA[$table]['ctrl']['iconfile']) ? $TCA[$table]['ctrl']['iconfile'] : $table.'.gif');
134 }
135 }
136
137 // Setting path of iconfile if not already set. Default is "gfx/i/"
138 if (!strstr($iconfile,'/')) {
139 $iconfile = 'gfx/i/'.$iconfile;
140 }
141
142 // Setting the absolute path where the icon should be found as a file:
143 if (substr($iconfile,0,3)=='../') {
144 $absfile=PATH_site.substr($iconfile,3);
145 } else {
146 $absfile=PATH_typo3.$iconfile;
147 }
148
149 // Initializing variables, all booleans except otherwise stated:
150 $hidden = FALSE;
151 $timing = FALSE;
152 $futuretiming = FALSE;
153 $user = FALSE; // In fact an integer value...
154 $deleted = FALSE;
155 $protectSection = FALSE; // Set, if a page-record (only pages!) has the extend-to-subpages flag set.
156 $noIconFound = $row['_NO_ICON_FOUND'] ? TRUE : FALSE;
157 // + $shaded which is also boolean!
158
159 // Icon state based on "enableFields":
160 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
161 $enCols = $TCA[$table]['ctrl']['enablecolumns'];
162 // If "hidden" is enabled:
163 if ($enCols['disabled']) { if ($row[$enCols['disabled']]) { $hidden = TRUE; }}
164 // If a "starttime" is set and higher than current time:
165 if ($enCols['starttime']) { if (time() < intval($row[$enCols['starttime']])) { $timing = TRUE; }}
166 // If an "endtime" is set:
167 if ($enCols['endtime']) {
168 if (intval($row[$enCols['endtime']]) > 0) {
169 if (intval($row[$enCols['endtime']]) < time()) {
170 $timing = TRUE; // End-timing applies at this point.
171 } else {
172 $futuretiming = TRUE; // End-timing WILL apply in the future for this element.
173 }
174 }
175 }
176 // If a user-group field is set:
177 if ($enCols['fe_group']) {
178 $user = $row[$enCols['fe_group']];
179 if ($user && $doNotRenderUserGroupNumber) $user=100; // Limit for user number rendering!
180 }
181 }
182
183 // If "deleted" flag is set (only when listing records which are also deleted!)
184 if ($col=$row[$TCA[$table]['ctrl']['delete']]) {
185 $deleted = TRUE;
186 }
187 // Detecting extendToSubpages (for pages only)
188 if ($table=='pages' && $row['extendToSubpages'] && ($hidden || $timing || $futuretiming || $user)) {
189 $protectSection = TRUE;
190 }
191
192 // If ANY of the booleans are set it means we have to alter the icon:
193 if ($hidden || $timing || $futuretiming || $user || $deleted || $shaded || $noIconFound) {
194 $flags='';
195 $string='';
196 if ($deleted) {
197 $string='deleted';
198 $flags='d';
199 } elseif ($noIconFound) { // This is ONLY for creating icons with "?" on easily...
200 $string='no_icon_found';
201 $flags='x';
202 } else {
203 if ($hidden) $string.='hidden';
204 if ($timing) $string.='timing';
205 if (!$string && $futuretiming) {
206 $string='futuretiming';
207 }
208
209 $flags.=
210 ($hidden ? 'h' : '').
211 ($timing ? 't' : '').
212 ($futuretiming ? 'f' : '').
213 ($user ? 'u' : '').
214 ($protectSection ? 'p' : '').
215 ($shaded ? 's' : '');
216 }
217
218 // Create tagged icon file name:
219 $iconFileName_stateTagged = ereg_replace('.([[:alnum:]]+)$','__'.$flags.'.\1',basename($iconfile));
220
221 // Check if tagged icon file name exists (a tagget icon means the icon base name with the flags added between body and extension of the filename, prefixed with underscore)
222 if (@is_file(dirname($absfile).'/'.$iconFileName_stateTagged)) { // Look for [iconname]_xxxx.[ext]
223 return dirname($iconfile).'/'.$iconFileName_stateTagged;
224 } elseif ($doNotGenerateIcon) { // If no icon generation can be done, try to look for the _X icon:
225 $iconFileName_X = ereg_replace('.([[:alnum:]]+)$','__x.\1',basename($iconfile));
226 if (@is_file(dirname($absfile).'/'.$iconFileName_X)) {
227 return dirname($iconfile).'/'.$iconFileName_X;
228 } else {
229 return 'gfx/i/no_icon_found.gif';
230 }
231 } else { // Otherwise, create the icon:
232 $theRes= t3lib_iconWorks::makeIcon($GLOBALS['BACK_PATH'].$iconfile, $string, $user, $protectSection, $absfile, $iconFileName_stateTagged);
233 return $theRes;
234 }
235 } else {
236 return $iconfile;
237 }
238 }
239
240 /**
241 * Returns the src=... for the input $src value OR any alternative found in $TBE_STYLES['skinImg']
242 * Used for skinning the TYPO3 backend with an alternative set of icons
243 *
244 * @param string Current backpath to PATH_typo3 folder
245 * @param string Icon file name relative to PATH_typo3 folder
246 * @param string Default width/height, defined like 'width="12" height="14"'
247 * @param integer Mode: 0 (zero) is default and returns src/width/height. 1 returns value of src+backpath, 2 returns value of w/h.
248 * @return string Returns ' src="[backPath][src]" [wHattribs]'
249 * @see skinImgFile()
250 */
251 function skinImg($backPath,$src,$wHattribs='',$outputMode=0) {
252
253 // Setting source key. If the icon is refered to inside an extension, we homogenize the prefix to "ext/":
254 $srcKey = ereg_replace('^(\.\.\/typo3conf\/ext|sysext|ext)\/','ext/',$src);
255 #if ($src!=$srcKey)debug(array($src,$srcKey));
256
257 // LOOKING for alternative icons:
258 if ($GLOBALS['TBE_STYLES']['skinImg'][$srcKey]) { // Slower or faster with is_array()? Could be used.
259 list($src,$wHattribs) = $GLOBALS['TBE_STYLES']['skinImg'][$srcKey];
260 } elseif ($GLOBALS['TBE_STYLES']['skinImgAutoCfg']) { // Otherwise, test if auto-detection is enabled:
261
262 // Search for alternative icon automatically:
263 $fExt = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['forceFileExtension'];
264 $scaleFactor = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['scaleFactor'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['scaleFactor'] : 1; // Scaling factor
265 $lookUpName = $fExt ? ereg_replace('\.[[:alnum:]]+$','',$srcKey).'.'.$fExt : $srcKey; // Set filename to look for
266
267 // If file is found:
268 if (@is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'].$lookUpName)) { // If there is a file...
269 $iInfo = @getimagesize($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'].$lookUpName); // Get width/height:
270
271 // Set $src and $wHattribs:
272 $src = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['relDir'].$lookUpName;
273 $wHattribs = 'width="'.round($iInfo[0]*$scaleFactor).'" height="'.round($iInfo[1]*$scaleFactor).'"';
274 }
275
276 // In anycase, set currect src / wHattrib - this way we make sure that an entry IS found next time we hit the function, regardless of whether it points to a alternative icon or just the current.
277 $GLOBALS['TBE_STYLES']['skinImg'][$srcKey] = array($src,$wHattribs); // Set default...
278 }
279
280 // DEBUG: This doubles the size of all icons - for testing/debugging:
281 # if (ereg('^width="([0-9]+)" height="([0-9]+)"$',$wHattribs,$reg)) $wHattribs='width="'.($reg[1]*2).'" height="'.($reg[2]*2).'"';
282
283 // Return icon source/wHattributes:
284 switch($outputMode) {
285 case 0:
286 return ' src="'.$backPath.$src.'" '.$wHattribs;
287 break;
288 case 1:
289 return $backPath.$src;
290 break;
291 case 2:
292 return $wHattribs;
293 break;
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306
307 /***********************************
308 *
309 * Other functions
310 *
311 ***********************************/
312
313 /**
314 * Creates the icon file for the function getIcon()
315 *
316 * @param string Original unprocessed Icon file, relative path to PATH_typo3
317 * @param string Mode string, eg. "deleted" or "futuretiming" determining how the icon will look
318 * @param integer The number of the fe_group record uid if applicable
319 * @param boolean Flag determines if the protected-section icon should be applied.
320 * @param string Absolute path to file from which to create the icon.
321 * @param string The filename that this icon should have had, basically [icon base name]_[flags].[extension] - used for part of temporary filename
322 * @return string Filename relative to PATH_typo3
323 * @access private
324 */
325 function makeIcon($iconfile,$mode, $user, $protectSection,$absFile,$iconFileName_stateTagged) {
326 $iconFileName = 'icon_'.t3lib_div::shortMD5($iconfile.'|'.$mode.'|-'.$user.'|'.$protectSection).'_'.$iconFileName_stateTagged.'.'.($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']?'png':'gif');
327 $mainpath = '../typo3temp/'.$iconFileName;
328 $path = PATH_site.'typo3temp/'.$iconFileName;
329
330
331 if (@file_exists(PATH_typo3.'icons/'.$iconFileName)) { // Returns if found in typo3/icons/
332 return 'icons/'.$iconFileName;
333 } elseif (@file_exists($path)) { // Returns if found in ../typo3temp/icons/
334 return $mainpath;
335 } else { // Makes icon:
336 if (@file_exists($absFile)) {
337 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
338
339 // Create image pointer, if possible:
340 $im = t3lib_iconworks::imagecreatefrom($absFile);
341 if ($im<0) return $iconfile;
342
343 // Converting to gray scale, dimming the icon:
344 if ($mode!='futuretiming' && $mode!='no_icon_found' && !(!$mode && $user)) {
345 for ($c=0; $c<ImageColorsTotal($im); $c++) {
346 $cols = ImageColorsForIndex($im,$c);
347 $newcol = round(($cols['red']+$cols['green']+$cols['blue'])/3);
348 $lighten = 2;
349 $newcol = round(255-((255-$newcol)/$lighten));
350 ImageColorSet($im,$c,$newcol,$newcol,$newcol);
351 }
352 }
353 // Applying user icon, if there are access control on the item:
354 if ($user) {
355 if ($user < 100) { // Apply user number only if lower than 100
356 $black = ImageColorAllocate($im, 0,0,0);
357 imagefilledrectangle($im, 0,0,(($user>10)?9:5),8,$black);
358
359 $white = ImageColorAllocate($im, 255,255,255);
360 imagestring($im, 1, 1, 1, $user, $white);
361 }
362
363 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_group.gif');
364 if ($ol_im<0) return $iconfile;
365
366 t3lib_iconworks::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im));
367 }
368 // Applying overlay based on mode:
369 if ($mode) {
370 unset($ol_im);
371 switch($mode) {
372 case 'deleted':
373 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_deleted.gif');
374 break;
375 case 'futuretiming':
376 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_timing.gif');
377 break;
378 case 'timing':
379 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_timing.gif');
380 break;
381 case 'hiddentiming':
382 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_hidden_timing.gif');
383 break;
384 case 'no_icon_found':
385 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_no_icon_found.gif');
386 break;
387 case 'hidden':
388 default:
389 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_hidden.gif');
390 break;
391 }
392 if ($ol_im<0) return $iconfile;
393 t3lib_iconworks::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im));
394 }
395 // Protect-section icon:
396 if ($protectSection) {
397 $ol_im = t3lib_iconworks::imagecreatefrom($GLOBALS['BACK_PATH'].'gfx/overlay_sub5.gif');
398 if ($ol_im<0) return $iconfile;
399 t3lib_iconworks::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im));
400 }
401
402 // Create the image as file, destroy GD image and return:
403 @t3lib_iconWorks::imagemake($im, $path);
404 t3lib_div::gif_compress($path, 'IM');
405 ImageDestroy($im);
406 return $mainpath;
407 } else {
408 return $iconfile;
409 }
410 } else {
411 return $GLOBALS['BACK_PATH'].'gfx/fileicons/default.gif';
412 }
413 }
414 }
415
416 /**
417 * The necessity of using this function for combining two images if GD is version 2 is that
418 * GD2 cannot manage to combine two indexed-color images without totally spoiling everything.
419 * In class.t3lib_stdgraphic this was solved by combining the images onto a first created true color image
420 * However it has turned out that this method will not work if the indexed png-files contains transparency.
421 * So I had to turn my attention to ImageMagick - my 'enemy of death'.
422 * And so it happend - ImageMagick is now used to combine my two indexed-color images with transparency. And that works.
423 * Of course it works only if ImageMagick is able to create valid png-images - which you cannot be sure of with older versions (still 5+)
424 * The only drawback is (apparently) that IM creates true-color png's. The transparency of these will not be shown by MSIE on windows at this time (although it's straight 0%/100% transparency!) and the file size may be larger.
425 *
426 * For parameters, see PHP function "imagecopyresized()"
427 *
428 * @param pointer see PHP function "imagecopyresized()"
429 * @param pointer see PHP function "imagecopyresized()"
430 * @param integer see PHP function "imagecopyresized()"
431 * @param integer see PHP function "imagecopyresized()"
432 * @param integer see PHP function "imagecopyresized()"
433 * @param integer see PHP function "imagecopyresized()"
434 * @param integer see PHP function "imagecopyresized()"
435 * @param integer see PHP function "imagecopyresized()"
436 * @param integer see PHP function "imagecopyresized()"
437 * @param integer see PHP function "imagecopyresized()"
438 * @return void
439 * @access private
440 */
441 function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) {
442 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_2'] && $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) { // Maybe I'll have to change this if GD2/gif does not work either...
443 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path']) {
444 $cmd=$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path'].
445 ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename']?$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_combine_filename']:'combine').
446 ' -compose over ';
447 $tempBaseName = PATH_site.'typo3temp/ICRZ_'.md5(uniqid('.'));
448
449 ImagePng($im, $tempBaseName.'_im.png');
450 ImagePng($cpImg, $tempBaseName.'_cpImg.png');
451 exec($cmd.
452 $tempBaseName.'_cpImg.png '.
453 $tempBaseName.'_im.png '.
454 $tempBaseName.'_out.png '
455 );
456 $im = imagecreatefrompng($tempBaseName.'_out.png');
457 unlink($tempBaseName.'_im.png');
458 unlink($tempBaseName.'_cpImg.png');
459 unlink($tempBaseName.'_out.png');
460 }
461 } else {
462 imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
463 }
464 }
465
466 /**
467 * Create new image pointer from input file (either gif/png, in case the wrong format it is converted by t3lib_div::read_png_gif())
468 *
469 * @param string Absolute filename of the image file from which to start the icon creation.
470 * @return mixed If success, image pointer, otherwise "-1"
471 * @access private
472 * @see t3lib_div::read_png_gif
473 */
474 function imagecreatefrom($file) {
475 $file = t3lib_div::read_png_gif($file,$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']);
476 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
477 return $file ? imagecreatefrompng($file) : -1;
478 } else {
479 return $file ? imagecreatefromgif($file) : -1;
480 }
481 }
482
483 /**
484 * Write the icon in $im pointer to $path
485 *
486 * @param pointer Pointer to GDlib image resource
487 * @param string Absolute path to the filename in which to write the icon.
488 * @return void
489 * @access private
490 */
491 function imagemake($im, $path) {
492 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
493 @ImagePng($im, $path);
494 } else {
495 @ImageGif($im, $path);
496 }
497 }
498 }
499 ?>