$l2) { $ratio = ($l1 + 0.05) / ($l2 + 0.05); } else { $ratio = ($l2 + 0.05) / ($l1 + 0.05); } return $ratio; } /** * Compute WCAG contrast ration level * * @param float $ratio computed ratio between foreground and backround color * @param string $size font size as defined in CSS * @param boolean $bold true if bold font * * @return string WCAG contrast ratio level (AAA, AA or ) */ public static function contrastRatioLevel($ratio, $size, $bold = false) { if ($size == '') { return ''; } // Eval font size in em (assume base font size in pixels equal to 16) if (preg_match('/^([0-9.]+)\s*(%|pt|px|em|ex|rem)?$/', $size, $m)) { if (empty($m[2])) { $m[2] = 'em'; } } else { return ''; } switch ($m[2]) { case '%': $s = (float) $m[1] / 100; break; case 'pt': $s = (float) $m[1] / 12; break; case 'px': $s = (float) $m[1] / 16; break; case 'em': $s = (float) $m[1]; break; case 'ex': $s = (float) $m[1] / 2; break; default: return ''; } $large = ((($s > 1.5) && ($bold == false)) || (($s > 1.2) && ($bold == true))); // Check ratio if ($ratio > 7) { return 'AAA'; } elseif (($ratio > 4.5) && $large) { return 'AAA'; } elseif ($ratio > 4.5) { return 'AA'; } elseif (($ratio > 3) && $large) { return 'AA'; } return ''; } /** * Return full information about constrat ratio * * @param string $color text color * @param string $background background color * @param string $size font size * @param boolean $bold bold font * * @return string contrast ratio including WCAG level */ public static function contrastRatio($color, $background, $size = '', $bold = false) { if (($color != '') && ($background != '')) { $ratio = self::computeContrastRatio($color, $background); $level = self::contrastRatioLevel($ratio, $size, $bold); return sprintf(__('ratio %.1f'), $ratio) . ($level != '' ? ' ' . sprintf(__('(%s)'), $level) : ''); } return ''; } /** * Check font size * * @param string $s font size * * @return string checked font size */ public static function adjustFontSize($s) { if (preg_match('/^([0-9.]+)\s*(%|pt|px|em|ex|rem)?$/', $s, $m)) { if (empty($m[2])) { $m[2] = 'em'; } return $m[1] . $m[2]; } return; } /** * Check object position, should be x:y * * @param string $p position * * @return string checked position */ public static function adjustPosition($p) { if (!preg_match('/^[0-9]+(:[0-9]+)?$/', $p)) { return; } $p = explode(':', $p); return $p[0] . (count($p) == 1 ? ':0' : ':' . $p[1]); } /** * Check a CSS color * * @param string $c CSS color * * @return string checked CSS color */ public static function adjustColor($c) { if ($c === '') { return ''; } $c = strtoupper($c); if (preg_match('/^[A-F0-9]{3,6}$/', $c)) { $c = '#' . $c; } if (preg_match('/^#[A-F0-9]{6}$/', $c)) { return $c; } if (preg_match('/^#[A-F0-9]{3,}$/', $c)) { return '#' . substr($c, 1, 1) . substr($c, 1, 1) . substr($c, 2, 1) . substr($c, 2, 1) . substr($c, 3, 1) . substr($c, 3, 1); } return ''; } /** * Check and clean CSS * * @param string $css CSS to be checked * * @return string checked CSS */ public static function cleanCSS($css) { // TODO ? return $css; } /** * Return real path of a user defined CSS * * @param string $folder CSS folder * * @return string real path of CSS */ public static function cssPath($folder) { global $core; return path::real($core->blog->public_path) . '/' . $folder; } /** * Retirn URL of a user defined CSS * * @param string $folder CSS folder * * @return string CSS URL */ public static function cssURL($folder) { global $core; return $core->blog->settings->system->public_url . '/' . $folder; } /** * Check if user defined CSS may be written * * @param string $folder CSS folder * @param boolean $create create CSS folder if necessary * * @return boolean true if CSS folder exists and may be written, else false */ public static function canWriteCss($folder, $create = false) { global $core; $public = path::real($core->blog->public_path); $css = self::cssPath($folder); if (!is_dir($public)) { $core->error->add(__('The \'public\' directory does not exist.')); return false; } if (!is_dir($css)) { if (!is_writable($public)) { $core->error->add(sprintf(__('The \'%s\' directory cannot be modified.'), 'public')); return false; } if ($create) { files::makeDir($css); } return true; } if (!is_writable($css)) { $core->error->add(sprintf(__('The \'%s\' directory cannot be modified.'), 'public/' . $folder)); return false; } return true; } /** * Store CSS property value in associated array * * @param array $css CSS associated array * @param string $selector selector * @param string $prop property * @param string $value value */ public static function prop(&$css, $selector, $prop, $value) { if ($value) { $css[$selector][$prop] = $value; } } /** * Store background image property in CSS associated array * * @param string $folder image folder * @param array $css CSS associated array * @param string $selector selector * @param boolean $value false for default, true if image should be set * @param string $image image filename */ public static function backgroundImg($folder, &$css, $selector, $value, $image) { $file = self::imagesPath($folder) . '/' . $image; if ($value && file_exists($file)) { $css[$selector]['background-image'] = 'url(' . self::imagesURL($folder) . '/' . $image . ')'; } } /** * Write CSS file * * @param string $folder CSS folder * @param string $theme CSS filename * @param string $css CSS file content */ public static function writeCss($folder, $theme, $css) { file_put_contents(self::cssPath($folder) . '/' . $theme . '.css', $css); } /** * Delete CSS file * * @param string $folder CSS folder * @param string $theme CSS filename to be removed */ public static function dropCss($folder, $theme) { $file = path::real(self::cssPath($folder) . '/' . $theme . '.css'); if (is_writable(dirname($file))) { @unlink($file); } } /** * Return public URL of user defined CSS * * @param string $folder CSS folder * * @return string CSS file URL */ public static function publicCssUrlHelper($folder) { $theme = $GLOBALS['core']->blog->settings->system->theme; $url = self::cssURL($folder); $path = self::cssPath($folder); if (file_exists($path . '/' . $theme . '.css')) { return $url . '/' . $theme . '.css'; } return; } /** * Return real path of folder images * * @param string $folder images folder * * @return string real path of folder */ public static function imagesPath($folder) { global $core; return path::real($core->blog->public_path) . '/' . $folder; } /** * Return URL of images folder * * @param string $folder images folder * * @return string URL of images folder */ public static function imagesURL($folder) { global $core; return $core->blog->settings->system->public_url . '/' . $folder; } /** * Check if images folder exists and may be written * * @param string $folder images folder * @param boolean $create create the folder if not exists * * @return boolean true if folder exists and may be written */ public static function canWriteImages($folder, $create = false) { global $core; $public = path::real($core->blog->public_path); $imgs = self::imagesPath($folder); if (!function_exists('imagecreatetruecolor') || !function_exists('imagepng') || !function_exists('imagecreatefrompng')) { $core->error->add(__('At least one of the following functions is not available: ' . 'imagecreatetruecolor, imagepng & imagecreatefrompng.')); return false; } if (!is_dir($public)) { $core->error->add(__('The \'public\' directory does not exist.')); return false; } if (!is_dir($imgs)) { if (!is_writable($public)) { $core->error->add(sprintf(__('The \'%s\' directory cannot be modified.'), 'public')); return false; } if ($create) { files::makeDir($imgs); } return true; } if (!is_writable($imgs)) { $core->error->add(sprintf(__('The \'%s\' directory cannot be modified.'), 'public/' . $folder)); return false; } return true; } /** * Upload an image in images folder * * @param string $folder images folder * @param string $f selected image file (as $_FILES[]) * @param int $width check accurate width of uploaded image if <> 0 * * @return string full pathname of uploaded image */ public static function uploadImage($folder, $f, $width = 0) { if (!self::canWriteImages($folder, true)) { throw new Exception(__('Unable to create images.')); } $name = $f['name']; $type = files::getMimeType($name); if ($type != 'image/jpeg' && $type != 'image/png') { throw new Exception(__('Invalid file type.')); } $dest = self::imagesPath($folder) . '/uploaded' . ($type == 'image/png' ? '.png' : '.jpg'); if (@move_uploaded_file($f['tmp_name'], $dest) === false) { throw new Exception(__('An error occurred while writing the file.')); } if ($width) { $s = getimagesize($dest); if ($s[0] != $width) { throw new Exception(sprintf(__('Uploaded image is not %s pixels wide.'), $width)); } } return $dest; } /** * Delete an image from images folder (with its thumbnails if any) * * @param string $folder images folder * @param string $img image filename */ public static function dropImage($folder, $img) { global $core; $img = path::real(self::imagesPath($folder) . '/' . $img); if (is_writable(dirname($img))) { // Delete thumbnails if any try { $media = new dcMedia($core); $media->imageThumbRemove($img); } catch (Exception $e) { $core->error->add($e->getMessage()); } // Delete image @unlink($img); } } }