|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 /** 00028 * Contains class for icon generation in the backend 00029 * 00030 * $Id: class.t3lib_iconworks.php 10395 2011-02-05 23:19:57Z stephenking $ 00031 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj 00032 * XHTML compliant 00033 * 00034 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00035 */ 00036 /** 00037 * [CLASS/FUNCTION INDEX of SCRIPT] 00038 * 00039 * 00040 * 00041 * 85: class t3lib_iconWorks 00042 * 100: function getIconImage($table,$row=array(),$backPath,$params='',$shaded=FALSE) 00043 * 118: function getIcon($table,$row=array(),$shaded=FALSE) 00044 * 264: function skinImg($backPath,$src,$wHattribs='',$outputMode=0) 00045 * 00046 * SECTION: Other functions 00047 * 353: function makeIcon($iconfile,$mode, $user, $protectSection,$absFile,$iconFileName_stateTagged) 00048 * 475: function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) 00049 * 505: function imagecreatefrom($file) 00050 * 522: function imagemake($im, $path) 00051 * 00052 * TOTAL FUNCTIONS: 7 00053 * (This index is automatically created/updated by the extension "extdeveval") 00054 * 00055 */ 00056 00057 00058 /** 00059 * Icon generation, backend 00060 * This library has functions that returns - and if necessary creates - the icon for an element in TYPO3 00061 * 00062 * Expects global vars: 00063 * - $BACK_PATH 00064 * - PATH_typo3 00065 * - $TCA, $PAGES_TYPES 00066 * 00067 * 00068 * Notes: 00069 * These functions are strongly related to the interface of TYPO3. 00070 * The class is included in eg. init.php 00071 * ALL functions called without making a class instance, eg. "t3lib_iconWorks::getIconImage()" 00072 * 00073 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00074 * @package TYPO3 00075 * @subpackage t3lib 00076 */ 00077 final class t3lib_iconWorks { 00078 00079 public static $fileSpriteIconNames = array( 00080 'htm' => 'mimetypes-text-html', 00081 'html' => 'mimetypes-text-html', 00082 'css' => 'mimetypes-text-css', 00083 'js' => 'mimetypes-text-js', 00084 'csv' => 'mimetypes-text-csv', 00085 'php' => 'mimetypes-text-php', 00086 'php6' => 'mimetypes-text-php', 00087 'php5' => 'mimetypes-text-php', 00088 'php4' => 'mimetypes-text-php', 00089 'php3' => 'mimetypes-text-php', 00090 'inc' => 'mimetypes-text-php', 00091 'ts' => 'mimetypes-text-ts', 00092 'txt' => 'mimetypes-text-text', 00093 'class' => 'mimetypes-text-text', 00094 'tmpl' => 'mimetypes-text-text', 00095 'jpg' => 'mimetypes-media-image', 00096 'jpeg' => 'mimetypes-media-image', 00097 'gif' => 'mimetypes-media-image', 00098 'png' => 'mimetypes-media-image', 00099 'bmp' => 'mimetypes-media-image', 00100 'tif' => 'mimetypes-media-image', 00101 'tga' => 'mimetypes-media-image', 00102 'psd' => 'mimetypes-media-image', 00103 'eps' => 'mimetypes-media-image', 00104 'avi' => 'mimetypes-media-video', 00105 'mpg' => 'mimetypes-media-video', 00106 'mpeg' => 'mimetypes-media-video', 00107 'mov' => 'mimetypes-media-video', 00108 'wav' => 'mimetypes-media-audio', 00109 'mp3' => 'mimetypes-media-audio', 00110 'mid' => 'mimetypes-media-audio', 00111 'swf' => 'mimetypes-media-flash', 00112 'swa' => 'mimetypes-media-flash', 00113 'exe' => 'mimetypes-executable-executable', 00114 'com' => 'mimetypes-executable-executable', 00115 't3x' => 'mimetypes-compressed', 00116 't3d' => 'mimetypes-compressed', 00117 'zip' => 'mimetypes-compressed', 00118 'tgz' => 'mimetypes-compressed', 00119 'gz' => 'mimetypes-compressed', 00120 'pdf' => 'mimetypes-pdf', 00121 'doc' => 'mimetypes-word', 00122 'dot' => 'mimetypes-word', 00123 'docm' => 'mimetypes-word', 00124 'docx' => 'mimetypes-word', 00125 'dotm' => 'mimetypes-word', 00126 'dotx' => 'mimetypes-word', 00127 'sxw' => 'mimetypes-word', 00128 'rtf' => 'mimetypes-word', 00129 'xls' => 'mimetypes-excel', 00130 'xlsm' => 'mimetypes-excel', 00131 'xlsx' => 'mimetypes-excel', 00132 'xltm' => 'mimetypes-excel', 00133 'xltx' => 'mimetypes-excel', 00134 'sxc' => 'mimetypes-excel', 00135 'ppt' => 'mimetypes-powerpoint', 00136 'pptm' => 'mimetypes-powerpoint', 00137 'pptx' => 'mimetypes-powerpoint', 00138 'potm' => 'mimetypes-powerpoint', 00139 'potx' => 'mimetypes-powerpoint', 00140 'mount' => 'apps-filetree-mount', 00141 'folder' => 'apps-filetree-folder-default', 00142 'default' => 'mimetypes-other-other' 00143 ); 00144 00145 /** 00146 * Returns an icon image tag, 18x16 pixels, based on input information. 00147 * This function is recommended to use in your backend modules. 00148 * Usage: 60 00149 * 00150 * @param string The table name 00151 * @param array The table row ("enablefields" are at least needed for correct icon display and for pages records some more fields in addition!) 00152 * @param string The backpath to the main TYPO3 directory (relative path back to PATH_typo3) 00153 * @param string Additional attributes for the image tag 00154 * @param boolean If set, the icon will be grayed/shaded 00155 * @return string <img>-tag 00156 * @see getIcon() 00157 */ 00158 public static function getIconImage($table, $row = array(), $backPath, $params = '', $shaded = FALSE) { 00159 $str = '<img' . 00160 self::skinImg($backPath, self::getIcon($table, $row, $shaded), 'width="18" height="16"') . 00161 (trim($params) ? ' ' . trim($params) : ''); 00162 if (!stristr($str, 'alt="')) { 00163 $str .= ' alt=""'; 00164 } 00165 $str .= ' />'; 00166 return $str; 00167 } 00168 00169 /** 00170 * Creates the icon for input table/row 00171 * Returns filename for the image icon, relative to PATH_typo3 00172 * Usage: 24 00173 * 00174 * @param string The table name 00175 * @param array The table row ("enablefields" are at least needed for correct icon display and for pages records some more fields in addition!) 00176 * @param boolean If set, the icon will be grayed/shaded 00177 * @return string Icon filename 00178 * @see getIconImage() 00179 */ 00180 public static function getIcon($table, $row = array(), $shaded = FALSE) { 00181 global $TCA, $PAGES_TYPES, $ICON_TYPES; 00182 00183 // Flags: 00184 $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... 00185 00186 // Shadow: 00187 if ($TCA[$table]['ctrl']['versioningWS']) { 00188 switch ((int) $row['t3ver_state']) { 00189 case 1: 00190 return 'gfx/i/shadow_hide.png'; 00191 break; 00192 case 2: 00193 return 'gfx/i/shadow_delete.png'; 00194 break; 00195 case 3: 00196 return 'gfx/i/shadow_moveto_plh.png'; 00197 break; 00198 case 4: 00199 return 'gfx/i/shadow_moveto_pointer.png'; 00200 break; 00201 } 00202 } 00203 00204 // First, find the icon file name. This can depend on configuration in TCA, field values and more: 00205 if ($table == 'pages') { 00206 // @TODO: RFC #7370: doktype 2&5 are deprecated since TYPO3 4.2-beta1 00207 if ($row['nav_hide'] && ($row['doktype'] == t3lib_pageSelect::DOKTYPE_DEFAULT || $row['doktype'] == t3lib_pageSelect::DOKTYPE_ADVANCED)) { 00208 $row['doktype'] = t3lib_pageSelect::DOKTYPE_HIDE_IN_MENU; 00209 } // Workaround to change the icon if "Hide in menu" was set 00210 00211 if (!$iconfile = $PAGES_TYPES[$row['doktype']]['icon']) { 00212 $iconfile = $PAGES_TYPES['default']['icon']; 00213 } 00214 if ($row['module'] && $ICON_TYPES[$row['module']]['icon']) { 00215 $iconfile = $ICON_TYPES[$row['module']]['icon']; 00216 } 00217 } else { 00218 if (!$iconfile = $TCA[$table]['ctrl']['typeicons'][$row[$TCA[$table]['ctrl']['typeicon_column']]]) { 00219 $iconfile = (($TCA[$table]['ctrl']['iconfile']) ? $TCA[$table]['ctrl']['iconfile'] : $table . '.gif'); 00220 } 00221 } 00222 00223 // Setting path of iconfile if not already set. Default is "gfx/i/" 00224 if (!strstr($iconfile, '/')) { 00225 $iconfile = 'gfx/i/' . $iconfile; 00226 } 00227 00228 // Setting the absolute path where the icon should be found as a file: 00229 if (substr($iconfile, 0, 3) == '../') { 00230 $absfile = PATH_site . substr($iconfile, 3); 00231 } else { 00232 $absfile = PATH_typo3 . $iconfile; 00233 } 00234 00235 // Initializing variables, all booleans except otherwise stated: 00236 $hidden = FALSE; 00237 $timing = FALSE; 00238 $futuretiming = FALSE; 00239 $user = FALSE; // In fact an integer value... 00240 $deleted = FALSE; 00241 $protectSection = FALSE; // Set, if a page-record (only pages!) has the extend-to-subpages flag set. 00242 $noIconFound = $row['_NO_ICON_FOUND'] ? TRUE : FALSE; 00243 // + $shaded which is also boolean! 00244 00245 // Icon state based on "enableFields": 00246 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) { 00247 $enCols = $TCA[$table]['ctrl']['enablecolumns']; 00248 // If "hidden" is enabled: 00249 if ($enCols['disabled']) { 00250 if ($row[$enCols['disabled']]) { 00251 $hidden = TRUE; 00252 } 00253 } 00254 // If a "starttime" is set and higher than current time: 00255 if ($enCols['starttime']) { 00256 if ($GLOBALS['EXEC_TIME'] < intval($row[$enCols['starttime']])) { 00257 $timing = TRUE; 00258 // ...And if "endtime" is NOT set: 00259 if (intval($row[$enCols['endtime']]) == 0) { 00260 $futuretiming = TRUE; 00261 } 00262 } 00263 } 00264 // If an "endtime" is set: 00265 if ($enCols['endtime']) { 00266 if (intval($row[$enCols['endtime']]) > 0) { 00267 if (intval($row[$enCols['endtime']]) < $GLOBALS['EXEC_TIME']) { 00268 $timing = TRUE; // End-timing applies at this point. 00269 } else { 00270 $futuretiming = TRUE; // End-timing WILL apply in the future for this element. 00271 } 00272 } 00273 } 00274 // If a user-group field is set: 00275 if ($enCols['fe_group']) { 00276 $user = $row[$enCols['fe_group']]; 00277 if ($user && $doNotRenderUserGroupNumber) { 00278 $user = 100; 00279 } // Limit for user number rendering! 00280 } 00281 } 00282 00283 // If "deleted" flag is set (only when listing records which are also deleted!) 00284 if ($col = $row[$TCA[$table]['ctrl']['delete']]) { 00285 $deleted = TRUE; 00286 } 00287 // Detecting extendToSubpages (for pages only) 00288 if ($table == 'pages' && $row['extendToSubpages'] && ($hidden || $timing || $futuretiming || $user)) { 00289 $protectSection = TRUE; 00290 } 00291 00292 // If ANY of the booleans are set it means we have to alter the icon: 00293 if ($hidden || $timing || $futuretiming || $user || $deleted || $shaded || $noIconFound) { 00294 $flags = ''; 00295 $string = ''; 00296 if ($deleted) { 00297 $string = 'deleted'; 00298 $flags = 'd'; 00299 } elseif ($noIconFound) { // This is ONLY for creating icons with "?" on easily... 00300 $string = 'no_icon_found'; 00301 $flags = 'x'; 00302 } else { 00303 if ($hidden) { 00304 $string .= 'hidden'; 00305 } 00306 if ($timing) { 00307 $string .= 'timing'; 00308 } 00309 if (!$string && $futuretiming) { 00310 $string = 'futuretiming'; 00311 } 00312 00313 $flags .= 00314 ($hidden ? 'h' : '') . 00315 ($timing ? 't' : '') . 00316 ($futuretiming ? 'f' : '') . 00317 ($user ? 'u' : '') . 00318 ($protectSection ? 'p' : '') . 00319 ($shaded ? 's' : ''); 00320 } 00321 00322 // Create tagged icon file name: 00323 $iconFileName_stateTagged = preg_replace('/.([[:alnum:]]+)$/', '__' . $flags . '.\1', basename($iconfile)); 00324 00325 // 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) 00326 if (@is_file(dirname($absfile) . '/' . $iconFileName_stateTagged) || @is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . '/' . dirname($iconfile) . '/' . $iconFileName_stateTagged)) { // Look for [iconname]_xxxx.[ext] 00327 return dirname($iconfile) . '/' . $iconFileName_stateTagged; 00328 } else { // Otherwise, create the icon: 00329 $theRes = self::makeIcon($GLOBALS['BACK_PATH'] . $iconfile, $string, $user, $protectSection, $absfile, $iconFileName_stateTagged); 00330 return $theRes; 00331 } 00332 } else { 00333 return $iconfile; 00334 } 00335 } 00336 00337 /** 00338 * Returns the src=... for the input $src value OR any alternative found in $TBE_STYLES['skinImg'] 00339 * Used for skinning the TYPO3 backend with an alternative set of icons 00340 * Usage: 336 00341 * 00342 * @param string Current backpath to PATH_typo3 folder 00343 * @param string Icon file name relative to PATH_typo3 folder 00344 * @param string Default width/height, defined like 'width="12" height="14"' 00345 * @param integer Mode: 0 (zero) is default and returns src/width/height. 1 returns value of src+backpath, 2 returns value of w/h. 00346 * @return string Returns ' src="[backPath][src]" [wHattribs]' 00347 * @see skinImgFile() 00348 */ 00349 public static function skinImg($backPath, $src, $wHattribs = '', $outputMode = 0) { 00350 00351 static $cachedSkinImages = array(); 00352 00353 $imageId = md5($backPath . $src . $wHattribs . $outputMode); 00354 00355 if (isset($cachedSkinImages[$imageId])) { 00356 return $cachedSkinImages[$imageId]; 00357 } 00358 // Setting source key. If the icon is refered to inside an extension, we homogenize the prefix to "ext/": 00359 $srcKey = preg_replace('/^(\.\.\/typo3conf\/ext|sysext|ext)\//', 'ext/', $src); 00360 #if ($src!=$srcKey)debug(array($src, $srcKey)); 00361 00362 // LOOKING for alternative icons: 00363 if ($GLOBALS['TBE_STYLES']['skinImg'][$srcKey]) { // Slower or faster with is_array()? Could be used. 00364 list($src, $wHattribs) = $GLOBALS['TBE_STYLES']['skinImg'][$srcKey]; 00365 } elseif ($GLOBALS['TBE_STYLES']['skinImgAutoCfg']) { // Otherwise, test if auto-detection is enabled: 00366 00367 // Search for alternative icon automatically: 00368 $fExt = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['forceFileExtension']; 00369 $scaleFactor = ($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['scaleFactor'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['scaleFactor'] : 1); // Scaling factor 00370 $lookUpName = ($fExt ? preg_replace('/\.[[:alnum:]]+$/', '', $srcKey) . '.' . $fExt : $srcKey); // Set filename to look for 00371 00372 if ($fExt && !@is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . $lookUpName)) { 00373 // fallback to original filename if icon with forced extension doesn't exists 00374 $lookUpName = $srcKey; 00375 } 00376 // If file is found: 00377 if (@is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . $lookUpName)) { // If there is a file... 00378 $iInfo = @getimagesize($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . $lookUpName); // Get width/height: 00379 00380 // Set $src and $wHattribs: 00381 $src = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['relDir'] . $lookUpName; 00382 $wHattribs = 'width="' . round($iInfo[0] * $scaleFactor) . '" height="' . round($iInfo[1] * $scaleFactor) . '"'; 00383 } 00384 00385 // In any case, set currect src / wHattrib - this way we make sure that an entry IS found next time we hit the function, 00386 // regardless of whether it points to a alternative icon or just the current. 00387 $GLOBALS['TBE_STYLES']['skinImg'][$srcKey] = array($src, $wHattribs); // Set default... 00388 } 00389 00390 // DEBUG: This doubles the size of all icons - for testing/debugging: 00391 // if (preg_match('/^width="([0-9]+)" height="([0-9]+)"$/', $wHattribs, $reg)) $wHattribs='width="'.($reg[1]*2).'" height="'.($reg[2]*2).'"'; 00392 00393 00394 // rendering disabled (greyed) icons using _i (inactive) as name suffix ("_d" is already used) 00395 $matches = array(); 00396 $srcBasename = basename($src); 00397 if (preg_match('/(.*)_i(\....)$/', $srcBasename, $matches)) { 00398 $temp_path = dirname(PATH_thisScript) . '/'; 00399 if (!@is_file($temp_path . $backPath . $src)) { 00400 $srcOrg = preg_replace('/_i' . preg_quote($matches[2]) . '$/', $matches[2], $src); 00401 $src = self::makeIcon($backPath . $srcOrg, 'disabled', 0, FALSE, $temp_path . $backPath . $srcOrg, $srcBasename); 00402 } 00403 } 00404 00405 00406 // Return icon source/wHattributes: 00407 $output = ''; 00408 switch ($outputMode) { 00409 case 0: 00410 $output = ' src="' . $backPath . $src . '" ' . $wHattribs; 00411 break; 00412 case 1: 00413 $output = $backPath . $src; 00414 break; 00415 case 2: 00416 $output = $wHattribs; 00417 break; 00418 } 00419 00420 $cachedSkinImages[$imageId] = $output; 00421 return $output; 00422 } 00423 00424 00425 /*********************************** 00426 * 00427 * Other functions 00428 * 00429 ***********************************/ 00430 00431 /** 00432 * Creates the icon file for the function getIcon() 00433 * 00434 * @param string Original unprocessed Icon file, relative path to PATH_typo3 00435 * @param string Mode string, eg. "deleted" or "futuretiming" determining how the icon will look 00436 * @param integer The number of the fe_group record uid if applicable 00437 * @param boolean Flag determines if the protected-section icon should be applied. 00438 * @param string Absolute path to file from which to create the icon. 00439 * @param string The filename that this icon should have had, basically [icon base name]_[flags].[extension] - used for part of temporary filename 00440 * @return string Filename relative to PATH_typo3 00441 * @access private 00442 */ 00443 public static function makeIcon($iconfile, $mode, $user, $protectSection, $absFile, $iconFileName_stateTagged) { 00444 $iconFileName = 'icon_' . t3lib_div::shortMD5($iconfile . '|' . $mode . '|-' . $user . '|' . $protectSection) . '_' . $iconFileName_stateTagged . '.' . ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] ? 'png' : 'gif'); 00445 $mainpath = '../typo3temp/' . $iconFileName; 00446 $path = PATH_site . 'typo3temp/' . $iconFileName; 00447 00448 00449 if (file_exists(PATH_typo3 . 'icons/' . $iconFileName)) { // Returns if found in typo3/icons/ 00450 return 'icons/' . $iconFileName; 00451 } elseif (file_exists($path)) { // Returns if found in ../typo3temp/icons/ 00452 return $mainpath; 00453 } else { // Makes icon: 00454 if (file_exists($absFile)) { 00455 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) { 00456 00457 // Create image pointer, if possible 00458 $im = self::imagecreatefrom($absFile); 00459 if ($im < 0) { 00460 return $iconfile; 00461 } 00462 00463 // Converting to gray scale, dimming the icon: 00464 if (($mode == 'disabled') OR ($mode != 'futuretiming' && $mode != 'no_icon_found' && !(!$mode && $user))) { 00465 for ($c = 0; $c < ImageColorsTotal($im); $c++) { 00466 $cols = ImageColorsForIndex($im, $c); 00467 $newcol = round(($cols['red'] + $cols['green'] + $cols['blue']) / 3); 00468 $lighten = ($mode == 'disabled') ? 2.5 : 2; 00469 $newcol = round(255 - ((255 - $newcol) / $lighten)); 00470 ImageColorSet($im, $c, $newcol, $newcol, $newcol); 00471 } 00472 } 00473 // Applying user icon, if there are access control on the item: 00474 if ($user) { 00475 if ($user < 100) { // Apply user number only if lower than 100 00476 $black = ImageColorAllocate($im, 0, 0, 0); 00477 imagefilledrectangle($im, 0, 0, (($user > 10) ? 9 : 5), 8, $black); 00478 00479 $white = ImageColorAllocate($im, 255, 255, 255); 00480 imagestring($im, 1, 1, 1, $user, $white); 00481 } 00482 00483 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_group.gif'); 00484 if ($ol_im < 0) { 00485 return $iconfile; 00486 } 00487 00488 self::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im)); 00489 } 00490 // Applying overlay based on mode: 00491 if ($mode) { 00492 unset($ol_im); 00493 switch ($mode) { 00494 case 'deleted': 00495 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_deleted.gif'); 00496 break; 00497 case 'futuretiming': 00498 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_timing.gif'); 00499 break; 00500 case 'timing': 00501 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_timing.gif'); 00502 break; 00503 case 'hiddentiming': 00504 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_hidden_timing.gif'); 00505 break; 00506 case 'no_icon_found': 00507 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_no_icon_found.gif'); 00508 break; 00509 case 'disabled': 00510 // is already greyed - nothing more 00511 $ol_im = 0; 00512 break; 00513 case 'hidden': 00514 default: 00515 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_hidden.gif'); 00516 break; 00517 } 00518 if ($ol_im < 0) { 00519 return $iconfile; 00520 } 00521 if ($ol_im) { 00522 self::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im)); 00523 } 00524 } 00525 // Protect-section icon: 00526 if ($protectSection) { 00527 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_sub5.gif'); 00528 if ($ol_im < 0) { 00529 return $iconfile; 00530 } 00531 self::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im)); 00532 } 00533 00534 // Create the image as file, destroy GD image and return: 00535 @self::imagemake($im, $path); 00536 t3lib_div::gif_compress($path, 'IM'); 00537 ImageDestroy($im); 00538 return $mainpath; 00539 } else { 00540 return $iconfile; 00541 } 00542 } else { 00543 return $GLOBALS['BACK_PATH'] . 'gfx/fileicons/default.gif'; 00544 } 00545 } 00546 } 00547 00548 /** 00549 * The necessity of using this function for combining two images if GD is version 2 is that 00550 * GD2 cannot manage to combine two indexed-color images without totally spoiling everything. 00551 * In class.t3lib_stdgraphic this was solved by combining the images onto a first created true color image 00552 * However it has turned out that this method will not work if the indexed png-files contains transparency. 00553 * So I had to turn my attention to ImageMagick - my 'enemy of death'. 00554 * And so it happend - ImageMagick is now used to combine my two indexed-color images with transparency. And that works. 00555 * 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+) 00556 * 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. 00557 * 00558 * For parameters, see PHP function "imagecopyresized()" 00559 * 00560 * @param pointer see PHP function "imagecopyresized()" 00561 * @param pointer see PHP function "imagecopyresized()" 00562 * @param integer see PHP function "imagecopyresized()" 00563 * @param integer see PHP function "imagecopyresized()" 00564 * @param integer see PHP function "imagecopyresized()" 00565 * @param integer see PHP function "imagecopyresized()" 00566 * @param integer see PHP function "imagecopyresized()" 00567 * @param integer see PHP function "imagecopyresized()" 00568 * @param integer see PHP function "imagecopyresized()" 00569 * @param integer see PHP function "imagecopyresized()" 00570 * @return void 00571 * @access private 00572 */ 00573 public static function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) { 00574 imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); 00575 } 00576 00577 /** 00578 * Create new image pointer from input file (either gif/png, in case the wrong format it is converted by t3lib_div::read_png_gif()) 00579 * 00580 * @param string Absolute filename of the image file from which to start the icon creation. 00581 * @return mixed If success, image pointer, otherwise "-1" 00582 * @access private 00583 * @see t3lib_div::read_png_gif 00584 */ 00585 public static function imagecreatefrom($file) { 00586 $file = t3lib_div::read_png_gif($file, $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']); 00587 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) { 00588 return $file ? imagecreatefrompng($file) : -1; 00589 } else { 00590 return $file ? imagecreatefromgif($file) : -1; 00591 } 00592 } 00593 00594 /** 00595 * Write the icon in $im pointer to $path 00596 * 00597 * @param pointer Pointer to GDlib image resource 00598 * @param string Absolute path to the filename in which to write the icon. 00599 * @return void 00600 * @access private 00601 */ 00602 public static function imagemake($im, $path) { 00603 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) { 00604 @ImagePng($im, $path); 00605 } else { 00606 @ImageGif($im, $path); 00607 } 00608 if (@is_file($path)) { 00609 t3lib_div::fixPermissions($path); 00610 } 00611 } 00612 00613 00614 /********************************************** 00615 * SPRITE ICON API 00616 * 00617 * The Sprite Icon API helps you to quickly get the HTML for any icon you want 00618 * this is typically wrapped in a <span> tag with corresponding CSS classes that 00619 * will be responsible for the 00620 * 00621 * There are three ways to use this API: 00622 * 00623 * 1) for any given TCA record 00624 * $spriteIconHtml = t3lib_iconWorks::getSpriteIconForRecord('pages', $row); 00625 * 00626 * 2) for any given file 00627 * $spriteIconHtml = t3lib_iconWorks::getSpriteIconForFile('myimage.png'); 00628 * 00629 * 3) for any other icon you know the name 00630 * $spriteIconHtml = t3lib_iconWorks::getSpriteIcon('actions-document-open'); 00631 * 00632 **********************************************/ 00633 00634 /** 00635 * This generic method is used throughout the TYPO3 Backend to show icons in any variation which are not 00636 * bound to any file type (see getSpriteIconForFile) or database record (see getSpriteIconForRecord) 00637 * 00638 * Generates a HTML tag with proper CSS classes. The TYPO3 skin has defined these CSS classes 00639 * already to have a pre-defined background image, and the correct background-position to show 00640 * the necessary icon. 00641 * 00642 * @param string $iconName the name of the icon to fetch 00643 * @param array $options an associative array with additional options and attributes for the tag. by default, the key is the name of the attribute, and the value is the parameter string that is set. However, there are some additional special reserved keywords that can be used as keys: "html" (which is the HTML that will be inside the icon HTML tag), "tagName" (which is an alternative tagName than "span"), and "class" (additional class names that will be merged with the sprite icon CSS classes) 00644 * @param array $overlays an associative array with the icon-name as key, and the options for this overlay as an array again (see the parameter $options again) 00645 * @return string the full HTML tag (usually a <span>) 00646 * @access public 00647 */ 00648 public static function getSpriteIcon($iconName, array $options = array(), array $overlays = array()) { 00649 $innerHtml = (isset($options['html']) ? $options['html'] : NULL); 00650 $tagName = (isset($options['tagName']) ? $options['tagName'] : NULL); 00651 00652 // deal with the overlays 00653 if (count($overlays)) { 00654 foreach ($overlays as $overlayIconName => $overlayOptions) { 00655 $overlayOptions['html'] = $innerHtml; 00656 $overlayOptions['class'] = (isset($overlayOptions['class']) ? $overlayOptions['class'] . ' ' : '') . 't3-icon-overlay'; 00657 $innerHtml = self::getSpriteIcon($overlayIconName, $overlayOptions); 00658 } 00659 } 00660 00661 // check if whished icon is available 00662 $iconName = (in_array($iconName, $GLOBALS['TBE_STYLES']['spriteIconApi']['iconsAvailable']) || $iconName == 'empty-empty' ? $iconName : 'status-status-icon-missing'); 00663 00664 // create the CSS class 00665 $options['class'] = self::getSpriteIconClasses($iconName) . (isset($options['class']) ? ' ' . $options['class'] : ''); 00666 00667 unset($options['html']); 00668 unset($options['tagName']); 00669 return self::buildSpriteHtmlIconTag($options, $innerHtml, $tagName); 00670 } 00671 00672 00673 /** 00674 * This method is used throughout the TYPO3 Backend to show icons for a file type 00675 * 00676 * Generates a HTML tag with proper CSS classes. The TYPO3 skin has defined these CSS classes 00677 * already to have a pre-defined background image, and the correct background-position to show 00678 * the necessary icon. 00679 * 00680 * @param string $fileExtension the name of the icon to fetch, can be a file extension, full file path or one of the special keywords "folder" or "mount" 00681 * @param array $options an associative array with additional options and attributes for the tag. by default, the key is the name of the attribute, and the value is the parameter string that is set. However, there are some additional special reserved keywords that can be used as keys: "html" (which is the HTML that will be inside the icon HTML tag), "tagName" (which is an alternative tagName than "span"), and "class" (additional class names that will be merged with the sprite icon CSS classes) 00682 * @return string the full HTML tag (usually a <span>) 00683 * @access public 00684 */ 00685 public static function getSpriteIconForFile($fileExtension, array $options = array()) { 00686 $innerHtml = (isset($options['html']) ? $options['html'] : NULL); 00687 $tagName = (isset($options['tagName']) ? $options['tagName'] : NULL); 00688 00689 // create the CSS class 00690 $options['class'] = self::mapFileExtensionToSpriteIconClass($fileExtension) . (isset($options['class']) ? ' ' . $options['class'] : ''); 00691 00692 unset($options['html']); 00693 unset($options['tagName']); 00694 return self::buildSpriteHtmlIconTag($options, $innerHtml, $tagName); 00695 } 00696 00697 00698 /** 00699 * Generates the spriteicon css classes name for a given path or fileExtension 00700 * usually called from getSpriteIconForFile or ExtJs Provider 00701 * 00702 * @param string fileExtension can be jpg, gif etc, but also be 'mount' or 'folder', but can also be a full path which will be resolved then 00703 * @return string the string of the CSS class, see t3lib_iconworks::$fileSpriteIconNames 00704 * @access private 00705 */ 00706 public static function mapFileExtensionToSpriteIconClass($fileExtension) { 00707 return self::getSpriteIconClasses(self::mapFileExtensionToSpriteIconName($fileExtension)); 00708 } 00709 00710 /** 00711 * Generates the spriteicon name for a given path or fileExtension 00712 * usually called from mapFileExtensionToSpriteIconClass and tceforms 00713 * 00714 * @param string fileExtension can be jpg, gif etc, but also be 'mount' or 'folder', but can also be a full path which will be resolved then 00715 * @return string the string of the CSS class, see t3lib_iconworks::$fileSpriteIconNames 00716 * @access private 00717 */ 00718 public static function mapFileExtensionToSpriteIconName($fileExtension) { 00719 00720 // if the file is a whole file with name etc (mainly, if it has a "." or a "/"), 00721 // then it is checked whether it is a valid directory 00722 if (strpos($fileExtension, '.') !== FALSE || strpos($fileExtension, '/') !== FALSE) { 00723 00724 // check if it is a directory 00725 $filePath = dirname(t3lib_div::getIndpEnv('SCRIPT_FILENAME')) . '/' . $GLOBALS['BACK_PATH'] . $fileExtension; 00726 $path = t3lib_div::resolveBackPath($filePath); 00727 if (is_dir($path) || substr($fileExtension, -1) === '/' || substr($fileExtension, -1) === '\\') { 00728 $fileExtension = 'folder'; 00729 } else { 00730 if (($pos = strrpos($fileExtension, '.')) !== FALSE) { 00731 $fileExtension = strtolower(substr($fileExtension, $pos + 1)); 00732 } else { 00733 $fileExtension = 'default'; 00734 } 00735 } 00736 } 00737 00738 // if the file extension is not valid 00739 // then use the default one 00740 if (!isset(self::$fileSpriteIconNames[$fileExtension])) { 00741 $fileExtension = 'default'; 00742 } 00743 $iconName = self::$fileSpriteIconNames[$fileExtension]; 00744 00745 return $iconName; 00746 } 00747 00748 00749 /** 00750 * This method is used throughout the TYPO3 Backend to show icons for a DB record 00751 * 00752 * Generates a HTML tag with proper CSS classes. The TYPO3 skin has defined these CSS classes 00753 * already to have a pre-defined background image, and the correct background-position to show 00754 * the necessary icon. 00755 * 00756 * @param string $table the TCA table name 00757 * @param array $row the DB record of the TCA table 00758 * @param array $options an associative array with additional options and attributes for the tag. by default, the key is the name of the attribute, and the value is the parameter string that is set. However, there are some additional special reserved keywords that can be used as keys: "html" (which is the HTML that will be inside the icon HTML tag), "tagName" (which is an alternative tagName than "span"), and "class" (additional class names that will be merged with the sprite icon CSS classes) 00759 * @return string the full HTML tag (usually a <span>) 00760 * @access public 00761 */ 00762 public static function getSpriteIconForRecord($table, array $row, array $options = array()) { 00763 $innerHtml = (isset($options['html']) ? $options['html'] : NULL); 00764 $tagName = (isset($options['tagName']) ? $options['tagName'] : NULL); 00765 00766 // overlay this record icon with the status of the row 00767 $overlaySpriteIconName = self::mapRecordOverlayToSpriteIconName($table, $row); 00768 if ($overlaySpriteIconName) { 00769 $overlayOptions = array( 00770 'html' => $innerHtml, 00771 'class' => 't3-icon-overlay' 00772 ); 00773 $innerHtml = self::getSpriteIcon($overlaySpriteIconName, $overlayOptions); 00774 } 00775 00776 // fetch the name for the CSS class, based on the $row 00777 $options['class'] = self::mapRecordTypeToSpriteIconClass($table, $row) . (isset($options['class']) ? ' ' . $options['class'] : ''); 00778 00779 unset($options['html']); 00780 unset($options['tagName']); 00781 return self::buildSpriteHtmlIconTag($options, $innerHtml, $tagName); 00782 } 00783 00784 00785 /** 00786 * this helper functions looks up the column that is used for the type of 00787 * the chosen TCA table. And then fetches the corresponding class 00788 * based on the chosen iconsprite class in this TCA 00789 * The TCA looks up 00790 * - [ctrl][typeicon_column] 00791 * - 00792 * This method solely takes care of the type of this record, not any 00793 * statuses, used for overlays. 00794 * You should not use this directly besides if you need classes for ExtJS iconCls. 00795 * 00796 * see t3lib/stddb/tables.php for an example with the TCA table "pages" 00797 * 00798 * @param string $table the TCA table 00799 * @param array $row the selected record 00800 * @return string the CSS class for the sprite icon of that DB record 00801 * @access private 00802 **/ 00803 public static function mapRecordTypeToSpriteIconClass($table, array $row) { 00804 return self::getSpriteIconClasses(self::mapRecordTypeToSpriteIconName($table, $row)); 00805 } 00806 00807 /** 00808 * this helper functions looks up the column that is used for the type of 00809 * the chosen TCA table. And then fetches the corresponding iconname 00810 * based on the chosen iconsprite class in this TCA 00811 * The TCA looks up 00812 * - [ctrl][typeicon_column] 00813 * - 00814 * This method solely takes care of the type of this record, not any 00815 * statuses, used for overlays. 00816 * You should not use this directly besides if you need it in tceforms/core classes 00817 * 00818 * see t3lib/stddb/tables.php for an example with the TCA table "pages" 00819 * 00820 * @param string $table the TCA table 00821 * @param array $row the selected record 00822 * @return string the CSS class for the sprite icon of that DB record 00823 * @access private 00824 **/ 00825 public static function mapRecordTypeToSpriteIconName($table, array $row) { 00826 $recordType = array(); 00827 $ref = NULL; 00828 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_column'])) { 00829 $column = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column']; 00830 00831 if (isset($row[$column])) { 00832 $recordType[1] = $row[$column]; 00833 } else { 00834 $recordType[1] = 'default'; 00835 } 00836 00837 // workaround to give nav_hide pages a complete different icon 00838 // although it's not a separate doctype 00839 // and to give root-pages an own icon 00840 if ($table === 'pages') { 00841 if ($row['nav_hide']) { 00842 $recordType[2] = $recordType[1] . '-hideinmenu'; 00843 } 00844 if ($row['is_siteroot']) { 00845 $recordType[3] = $recordType[1] . '-root'; 00846 } 00847 if ($row['module']) { 00848 $recordType[4] = 'contains-' . $row['module']; 00849 } 00850 } 00851 00852 if (is_array($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'])) { 00853 foreach ($recordType AS $key => $type) { 00854 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'][$type])) { 00855 $recordType[$key] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'][$type]; 00856 } else { 00857 unset($recordType[$key]); 00858 } 00859 } 00860 $recordType[0] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['default']; 00861 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['mask'])) { 00862 $recordType[5] = str_replace('###TYPE###', $row[$column], $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['mask']); 00863 } 00864 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['userFunc'])) { 00865 $recordType[6] = t3lib_div::callUserFunction($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['userFunc'], array('row' => $row), $ref); 00866 } 00867 } else { 00868 foreach ($recordType AS $key => $type) { 00869 $recordType[$key] = 'tcarecords-' . $table . '-' . $type; 00870 } 00871 $recordType[0] = 'tcarecords-' . $table . '-default'; 00872 } 00873 } else { 00874 if (is_array($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'])) { 00875 $recordType[0] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['default']; 00876 } else { 00877 $recordType[0] = 'tcarecords-' . $table . '-default'; 00878 } 00879 } 00880 krsort($recordType); 00881 foreach ($recordType as $iconName) { 00882 if (in_array($iconName, $GLOBALS['TBE_STYLES']['spriteIconApi']['iconsAvailable'])) { 00883 return $iconName; 00884 } 00885 } 00886 return 'status-status-icon-missing'; 00887 } 00888 00889 00890 /** 00891 * this helper functions checks if the DB record ($row) has any special status 00892 * based on the TCA settings like hidden, starttime etc, and then returns a specific 00893 * Sprite icon class for the overlay of this DB record 00894 * This method solely takes care of the overlay of this record, not any type 00895 * 00896 * Please note that this only returns one overlay, one status, that is prioritized 00897 * by $GLOBALS['TYPO3_CONF_VARS']['BE']['spriteIconRecordOverlayPriorities'] 00898 * We wanted to not have these icons blown over by tons of overlays, so this is limited 00899 * to just one. 00900 * 00901 * see t3lib/config_default.php for the default options, you will find 00902 * $GLOBALS['TYPO3_CONF_VARS']['BE']['spriteIconRecordOverlayNames'] that shows 00903 * the list of CSS classes that will be used for the sprites, mapped to the statuses here 00904 * 00905 * @param string $table the TCA table 00906 * @param array $row the selected record 00907 * @return string the CSS class for the sprite icon of that DB record 00908 * @access private 00909 */ 00910 public static function mapRecordOverlayToSpriteIconName($table, array $row) { 00911 $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl']; 00912 00913 // Calculate for a given record the actual visibility at the moment 00914 $status = array( 00915 'hidden' => FALSE, 00916 'starttime' => FALSE, 00917 'endtime' => FALSE, 00918 'futureendtime' => FALSE, 00919 'fe_group' => FALSE, 00920 'deleted' => FALSE, 00921 'protectedSection' => FALSE, 00922 'nav_hide' => ($row['nav_hide'] ? TRUE : FALSE), 00923 'noIconFound' => ($row['_NO_ICON_FOUND'] ? TRUE : FALSE), 00924 ); 00925 00926 // Icon state based on "enableFields": 00927 if (is_array($tcaCtrl['enablecolumns'])) { 00928 $enCols = $tcaCtrl['enablecolumns']; 00929 // If "hidden" is enabled: 00930 if ($tcaCtrl['enablecolumns']['disabled'] && $row[$tcaCtrl['enablecolumns']['disabled']]) { 00931 $status['hidden'] = TRUE; 00932 } 00933 // If a "starttime" is set and higher than current time: 00934 if ($tcaCtrl['enablecolumns']['starttime'] && $GLOBALS['EXEC_TIME'] < intval($row[$tcaCtrl['enablecolumns']['starttime']])) { 00935 $status['starttime'] = TRUE; 00936 } 00937 00938 // If an "endtime" is set 00939 if ($tcaCtrl['enablecolumns']['endtime']) { 00940 if (intval($row[$tcaCtrl['enablecolumns']['endtime']]) > 0) { 00941 if (intval($row[$tcaCtrl['enablecolumns']['endtime']]) < $GLOBALS['EXEC_TIME']) { 00942 // End-timing applies at this point. 00943 $status['endtime'] = TRUE; 00944 } else { 00945 // End-timing WILL apply in the future for this element. 00946 $status['futureendtime'] = TRUE; 00947 } 00948 } 00949 } 00950 // If a user-group field is set 00951 if ($tcaCtrl['enablecolumns']['fe_group'] && $row[$tcaCtrl['enablecolumns']['fe_group']]) { 00952 $status['fe_group'] = TRUE; 00953 } 00954 } 00955 00956 // If "deleted" flag is set (only when listing records which are also deleted!) 00957 if ($row[$tcaCtrl['delete']]) { 00958 $status['deleted'] = TRUE; 00959 } 00960 00961 // Detecting extendToSubpages (for pages only) 00962 if ($table == 'pages' && $row['extendToSubpages']) { 00963 $status['protectedSection'] = TRUE; 00964 } 00965 00966 00967 // now only show the status with the highest priority 00968 $priorities = $GLOBALS['TBE_STYLES']['spriteIconApi']['spriteIconRecordOverlayPriorities']; 00969 00970 $iconName = ''; 00971 foreach ($priorities as $priority) { 00972 if ($status[$priority]) { 00973 $iconName = $GLOBALS['TBE_STYLES']['spriteIconApi']['spriteIconRecordOverlayNames'][$priority]; 00974 break; 00975 } 00976 } 00977 00978 return $iconName; 00979 } 00980 00981 00982 /** 00983 * generic method to create the final CSS classes based on the sprite icon name 00984 * with the base class and splits the name into parts 00985 * is usually called by the methods that are responsible for fetching the names 00986 * out of the file name, or the record type 00987 * 00988 * @param string $name iconname like 'actions-document-new' 00989 * @return string a list of all CSS classes needed for the HTML tag 00990 * @access public 00991 */ 00992 public static function getSpriteIconClasses($iconName) { 00993 $cssClasses = $baseCssClass = 't3-icon'; 00994 $parts = explode('-', $iconName); 00995 00996 if (count($parts) > 1) { 00997 // will be something like "t3-icon-actions" 00998 $cssClasses .= ' ' . ($baseCssClass . '-' . $parts[0]); 00999 // will be something like "t3-icon-actions-document" 01000 $cssClasses .= ' ' . ($baseCssClass . '-' . $parts[0] . '-' . $parts[1]); 01001 // will be something like "t3-icon-document-new" 01002 $cssClasses .= ' ' . ($baseCssClass . '-' . substr($iconName, strlen($parts[0]) + 1)); 01003 } 01004 return $cssClasses; 01005 } 01006 01007 01008 /** 01009 * low level function that generates the HTML tag for the sprite icon 01010 * is usually called by the three API classes (getSpriteIcon, getSpriteIconForFile, getSpriteIconForRecord) 01011 * it does not care about classes or anything else, but just plainly builds the HTML tag 01012 * 01013 * @param array $tagAttributes an associative array of additional tagAttributes for the HTML tag 01014 * @param string $innerHtml (optional) the content within the tag, a " " by default 01015 * @param string $tagName (optional) the name of the HTML element that should be used (span by default) 01016 */ 01017 protected static function buildSpriteHtmlIconTag(array $tagAttributes, $innerHtml = NULL, $tagName = NULL) { 01018 $innerHtml = ($innerHtml === NULL ? ' ' : $innerHtml); 01019 $tagName = ($tagName === NULL ? 'span' : $tagName); 01020 $attributes = ''; 01021 foreach ($tagAttributes as $attribute => $value) { 01022 $attributes .= ' ' . htmlspecialchars($attribute) . '="' . htmlspecialchars($value) . '"'; 01023 } 01024 return '<' . $tagName . $attributes . '>' . $innerHtml . '</' . $tagName . '>'; 01025 } 01026 01027 } 01028 01029 ?>
1.8.0