Source of file SassScriptFunction.php
Size: 8,263 Bytes - Last Modified: 2021-12-23T10:32:55+00:00
/var/www/docs.ssmods.com/process/src/code/phpsass/script/SassScriptFunction.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 | <?php /** * SassScriptFunction class file. * @author Chris Yates <chris.l.yates@gmail.com> * @copyright Copyright (c) 2010 PBM Web Development * @license http://phamlp.googlecode.com/files/license.txt * @package PHamlP * @subpackage Sass.script */ require_once('SassScriptFunctions.php'); /** * SassScriptFunction class. * Preforms a SassScript function. * @package PHamlP * @subpackage Sass.script */ class SassScriptFunction { /**@#+ * Regexes for matching and extracting functions and arguments */ const MATCH = '/^(((-\w)|(\w))[-\w]*)\(/'; const MATCH_FUNC = '/^((?:(?:-\w)|(?:\w))[-\w]*)\((.*)\)/'; const SPLIT_ARGS = '/\s*((?:[\'"].*?["\'])|(?:.+?(?:\(.*\).*?)?))\s*(?:,|$)/'; const NAME = 1; const ARGS = 2; private $name; private $args; public static $context; /** * SassScriptFunction constructor * @param string name of the function * @param array arguments for the function * @return SassScriptFunction */ public function __construct($name, $args) { $this->name = $name; $this->args = $args; } private function process_arguments($input) { if (is_array($input)) { $output = array(); foreach ($input as $k => $token) { $output[$k] = trim($this->process_arguments($token), '\'"'); } return $output; } $token = $input; if (is_null($token)) return ' '; if (!is_object($token)) return (string) $token; if (method_exists($token, 'toString')) return $token->toString(); if (method_exists($token, '__toString')) return $token->__toString(); if (method_exists($token, 'perform')) return $token->perform(); return ''; } /** * Evaluates the function. * Look for a user defined function first - this allows users to override * pre-defined functions, then try the pre-defined functions. * @return Function the value of this Function */ public function perform() { self::$context = new SassContext(SassScriptParser::$context); $name = preg_replace('/[^a-z0-9_]/', '_', strtolower($this->name)); $args = $this->process_arguments($this->args); foreach ($this->args as $k => $v) { if (!is_numeric($k)) { self::$context->setVariable($k, $v); } } try { if (SassScriptParser::$context->hasFunction($this->name)) { $return = SassScriptParser::$context->getFunction($this->name)->execute(SassScriptParser::$context, $this->args); return $return; } else if (SassScriptParser::$context->hasFunction($name)) { $return = SassScriptParser::$context->getFunction($name)->execute(SassScriptParser::$context, $this->args); return $return; } } catch (Exception $e) { throw $e; } if (isset(SassParser::$functions) && count(SassParser::$functions)) { foreach (SassParser::$functions as $fn => $callback) { if (($fn == $name || $fn == $this->name) && function_exists($callback)) { $result = call_user_func_array($callback, $args); if (!is_object($result)) { $lexed = SassScriptLexer::$instance->lex($result, self::$context); if (count($lexed) === 1) { return $lexed[0]; } return new SassString(implode('', $this->process_arguments($lexed))); } return $result; } } } if (method_exists('SassScriptFunctions', $name) || method_exists('SassScriptFunctions', $name = '_' . $name)) { $sig = self::get_reflection(array('SassScriptFunctions', $name)); list($args) = self::fill_parameters($sig, $this->args, SassScriptParser::$context, $this); return call_user_func_array(array('SassScriptFunctions', $name), $args); } foreach ($this->args as $i => $arg) { if (is_object($arg) && isset($arg->quote)) { $args[$i] = $arg->toString(); } if (!is_numeric($i) && SassScriptParser::$context->hasVariable($i)) { $args[$i] = SassScriptParser::$context->getVariable($i); } } // CSS function: create a SassString that will emit the function into the CSS return new SassString($this->name . '(' . join(', ', $args) . ')'); } /** * Imports files in the specified directory. * @param string path to directory to import * @return array filenames imported */ private function import($dir) { $files = array(); foreach (array_slice(scandir($dir), 2) as $file) { if (is_file($dir . DIRECTORY_SEPARATOR . $file)) { $files[] = $file; require_once($dir . DIRECTORY_SEPARATOR . $file); } } // foreach return $files; } /** * Returns a value indicating if a token of this type can be matched at * the start of the subject string. * @param string the subject string * @return mixed match at the start of the string or false if no match */ public static function isa($subject) { if (!preg_match(self::MATCH, $subject, $matches)) return false; $match = $matches[0]; $paren = 1; $strpos = strlen($match); $strlen = strlen($subject); $subject_str = (string) $subject; while($paren && $strpos < $strlen) { $c = $subject_str[$strpos++]; $match .= $c; if ($c === '(') { $paren += 1; } elseif ($c === ')') { $paren -= 1; } } return $match; } public static function extractArgs($string, $include_null = TRUE) { $args = array(); $arg = ''; $paren = 0; $strpos = 0; $strlen = strlen($string); $list = SassList::_build_list($string, ','); $return = array(); foreach ($list as $k => $value) { if (strpos($value, ':') !== false && preg_match(SassVariableNode::MATCH, $value, $match)) { $return[$match[SassVariableNode::NAME]] = $match[SassVariableNode::VALUE]; } else if(substr($value, 0, 1) == '$' && $include_null) { $return[str_replace('$', '', $value)] = NULL; } elseif ($include_null || $value !== NULL) { $return[] = $value; } } return $return; } public static function get_reflection($method) { if (is_array($method)) { $class = new ReflectionClass($method[0]); $function = $class->getMethod($method[1]); } else { $function = new ReflectionFunction($method); } $return = array(); foreach ($function->getParameters() as $parameter) { $default = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : NULL; if ($default !== NULL) { $parsed = is_bool($default) ? new SassBoolean($default) : SassScriptParser::$instance->evaluate($default, new SassContext()); $parsed = ($parsed === NULL) ? new SassString($default) : $parsed; } else { $parsed = $default; } $return[$parameter->getName()] = $parsed; # we evaluate the defaults to get Sass objects. } return $return; } public static function fill_parameters($required, $provided, $context, $source) { $context = new SassContext($context); $_required = array_merge(array(), $required); // need to array_merge? $fill = $_required; foreach ($required as $name=>$default) { // we require that named variables provide a default. if (isset($provided[$name]) && $default !== NULL) { $_required[$name] = $provided[$name]; unset($provided[$name]); unset($required[$name]); } } foreach ($required as $name=>$default) { if (count($provided)) { $arg = array_shift($provided); } elseif ($default !== NULL) { $arg = $default; } else { throw new SassMixinNodeException("Function::$name: Required variable ($name) not given.\nFunction defined: " . $source->token->filename . '::' . $source->token->line . "\nFunction used", $source); } $_required[$name] = $arg; } $_required = array_merge($_required, $provided); // any remaining args get tacked onto the end foreach ($_required as $key => $value) { if (!is_object($value)) { $_required[$key] = SassScriptParser::$instance->evaluate($value, $context); } } return array($_required, $context); } } |