Created
May 24, 2011 23:16
-
-
Save Taluu/e2e3c5a66136e0e21869 to your computer and use it in GitHub Desktop.
Projet à reprendre ? :o
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Gestion de feuilles de styles CSS | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
* MA 02110-1301, USA. | |
* | |
* @package Talus' CSS | |
* @author Baptiste "Talus" Clavié <[email protected]> | |
* @copyright ©Talus, Talus' Works 2009+ | |
* @link http://www.talus-works.net Talus' Works | |
* @license http://www.gnu.org/licenses/lgpl.html LGNU Public License 2+ | |
* @version $Id$ | |
*/ | |
/** | |
* Talus' CSS - Singleton | |
* Gère toutes les feuilles de styles Talus_CSS_StyleSheets, et donne aussi la | |
* possibilité d'analyser une feuille de style existante et la retranscrire en | |
* Talus_CSS_StyleSheet : | |
* <code> | |
* <?php $stylesheet = Talus_CSS::__init()->analyze('./way/to/style.css'); ?> | |
* </code> | |
*/ | |
class Talus_CSS { | |
protected | |
$_stylesheets = array(), | |
$_analyzer = null; | |
private static $_inst = null; | |
const VERSION = '1.0.0DEV'; | |
private function __construct() {} | |
private function __clone() {} | |
/** | |
* Récupération de l'instance unique de Talus_CSS | |
* | |
* @return Talus_CSS | |
*/ | |
public static function __init() { | |
if (self::$_inst === null) { | |
self::$_inst = new self; | |
} | |
return self::$_inst; | |
} | |
/** | |
* Parsage d'une feuille CSS $file en Talus_CSS_StyleSheet | |
* | |
* @param string $file Feuille CSS à transformer | |
* @return Talus_CSS_StyleSheet | |
*/ | |
public function analyze($file){ | |
if ($this->_analyzer === null) { | |
$this->_analyzer = Talus_CSS_Analyzer::__init(); | |
} | |
$name = pathinfo($file, PATHINFO_BASENAME); | |
$this->_stylesheets[$name] = $this->_analyzer->analyze($file); | |
return $this->stylesheet($name); | |
} | |
/** | |
* Récupère l'instance de la feuille de style CSS $stylesheet ; | |
* Si elle n'existe pas, la crée. | |
* | |
* @param string $stylesheet Nom de la feuille de Style | |
* @return Talus_CSS_StyleSheet | |
*/ | |
public function stylesheet($stylesheet) { | |
if (!isset($this->_stylesheet[$stylesheet])) { | |
$this->_stylesheet[$stylesheet] = new Talus_CSS_StyleSheet($stylesheet); | |
} | |
return $this->_stylesheet[$stylesheet]; | |
} | |
/** | |
* Compresse la feuille de style $stylesheet | |
* | |
* @param string $stylesheet Nom de la feuille de style à compresser | |
* @return string | |
*/ | |
public function minify($stylesheet) { | |
$stylesheet = (string) $this->stylesheet($stylesheet); | |
$stylesheet = preg_replace('`/\*.*?\*/`s', '', $stylesheet); | |
$stylesheet = preg_replace('`\s+`', ' ', $stylesheet); | |
return $stylesheet; | |
} | |
} | |
/** | |
* Classe mère des sous-classes de Talus' CSS | |
*/ | |
abstract class Talus_CSS_Object { | |
protected | |
$_items = array(), | |
$_name = '', | |
$_slug = null, | |
$_comment = null; | |
/** | |
* Style d'indentation (2 espace ? une \t ?) | |
* | |
* @var string | |
*/ | |
const INDENT = "\t"; | |
/** | |
* Construit l'objet | |
* | |
* @param string $name Nom de l'objet | |
* @return void | |
*/ | |
public function __construct($name = null) { | |
if (!empty($name)) { | |
$this->_name = $name; | |
} | |
} | |
/** | |
* Créé le slug du nom de l'objet, et le renvoi | |
* Méthode venant du projet Jobeet par le tutoriel Symfony | |
* | |
* @link http://www.symfony-project.org Framework Symfony | |
* @return string | |
*/ | |
protected function _slug() { | |
if ($this->_slug === null && !empty($this->_name)) { | |
$slug = preg_replace('`[^\\pL\d]+`u', '-', $this->_name); | |
if (function_exists('iconv')) { | |
$slug = iconv('utf-8', 'us-ascii//TRANSLIT', $slug); | |
} | |
$slug = strtolower($slug); | |
$slug = preg_replace('`[^-\w]+`', '', $slug); | |
if (!$slug) { | |
$slug = 'n-a'; | |
} | |
$this->_slug = $slug; | |
} | |
return $this->_slug; | |
} | |
/** | |
* Commente l'élément courant (ou lui enleve son commentaire), et le renvoit | |
* | |
* @param string $comment Commentaire à ajouter | |
* @return string | |
*/ | |
public function comment($comment = null) { | |
if ($comment !== null) { | |
$this->_comment = empty($comment) ? null : str_replace('*/', '*//*', $comment); | |
} | |
return $this->_comment; | |
} | |
} | |
/** | |
* Représentation d'une feuille de style CSS | |
*/ | |
class Talus_CSS_StyleSheet extends Talus_CSS_Object { | |
protected $_imports = array(); | |
const | |
STYLE = 1, | |
MEDIA = 2, | |
ALL = 3; | |
/** | |
* Constructeur de l'objet | |
* | |
* @param string $name Nom du Style | |
* @param integer $indent Niveau d'indentation | |
*/ | |
public function __construct($name, $indent = 0) { | |
parent::__construct($name); | |
$this->_indent = str_repeat(Talus_CSS_Object::INDENT, abs(floor($indent))); | |
} | |
/** | |
* Ajoute un fichier CSS à importer | |
* | |
* @param string $file Fichier à importer | |
* @return Talus_CSS_StyleSheet | |
*/ | |
public function import($file) { | |
if (!in_array($file, $this->_imports)) { | |
$this->_imports[] = $file; | |
} | |
return $this; | |
} | |
/** | |
* Récupère un Style. Le créé s'il n'existe pas. | |
* | |
* @param string $name Nom du style à récupérer | |
* @return Talus_CSS_Style | |
*/ | |
public function style($name) { | |
$element = $this->get($name, self::STYLE); | |
if ($element === null) { | |
$element = new Talus_CSS_Style($name); | |
$this->_items[$name] = $element; | |
} | |
return $element; | |
} | |
/** | |
* Récupère un Media. Le créé s'il n'existe pas. | |
* | |
* @param string $name Nom du média à récupérer | |
* @return Talus_CSS_Media | |
*/ | |
public function media($name) { | |
$element = $this->get($name, self::MEDIA); | |
if ($element === null) { | |
$element = new Talus_CSS_Media($name); | |
$this->_items[$name] = $element; | |
} | |
return $element; | |
} | |
/** | |
* Récupère un objet Talus_CSS_Element | |
* | |
* @param $name Nom de l'objet à récupérer | |
* @param $type Type de l'objet (Style ? Media ? Les deux ?) | |
* @return Talus_CSS_Element | |
* @throws Exception | |
*/ | |
public function get($name, $type = self::ALL) { | |
static $classes = array( | |
self::STYLE => 'Talus_CSS_Style', | |
self::MEDIA => 'Talus_CSS_Media', | |
self::ALL => 'Talus_CSS_Element' | |
); | |
if (!isset($classes[$type])) { | |
throw new Exception('Wrong type selection for Talus_CSS_Stylesheet->get()'); | |
} | |
foreach (array_keys($this->_items, (string)$name, true) as $key) { | |
if ($this->_items[$key] instanceof $classes[$type]) { | |
return $this->_items[$key]; | |
} | |
} | |
return null; | |
} | |
/** | |
* Représentation de la feuille CSS en string (Méthode magique) | |
* | |
* @return string | |
*/ | |
public function __toString() { | |
$str = ''; | |
if (count($this->_items) > 0) { | |
$str .= '/*'; | |
if ($this->comment() !== null) { | |
$str .= "\n * " . implode("\n * ", explode("\n", $this->comment())) . "\n *"; | |
} | |
$str .= "\n * @generator Talus' CSS\n * @link http://www.talus-works.net Talus' Works\n */"; | |
if (count($this->_imports) > 0) { | |
$str .= "\n\n /*\n * CSS Imports\n */\n"; | |
foreach ($this->_imports as &$import) { | |
$str .= "\n@import \"{$import}\";"; | |
} | |
} | |
$str .= "\n\n /*\n * Stylesheet's Body\n */"; | |
foreach ($this->_items as &$item) { | |
$str .= "\n\n" . ((string) $item); | |
} | |
} | |
return $str; | |
} | |
/** | |
* Permet de sauvegarder la feuille CSS dans un fichier | |
* | |
* @param string $file Fichier CSS (si null, utilisation de $this->_slug). | |
* @param bool $compress Si il faut ou non compresser le fichier (false par défaut) | |
* @return Talus_CSS_StyleSheet | |
* @throws Exception | |
*/ | |
public function save($file = null, $compress = false){ | |
if ($file === null) { | |
$file = $this->_slug(); | |
} | |
$lockFile = dirname($file) . '/__css_flock__.' . sha1($file); | |
if (!@fclose(fopen($lockFile, 'x'))){ | |
throw new Exception("Couldn't save stylesheet {$this->_name} : Permission Denied."); | |
return $this; | |
} | |
file_put_contents($file, $compress ? Talus_CSS::__init()->minify($file) : (string) $this); | |
chmod($file, 0664); | |
unlink($lockFile); | |
return $this; | |
} | |
} | |
/** | |
* Désigne un élément d'une feuille de style | |
*/ | |
interface Talus_CSS_Element { | |
public function __toString(); | |
} | |
/** | |
* Gestion des balises @media | |
*/ | |
class Talus_CSS_Media extends Talus_CSS_Object implements Talus_CSS_Element { | |
/** | |
* Récupère un style du média, le créé s'il n'existe pas | |
* | |
* @param string $name Nom du style | |
* @return Talus_CSS_Style | |
*/ | |
public function style($name) { | |
if (!isset($this->_items[$name])) { | |
$this->_items[$name] = new Talus_CSS_Style($name, 1); | |
} | |
return $this->_items[$name]; | |
} | |
/** | |
* Formatte l'affichage pour le média | |
* | |
* @return string | |
*/ | |
public function __toString() { | |
$str = ''; | |
if (count($this->_items) == 0) { | |
return $str; | |
} | |
if ($this->comment() !== null) { | |
$str .= sprintf("/*%s*/\n", $this->comment()); | |
} | |
$str .= sprintf("@media %s {", $this->_name); | |
foreach ($this->_items as $item) { | |
$str .= sprintf("\n%s\n", (string) $item); | |
} | |
$str .= '}'; | |
return $str; | |
} | |
} | |
/** | |
* Gestion des styles (classes, id, par balisage...) | |
*/ | |
class Talus_CSS_Style extends Talus_CSS_Object implements Talus_CSS_Element { | |
protected $indent = ''; | |
/** | |
* Constructeur de l'objet | |
* | |
* @param string $name Nom du Style | |
* @param integer $indent Niveau d'indentation | |
*/ | |
public function __construct($name, $indent = 0) { | |
parent::__construct($name); | |
$this->_indent = str_repeat(Talus_CSS_Object::INDENT, abs(floor($indent))); | |
} | |
/** | |
* Ajoute la propriété $name et lui donne la valeur $value | |
* | |
* @param string $name Nom de la propriété CSS | |
* @param string $value Valeur (si null, suppression) | |
* @return Talus_CSS_Style | |
* @throws Exception | |
*/ | |
public function prop($name, $value = null) { | |
$name = strtolower($name); | |
if (isset($this->_items[$name]) && empty($value)) { | |
unset($this->_items[$name]); | |
} elseif (preg_match('`^-?[a-z][a-z-]+$`i', $name)) { | |
$this->_items[$name] = $value; | |
} else { | |
throw new Exception("Invalid prop name for Talus_CSS_Style->prop()"); | |
} | |
return $this; | |
} | |
/** | |
* Formatte le style en tant que string | |
* | |
* @return string | |
*/ | |
public function __toString() { | |
$str = ''; | |
if (count($this->_items) > 0) { | |
if ($this->comment() !== null) { | |
$str = sprintf("/*%s*/\n", $this->comment()); | |
} | |
$str .= sprintf('%1$s%2$s {', $this->_indent, $this->_name); | |
$props = array(); | |
foreach ($this->_items as $prop => $value) { | |
$props[] = sprintf('%1$s:%2$s;', $prop, $value); | |
} | |
$str .= sprintf('%1$s%3$s%2$s%1$s}', "\n{$this->_indent}", | |
implode($props, "\n" . $this->_indent . Talus_CSS_Object::INDENT), | |
Talus_CSS_Object::INDENT); | |
} | |
return $str; | |
} | |
} | |
/** | |
* Analyseur CSS - Singleton | |
* Parse un fichier CSS pour le transformer objets Talus' CSS | |
*/ | |
class Talus_CSS_Analyzer { | |
private static $_inst = null; | |
/** | |
* Récupération de l'unique instance de Talus_CSS_Analyzer | |
* | |
* @return Talus_CSS_Analyzer | |
*/ | |
public static function __init() { | |
if (self::$_inst === null) { | |
self::$_inst = new self; | |
} | |
return self::$_inst; | |
} | |
private function __construct() {} | |
private function __clone() {} | |
/** | |
* Analyse du fichier CSS donné, et le rend interpretable par Talus_CSS | |
* | |
* @param string $file Fichier à analyser | |
* @return Talus_CSS_StyleSheet | |
*/ | |
public function analyze($file) {} | |
/** | |
* Analyse du fichier CSS donné, et le rend interpretable par Talus_CSS | |
* Alias pour $this->analyze pour le __invoke() de PHP > 5.3. | |
* <code> | |
* <?php | |
* $o = Talus_CSS_Analyzer::__init(); | |
* $stylesheetFile = $o('file.css'); | |
* ?> | |
* </code> | |
* | |
* @param string $file Fichier à analyser | |
* @return Talus_CSS_StyleSheet | |
*/ | |
public function __invoke($file) { | |
return $this->analyze($file); | |
} | |
} | |
/* | |
* EOF | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment