From 25e82b3d1abee899a6fba36c7aab0b3875ea6d06 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 1 Feb 2013 12:46:08 -0500 Subject: [PATCH 1/3] ViewRenderer WIP --- framework/base/Application.php | 9 +++++ framework/base/View.php | 53 ++++++++++++++++++++++++++++ framework/base/ViewRenderer.php | 78 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 framework/base/ViewRenderer.php diff --git a/framework/base/Application.php b/framework/base/Application.php index f64e352..40e8437 100644 --- a/framework/base/Application.php +++ b/framework/base/Application.php @@ -359,6 +359,15 @@ class Application extends Module } /** + * Returns the view renderer. + * @return ViewRenderer the view renderer used by this application. + */ + public function getViewRenderer() + { + return $this->getComponent('viewRenderer'); + } + + /** * Sets default path aliases. */ public function registerDefaultAliases() diff --git a/framework/base/View.php b/framework/base/View.php index dccfb26..cd6e070 100644 --- a/framework/base/View.php +++ b/framework/base/View.php @@ -153,6 +153,59 @@ class View extends Component } /** + * Renders a view file. + * + * @param string $viewFile view file path + * @param array $data data to be extracted and made available to the view + * @param boolean $return whether the rendering result should be returned instead of being echoed + * @return string the rendering result. Null if the rendering result is not required. + * @throws CException if the view file does not exist + */ + public function renderFile($viewFile, $data = null, $return = false) + { + $widgetCount = count($this->_widgetStack); + if (($renderer = Yii::$application->getViewYii::app()->getViewRenderer()) !== null && $renderer->fileExtension === '.' . CFileHelper::getExtension($viewFile)) { + $content = $renderer->renderFile($this, $viewFile, $data, $return); + } else { + $content = $this->renderInternal($viewFile, $data, $return); + } + if (count($this->_widgetStack) === $widgetCount) { + return $content; + } else { + $widget = end($this->_widgetStack); + throw new CException(Yii::t('yii', '{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.', + array('{controller}' => get_class($this), '{view}' => $viewFile, '{widget}' => get_class($widget)))); + } + } + + /** + * Renders a view file. + * This method includes the view file as a PHP script + * and captures the display result if required. + * @param string $_viewFile_ view file + * @param array $_data_ data to be extracted and made available to the view file + * @param boolean $_return_ whether the rendering result should be returned as a string + * @return string the rendering result. Null if the rendering result is not required. + */ + public function renderInternal($_viewFile_, $_data_ = null, $_return_ = false) + { + // we use special variable names here to avoid conflict when extracting data + if (is_array($_data_)) { + extract($_data_, EXTR_PREFIX_SAME, 'data'); + } else { + $data = $_data_; + } + if ($_return_) { + ob_start(); + ob_implicit_flush(false); + require($_viewFile_); + return ob_get_clean(); + } else { + require($_viewFile_); + } + } + + /** * Creates a widget. * This method will use [[Yii::createObject()]] to create the widget. * @param string $class the widget class name or path alias diff --git a/framework/base/ViewRenderer.php b/framework/base/ViewRenderer.php new file mode 100644 index 0000000..4044edf --- /dev/null +++ b/framework/base/ViewRenderer.php @@ -0,0 +1,78 @@ + $sourceFile))); + } + $viewFile = $this->getViewFile($sourceFile); + if (@filemtime($sourceFile) > @filemtime($viewFile)) { + $this->generateViewFile($sourceFile, $viewFile); + @chmod($viewFile, $this->filePermission); + } + return $context->renderInternal($viewFile, $data, $return); + } + + /** + * Generates the resulting view file path. + * @param string $file source view file path + * @return string resulting view file path + */ + protected function getViewFile($file) + { + if ($this->useRuntimePath) { + $crc = sprintf('%x', crc32(get_class($this) . Yii::getVersion() . dirname($file))); + $viewFile = Yii::app()->getRuntimePath() . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $crc . DIRECTORY_SEPARATOR . basename($file); + if (!is_file($viewFile)) { + @mkdir(dirname($viewFile), $this->filePermission, true); + } + return $viewFile; + } else { + return $file . 'c'; + } + } +} From e3c85b478ea06a18f87256ae0b087055914a7f86 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 1 Feb 2013 14:55:37 -0500 Subject: [PATCH 2/3] Finished ViewRenderer. --- framework/base/View.php | 83 +++++++++++++-------------------------- framework/base/ViewRenderer.php | 86 ++++++++++------------------------------- todo.md | 3 ++ 3 files changed, 50 insertions(+), 122 deletions(-) diff --git a/framework/base/View.php b/framework/base/View.php index cd6e070..410e3c5 100644 --- a/framework/base/View.php +++ b/framework/base/View.php @@ -137,72 +137,43 @@ class View extends Component /** * Renders a view file. - * This method will extract the given parameters and include the view file. - * It captures the output of the included view file and returns it as a string. - * @param string $_file_ the view file. - * @param array $_params_ the parameters (name-value pairs) that will be extracted and made available in the view file. - * @return string the rendering result - */ - public function renderFile($_file_, $_params_ = array()) - { - ob_start(); - ob_implicit_flush(false); - extract($_params_, EXTR_OVERWRITE); - require($_file_); - return ob_get_clean(); - } - - /** - * Renders a view file. * - * @param string $viewFile view file path - * @param array $data data to be extracted and made available to the view - * @param boolean $return whether the rendering result should be returned instead of being echoed - * @return string the rendering result. Null if the rendering result is not required. - * @throws CException if the view file does not exist + * If a [[ViewRenderer|view renderer]] is installed, this method will try to use the view renderer + * to render the view file. Otherwise, it will simply include the view file, capture its output + * and return it as a string. + * + * @param string $file the view file. + * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file. + * @return string the rendering result */ - public function renderFile($viewFile, $data = null, $return = false) + public function renderFile($file, $params = array()) { - $widgetCount = count($this->_widgetStack); - if (($renderer = Yii::$application->getViewYii::app()->getViewRenderer()) !== null && $renderer->fileExtension === '.' . CFileHelper::getExtension($viewFile)) { - $content = $renderer->renderFile($this, $viewFile, $data, $return); - } else { - $content = $this->renderInternal($viewFile, $data, $return); - } - if (count($this->_widgetStack) === $widgetCount) { - return $content; + $renderer = Yii::$application->getViewRenderer(); + if ($renderer !== null) { + return $renderer->render($this, $file, $params); } else { - $widget = end($this->_widgetStack); - throw new CException(Yii::t('yii', '{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.', - array('{controller}' => get_class($this), '{view}' => $viewFile, '{widget}' => get_class($widget)))); + return $this->renderPhpFile($file, $params); } } /** - * Renders a view file. - * This method includes the view file as a PHP script - * and captures the display result if required. - * @param string $_viewFile_ view file - * @param array $_data_ data to be extracted and made available to the view file - * @param boolean $_return_ whether the rendering result should be returned as a string - * @return string the rendering result. Null if the rendering result is not required. + * Renders a view file as a PHP script. + * + * This method treats the view file as a PHP script and includes the file. + * It extracts the given parameters and makes them available in the view file. + * The method captures the output of the included view file and returns it as a string. + * + * @param string $_file_ the view file. + * @param array $_params_ the parameters (name-value pairs) that will be extracted and made available in the view file. + * @return string the rendering result */ - public function renderInternal($_viewFile_, $_data_ = null, $_return_ = false) + public function renderPhpFile($_file_, $_params_ = array()) { - // we use special variable names here to avoid conflict when extracting data - if (is_array($_data_)) { - extract($_data_, EXTR_PREFIX_SAME, 'data'); - } else { - $data = $_data_; - } - if ($_return_) { - ob_start(); - ob_implicit_flush(false); - require($_viewFile_); - return ob_get_clean(); - } else { - require($_viewFile_); - } + ob_start(); + ob_implicit_flush(false); + extract($_params_, EXTR_OVERWRITE); + require($_file_); + return ob_get_clean(); } /** diff --git a/framework/base/ViewRenderer.php b/framework/base/ViewRenderer.php index 4044edf..ecb216d 100644 --- a/framework/base/ViewRenderer.php +++ b/framework/base/ViewRenderer.php @@ -1,78 +1,32 @@ + * @since 2.0 */ abstract class ViewRenderer extends Component { /** - * @var boolean whether to store the parsing results in the application's - * runtime directory. Defaults to true. If false, the parsing results will - * be saved as files under the same directory as the source view files and the - * file names will be the source file names appended with letter 'c'. - */ - public $useRuntimePath = true; - /** - * @var integer the chmod permission for temporary directories and files - * generated during parsing. Defaults to 0755 (owner rwx, group rx and others rx). - */ - public $filePermission = 0755; - /** - * @var string the extension name of the view file. Defaults to '.php'. - */ - public $fileExtension = '.php'; - - /** - * Parses the source view file and saves the results as another file. - * @param string $sourceFile the source view file path - * @param string $viewFile the resulting view file path - */ - abstract protected function generateViewFile($sourceFile, $viewFile); - - /** * Renders a view file. - * This method is required by {@link IViewRenderer}. - * @param CBaseController $context the controller or widget who is rendering the view file. - * @param string $sourceFile the view file path - * @param mixed $data the data to be passed to the view - * @param boolean $return whether the rendering result should be returned - * @return mixed the rendering result, or null if the rendering result is not needed. - */ - public function renderFile($context, $sourceFile, $data, $return) - { - if (!is_file($sourceFile) || ($file = realpath($sourceFile)) === false) { - throw new CException(Yii::t('yii', 'View file "{file}" does not exist.', array('{file}' => $sourceFile))); - } - $viewFile = $this->getViewFile($sourceFile); - if (@filemtime($sourceFile) > @filemtime($viewFile)) { - $this->generateViewFile($sourceFile, $viewFile); - @chmod($viewFile, $this->filePermission); - } - return $context->renderInternal($viewFile, $data, $return); - } - - /** - * Generates the resulting view file path. - * @param string $file source view file path - * @return string resulting view file path + * + * This method is invoked by [[View]] whenever it tries to render a view. + * Child classes must implement this method to render the given view file. + * + * @param View $view the view object used for rendering the file. + * @param string $file the view file. + * @param array $params the parameters to be passed to the view file. + * @return string the rendering result */ - protected function getViewFile($file) - { - if ($this->useRuntimePath) { - $crc = sprintf('%x', crc32(get_class($this) . Yii::getVersion() . dirname($file))); - $viewFile = Yii::app()->getRuntimePath() . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $crc . DIRECTORY_SEPARATOR . basename($file); - if (!is_file($viewFile)) { - @mkdir(dirname($viewFile), $this->filePermission, true); - } - return $viewFile; - } else { - return $file . 'c'; - } - } + abstract public function render($view, $file, $params); } diff --git a/todo.md b/todo.md index 7517b07..60e37c5 100644 --- a/todo.md +++ b/todo.md @@ -5,6 +5,9 @@ * mongodb (put it under framework/db/mongodb) * key-value-based (should allow storage-specific methods additionally to generic ones) * redis (put it under framework/db/redis or perhaps framework/caching?) +- base + * TwigViewRenderer + * SmartyViewRenderer - logging * WebTarget (TBD after web is in place): should consider using javascript and make it into a toolbar * ProfileTarget (TBD after web is in place): should consider using javascript and make it into a toolbar From dcca0bcf44a526b9619fc3333c20b08e47f0087b Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 1 Feb 2013 15:16:38 -0500 Subject: [PATCH 3/3] moved ConsoleColor. --- framework/console/View.php | 480 ---------------------------------------- framework/util/ConsoleColor.php | 480 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 480 insertions(+), 480 deletions(-) delete mode 100644 framework/console/View.php create mode 100644 framework/util/ConsoleColor.php diff --git a/framework/console/View.php b/framework/console/View.php deleted file mode 100644 index 38f0b94..0000000 --- a/framework/console/View.php +++ /dev/null @@ -1,480 +0,0 @@ - - * @since 2.0 - */ -class View extends \yii\base\Component -{ - const FG_BLACK = 30; - const FG_RED = 31; - const FG_GREEN = 32; - const FG_YELLOW = 33; - const FG_BLUE = 34; - const FG_PURPLE = 35; - const FG_CYAN = 36; - const FG_GREY = 37; - - const BG_BLACK = 40; - const BG_RED = 41; - const BG_GREEN = 42; - const BG_YELLOW = 43; - const BG_BLUE = 44; - const BG_PURPLE = 45; - const BG_CYAN = 46; - const BG_GREY = 47; - - const BOLD = 1; - const ITALIC = 3; - const UNDERLINE = 4; - const BLINK = 5; - const NEGATIVE = 7; - const CONCEALED = 8; - const CROSSED_OUT = 9; - const FRAMED = 51; - const ENCIRCLED = 52; - const OVERLINED = 53; - - /** - * Moves the terminal cursor up by sending ANSI control code CUU to the terminal. - * If the cursor is already at the edge of the screen, this has no effect. - * @param integer $rows number of rows the cursor should be moved up - */ - public static function moveCursorUp($rows=1) - { - echo "\033[" . (int) $rows . 'A'; - } - - /** - * Moves the terminal cursor down by sending ANSI control code CUD to the terminal. - * If the cursor is already at the edge of the screen, this has no effect. - * @param integer $rows number of rows the cursor should be moved down - */ - public static function moveCursorDown($rows=1) - { - echo "\033[" . (int) $rows . 'B'; - } - - /** - * Moves the terminal cursor forward by sending ANSI control code CUF to the terminal. - * If the cursor is already at the edge of the screen, this has no effect. - * @param integer $steps number of steps the cursor should be moved forward - */ - public static function moveCursorForward($steps=1) - { - echo "\033[" . (int) $steps . 'C'; - } - - /** - * Moves the terminal cursor backward by sending ANSI control code CUB to the terminal. - * If the cursor is already at the edge of the screen, this has no effect. - * @param integer $steps number of steps the cursor should be moved backward - */ - public static function moveCursorBackward($steps=1) - { - echo "\033[" . (int) $steps . 'D'; - } - - /** - * Moves the terminal cursor to the beginning of the next line by sending ANSI control code CNL to the terminal. - * @param integer $lines number of lines the cursor should be moved down - */ - public static function moveCursorNextLine($lines=1) - { - echo "\033[" . (int) $lines . 'E'; - } - - /** - * Moves the terminal cursor to the beginning of the previous line by sending ANSI control code CPL to the terminal. - * @param integer $lines number of lines the cursor should be moved up - */ - public static function moveCursorPrevLine($lines=1) - { - echo "\033[" . (int) $lines . 'F'; - } - - /** - * Moves the cursor to an absolute position given as column and row by sending ANSI control code CUP or CHA to the terminal. - * @param integer $column 1-based column number, 1 is the left edge of the screen. - * @param integer|null $row 1-based row number, 1 is the top edge of the screen. if not set, will move cursor only in current line. - */ - public static function moveCursorTo($column, $row=null) - { - if ($row === null) { - echo "\033[" . (int) $column . 'G'; - } else { - echo "\033[" . (int) $row . ';' . (int) $column . 'H'; - } - } - - /** - * Scrolls whole page up by sending ANSI control code SU to the terminal. - * New lines are added at the bottom. This is not supported by ANSI.SYS used in windows. - * @param int $lines number of lines to scroll up - */ - public static function scrollUp($lines=1) - { - echo "\033[".(int)$lines."S"; - } - - /** - * Scrolls whole page down by sending ANSI control code SD to the terminal. - * New lines are added at the top. This is not supported by ANSI.SYS used in windows. - * @param int $lines number of lines to scroll down - */ - public static function scrollDown($lines=1) - { - echo "\033[".(int)$lines."T"; - } - - /** - * Saves the current cursor position by sending ANSI control code SCP to the terminal. - * Position can then be restored with {@link restoreCursorPosition}. - */ - public static function saveCursorPosition() - { - echo "\033[s"; - } - - /** - * Restores the cursor position saved with {@link saveCursorPosition} by sending ANSI control code RCP to the terminal. - */ - public static function restoreCursorPosition() - { - echo "\033[u"; - } - - /** - * Hides the cursor by sending ANSI DECTCEM code ?25l to the terminal. - * Use {@link showCursor} to bring it back. - * Do not forget to show cursor when your application exits. Cursor might stay hidden in terminal after exit. - */ - public static function hideCursor() - { - echo "\033[?25l"; - } - - /** - * Will show a cursor again when it has been hidden by {@link hideCursor} by sending ANSI DECTCEM code ?25h to the terminal. - */ - public static function showCursor() - { - echo "\033[?25h"; - } - - /** - * Clears entire screen content by sending ANSI control code ED with argument 2 to the terminal. - * Cursor position will not be changed. - * **Note:** ANSI.SYS implementation used in windows will reset cursor position to upper left corner of the screen. - */ - public static function clearScreen() - { - echo "\033[2J"; - } - - /** - * Clears text from cursor to the beginning of the screen by sending ANSI control code ED with argument 1 to the terminal. - * Cursor position will not be changed. - */ - public static function clearScreenBeforeCursor() - { - echo "\033[1J"; - } - - /** - * Clears text from cursor to the end of the screen by sending ANSI control code ED with argument 0 to the terminal. - * Cursor position will not be changed. - */ - public static function clearScreenAfterCursor() - { - echo "\033[0J"; - } - - /** - * Clears the line, the cursor is currently on by sending ANSI control code EL with argument 2 to the terminal. - * Cursor position will not be changed. - */ - public static function clearLine() - { - echo "\033[2K"; - } - - /** - * Clears text from cursor position to the beginning of the line by sending ANSI control code EL with argument 1 to the terminal. - * Cursor position will not be changed. - */ - public static function clearLineBeforeCursor() - { - echo "\033[1K"; - } - - /** - * Clears text from cursor position to the end of the line by sending ANSI control code EL with argument 0 to the terminal. - * Cursor position will not be changed. - */ - public static function clearLineAfterCursor() - { - echo "\033[0K"; - } - - /** - * Will send ANSI format for following output - * - * You can pass any of the FG_*, BG_* and TEXT_* constants and also xterm256ColorBg - * TODO: documentation - */ - public static function ansiStyle() - { - echo "\033[" . implode(';', func_get_args()) . 'm'; - } - - /** - * Will return a string formatted with the given ANSI style - * - * See {@link ansiStyle} for possible arguments. - * @param string $string the string to be formatted - * @return string - */ - public static function ansiStyleString($string) - { - $args = func_get_args(); - array_shift($args); - $code = implode(';', $args); - return "\033[0m" . ($code !== '' ? "\033[" . $code . "m" : '') . $string."\033[0m"; - } - - //const COLOR_XTERM256 = 38;// http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors - public static function xterm256ColorFg($i) // TODO naming! - { - return '38;5;'.$i; - } - - public static function xterm256ColorBg($i) // TODO naming! - { - return '48;5;'.$i; - } - - /** - * Usage: list($w, $h) = ConsoleHelper::getScreenSize(); - * - * @return array - */ - public static function getScreenSize() - { - // TODO implement - return array(150,50); - } - - /** - * resets any ansi style set by previous method {@link ansiStyle} - * Any output after this is will have default text style. - */ - public static function reset() - { - echo "\033[0m"; - } - - /** - * Strips ANSI control codes from a string - * - * @param string $string String to strip - * @return string - */ - public static function strip($string) - { - return preg_replace('/\033\[[\d;]+m/', '', $string); // TODO currently only strips color - } - - // TODO refactor and review - public static function ansiToHtml($string) - { - $tags = 0; - return preg_replace_callback('/\033\[[\d;]+m/', function($ansi) use (&$tags) { - $styleA = array(); - foreach(explode(';', $ansi) as $controlCode) - { - switch($controlCode) - { - case static::FG_BLACK: $style = array('color' => '#000000'); break; - case static::FG_BLUE: $style = array('color' => '#000078'); break; - case static::FG_CYAN: $style = array('color' => '#007878'); break; - case static::FG_GREEN: $style = array('color' => '#007800'); break; - case static::FG_GREY: $style = array('color' => '#787878'); break; - case static::FG_PURPLE: $style = array('color' => '#780078'); break; - case static::FG_RED: $style = array('color' => '#780000'); break; - case static::FG_YELLOW: $style = array('color' => '#787800'); break; - case static::BG_BLACK: $style = array('background-color' => '#000000'); break; - case static::BG_BLUE: $style = array('background-color' => '#000078'); break; - case static::BG_CYAN: $style = array('background-color' => '#007878'); break; - case static::BG_GREEN: $style = array('background-color' => '#007800'); break; - case static::BG_GREY: $style = array('background-color' => '#787878'); break; - case static::BG_PURPLE: $style = array('background-color' => '#780078'); break; - case static::BG_RED: $style = array('background-color' => '#780000'); break; - case static::BG_YELLOW: $style = array('background-color' => '#787800'); break; - case static::BOLD: $style = array('font-weight' => 'bold'); break; - case static::ITALIC: $style = array('font-style' => 'italic'); break; - case static::UNDERLINE: $style = array('text-decoration' => array('underline')); break; - case static::OVERLINED: $style = array('text-decoration' => array('overline')); break; - case static::CROSSED_OUT:$style = array('text-decoration' => array('line-through')); break; - case static::BLINK: $style = array('text-decoration' => array('blink')); break; - case static::NEGATIVE: // ??? - case static::CONCEALED: - case static::ENCIRCLED: - case static::FRAMED: - // TODO allow resetting codes - break; - case 0: // ansi reset - $return = ''; - for($n=$tags; $tags>0; $tags--) { - $return .= ''; - } - return $return; - } - - $styleA = ArrayHelper::merge($styleA, $style); - } - $styleString[] = array(); - foreach($styleA as $name => $content) { - if ($name = 'text-decoration') { - $content = implode(' ', $content); - } - $styleString[] = $name.':'.$content; - } - $tags++; - return '