Zhu Jinhui 7 жил өмнө
parent
commit
6f06adfdd4

+ 2 - 2
Qii/Base/Controller.php

@@ -186,7 +186,7 @@ abstract class Controller
      */
     public function setResponse(\Qii\Base\Response $response)
     {
-        $this->response = $response;
+        return $this->response = $response;
     }
     /**
      * 设置request
@@ -194,7 +194,7 @@ abstract class Controller
      */
     public function setRequest(\Qii\Base\Request $request)
     {
-        $this->request = $request;
+        return $this->request = $request;
     }
 
 

+ 3 - 2
Qii/Base/Response.php

@@ -34,6 +34,7 @@ class Response
     protected $_sendHeader = false;
 	public function __construct($data = array())
 	{
+        $this->format = isset($data['format']) ? isset($data['format']) : FORMAT_HTML;
 		$this->data = $data;
 	}
 
@@ -145,7 +146,7 @@ class Response
                     echo json_encode($this->data['body'], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
                 break;
                 default:
-                    echo $this->body;
+                    echo (IS_CLI ? (new \Qii\Response\Cli())->stdout($this->data['body']) : $this->data['body']);
                 break;
             }
             return;
@@ -154,7 +155,7 @@ class Response
             $this->sendHeaders();
         }
         foreach ($this->body as $key => $body) {
-            echo $body;
+            echo IS_CLI ? new \Qii\Response\Cli($body) : $body;
         }
     }
 

+ 41 - 10
Qii/Exceptions/Errors.php

@@ -47,14 +47,15 @@ class Errors extends \Exception
 			echo json_encode(array('code' => $e->getCode(), 'msg' => strip_tags($e->getMessage())), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
 			return;
 		}
-		$message[] = \Qii::i('Error file', self::getRelatePath($_SERVER['SCRIPT_FILENAME'], $e->getFile()));
-		$message[] = \Qii::i('Error code', $e->getCode());
-		$message[] = \Qii::i('Error description', $e->getMessage());
-		$message[] = \Qii::i('Error line', $e->getLine() . ' on ' . self::getLineMessage($e->getFile(), $e->getLine()));
-		$traceString = \Qii::i('Trace as below') . '<br />';
+		$message[] = (IS_CLI ? QII_EOL : '') . \Qii::i('Error file', self::getRelatePath($_SERVER['SCRIPT_FILENAME'], $e->getFile())) . (IS_CLI ? QII_EOL : '');
+		$message[] = \Qii::i('Error code', $e->getCode()) . (IS_CLI ? QII_EOL : '');
+		$message[] = \Qii::i('Error description', $e->getMessage()) . (IS_CLI ? QII_EOL : '');
+		$message[] = \Qii::i('Error line', $e->getLine() . ' on ' . self::getLineMessage($e->getFile(), $e->getLine())) . (IS_CLI ? QII_EOL : '');
+		$traceString = \Qii::i('Trace as below') . QII_EOL;
 		$traces = explode("\n", $e->getTraceAsString());
-		foreach ($traces AS $trance) {
-			$traceString .= "&nbsp;&nbsp;&nbsp;&nbsp;" . $trance . '<br />';
+		foreach ($traces AS $trance) 
+		{
+			$traceString .= str_repeat(QII_SPACE, 4) . $trance . QII_EOL;
 		}
 		$message[] = $traceString;
 		if (\Qii::getInstance()->logerWriter != null) {
@@ -83,7 +84,22 @@ class Errors extends \Exception
 				die();
 			}
 		}
+		ob_start();
 		include(join(DS, array(Qii_DIR, 'Exceptions', 'View', 'error.php')));
+		$html = ob_get_contents();
+		ob_clean();
+		
+		if(!IS_CLI)
+		{
+			echo $html;
+			return;
+		}
+		return (new \Qii\Response\Cli())->stdout(
+			str_replace("&nbsp;"
+						, " "
+						, strip_tags(join(PHP_EOL, preg_replace("/[\n|\r\n]/", PHP_EOL, $message)))
+			)
+		);
 	}
 
 	/**
@@ -110,14 +126,29 @@ class Errors extends \Exception
 				$currentLine = $i + ($min < 0 ? abs($min) : 0) + 1;
 				$color = $currentLine == $line ? ' color="red"' : '';
 				if ($spl->eof()) break;
-				$code[] = '<font ' . $color . '>' . $currentLine . ':</font>' . "\t" . '<font ' . $color . '>' . htmlspecialchars(rtrim($spl->current())) . '</font>';
+				if(IS_CLI)
+				{
+					$code[] = $currentLine . ($color != '' ? ' 行发生错误' : '') . rtrim($spl->current());
+				}
+				else
+				{
+					$code[] = '<font ' . $color . '>' . $currentLine . ':</font>' . "\t" . '<font ' . $color . '>' . htmlspecialchars(rtrim($spl->current())) . '</font>';
+				}
 				$spl->next();
 			}
 		} else {
 			$spl->seek($seekline);
-			$code[] = htmlspecialchars(rtrim($spl->current()));
+			if(IS_CLI)
+			{
+				$code[] = rtrim($spl->current());
+			}
+			else
+			{
+				$code[] = htmlspecialchars(rtrim($spl->current()));
+			}
+			
 		}
-		return '<pre style="font-weight:bold;">' . join("<br />", $code) . '</pre>';
+		return IS_CLI ? PHP_EOL . join(PHP_EOL, $code) : '<pre style="font-weight:bold;">' . join("<br />", $code) . '</pre>';
 	}
 
 	/**

+ 5 - 0
Qii/Qii.php

@@ -17,6 +17,11 @@ define('PS', PATH_SEPARATOR);
 define('OS', strtoupper(substr(PHP_OS, 0, 3)));
 
 define('IS_CLI', php_sapi_name() == 'cli' ? true : false);
+/**
+ * EOL 和 SPACE
+ */
+define('QII_EOL', IS_CLI ? PHP_EOL : '<br />');
+define('QII_SPACE', IS_CLI ? ' ' : '&nbsp;');
 
 require Qii_DIR . DS . 'Autoloader' . DS . 'Import.php';
 \Qii\Autoloader\Import::setFileLoaded(Qii_DIR . DS . 'Autoloader' . DS . 'Import.php');

+ 6 - 2
Qii/Response/Cli.php

@@ -3,6 +3,10 @@ namespace Qii\Response;
 
 class Cli extends \Qii\Base\Response
 {
+    public function __construct($body = null)
+    {
+        $this->body = $body;
+    }
     /**
      * Magic __toString functionality
      *
@@ -10,7 +14,7 @@ class Cli extends \Qii\Base\Response
      */
     public function __toString()
     {
-        $this->stdout($this->_body);
+        return $this->body;
     }
     /**
      * 在windows cmd 情况下的中文输出乱码问题
@@ -20,6 +24,6 @@ class Cli extends \Qii\Base\Response
     public function stdout($string)
     {
         $string = iconv('utf-8', 'gbk', $string);
-        return fwrite(\STDOUT, $string);
+        fwrite(\STDOUT, $string);
     }
 }

+ 277 - 0
_cli.php

@@ -0,0 +1,277 @@
+<?php
+/**
+ * @author Jinhui Zhu  <jinhui.zhu@live.cn>
+ * 通过命令行直接生成项目目录
+ */
+ini_set("display_errors", "On");
+/**
+ * 错误模式
+ */
+error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
+
+/**
+ * 自动生成目标目录
+ *
+ * php -q _cli.php create=yes workspace=../project cache=tmp useDB=1
+ * create: 是否自动创建
+ * workspace: 程序存放的目录
+ * cache: 缓存目录
+ * useDB: 是否使用数据库,值 0/1
+ * 目前已经将配置文件写在db.ini中,配置内容将不在创建项目的时候提供,可以自行在目录中修改
+ */
+class cmd
+{
+    const VERSION = '1.2';
+    public $dir = array('Configure', 'Controller', 'Model', 'View', 'Plugins', 'tmp');
+
+    public function __construct($args)
+    {
+        $param = $this->parseArgvs($args);
+        if (sizeof($param) < 1) {
+            $this->stdout("命令行使用如下:\n
+>php -q _cli.php create=yes workspace=../project cache=tmp useDB=1\n
+ * create: 是否自动创建:yes; \n
+ * workspace: 工作目录\n
+ * cache : 缓存目录\n
+ * useDB : 是否使用数据库 : 使用:1 不使用: 0\n
+ ");
+            $this->stdout("创建 yes/no:");
+            $param['create'] = trim(fgets(\STDIN));
+            $this->stdout("工作目录:");
+            $param['workspace'] = trim(fgets(\STDIN));
+            $this->stdout("缓存目录:");
+            $param['cache'] = trim(fgets(\STDIN));
+            $this->stdout("是否使用数据库 使用:1 不使用 0:");
+            $param['useDB'] = trim(fgets(\STDIN));
+
+            $this->stdout('将要在'. $param['workspace'] .'创建项目,确认请输入yes,取消请输入no:');
+
+            $param['create'] = trim(fgets(\STDIN));
+        }
+        if ($param['create'] == 'yes') {
+            if ($this->workspace($param['workspace'])) {
+                $cache = $param['cache'];
+                if (empty($param['cache'])) $cache = 'tmp';
+                $this->dir[5] = $cache;
+                //创建目录工作区目录
+                foreach ($this->dir AS $d) {
+                    $path = $param['workspace'] . '/' . $d;
+                    if (!is_dir($path)) {
+                        $date = date('Y-m-d H:i:s');
+                        echo "create path {$path} success.\n";
+                        mkdir($path, 0777, true);
+                        //写入.htaccess文件到包含的目录,不允许通过Apache浏览
+                        $htaccess = array();
+                        $htaccess[] = "##";
+                        $htaccess[] = "#";
+                        $htaccess[] = "#	\$Id: .htaccess 268 {$date}Z Jinhui.Zhu $";
+                        $htaccess[] = "#";
+                        $htaccess[] = "#	Copyright (C) 2010-2012 All Rights Reserved.";
+                        $htaccess[] = "#";
+                        $htaccess[] = "##";
+                        $htaccess[] = "";
+                        $htaccess[] = "Options Includes";
+                        file_put_contents($path . '/.htaccess', join("\n", $htaccess));
+                    } else {
+                        $this->stdout("{$path} 已经存在.". PHP_EOL);
+                    }
+                }
+                //拷贝网站配置文件site.xml到项目目录
+                if($cache != 'tmp'){
+                    $appIni = file_get_contents('_cli/app.ini');
+                    $appIni = str_replace('tmp/compile', $cache . '/compile', $appIni);
+                    $appIni = str_replace('tmp/cache', $cache . '/cache', $appIni);
+                    file_put_contents($param['workspace'] . '/Configure/app.ini', $appIni);
+                }else if (!copy("_cli/app.ini", $param['workspace'] . '/Configure/app.ini')) {
+                     $this->stdout('拷贝 app.ini 到 ' . $param['workspace'] . '/Configure/app.ini失败, 拒绝访问.');
+                    
+                }
+                if (!copy("_cli/router.config.php", $param['workspace'] . '/Configure/router.config.php')) {
+                    $this->stdout('拷贝 router.config.php 到' . $param['workspace'] . '/Configure/router.config.php 失败, 拒绝访问.');
+                }
+                if ($param['useDB'] != 'no') {
+                    if (!copy("_cli/db.ini", $param['workspace'] . '/Configure/db.ini')) {
+                        $this->stdout('拷贝 db.ini 到 ' . $param['workspace'] . '/Configure/db.ini false, 拒绝访问.');
+                    }
+                }
+
+                //生成数据库文件
+                //--生成首页文件
+                //--获取文件的相对路径
+                $realPath = $this->getRealPath($param['workspace']);
+                $this->stdout("真实路径 " . $realPath . "\n");
+                $QiiPath = $this->getRelatePath($realPath . "/index.php", dirname(__FILE__) . "/Qii/Qii.php");
+                $this->stdout("Qii 路径 " . $QiiPath . "\n");
+                $date = date("Y/m/d H:i:s");
+                $indexPage = array();
+                $indexPage[] = "<?php";
+                $indexPage[] = "/**";
+                $indexPage[] = " * This is index page auto create by Qii, don't delete";
+                $indexPage[] = " * ";
+                $indexPage[] = " * @author Jinhui.zhu	<jinhui.zhu@live.cn>";
+                $indexPage[] = " * @version  \$Id: index.php,v 1.1 {$date} Jinhui.Zhu Exp $";
+                $indexPage[] = " */";
+                $indexPage[] = 'require("'.$QiiPath.'");';
+                $indexPage[] = '$app = \\Qii::getInstance();';
+                $indexPage[] = '//如需更改网站源代码存储路径,请修改此路径';
+                $indexPage[] = '$app->setWorkspace(\''.$param['workspace'].'\');';
+                $indexPage[] = '$app->setCachePath(\''.$cache.'\');';
+                $indexPage[] = '$app->setAppConfigure(\'Configure/app.ini\');';
+                $indexPage[] = '$env = getenv(\'WEB_ENVIRONMENT\') ? getenv(\'WEB_ENVIRONMENT\') : \'product\';';
+                $indexPage[] = '$app->setEnv($env);';
+                if ($param['useDB']) $indexPage[] = '$app->setDB(\'Configure/db.ini\');';
+                $indexPage[] = '$app->setRouter(\'Configure/router.config.php\')';
+                $indexPage[] = '->run();';
+                if (!file_exists($realPath . "/index.php")) {
+                    //如果文件不存在就写入
+                    file_put_contents($realPath . "/index.php", join("\n", $indexPage));
+                }
+                //写入首页controller
+                if (!file_exists($realPath . "/Controller/index.php")) {
+                    $indexContents = array();
+                    $indexContents[] = "<?php";
+                    $indexContents[] = 'namespace Controller;' . PHP_EOL;
+                    $indexContents[] = 'use \Qii\Base\Controller;' . PHP_EOL;
+                    $indexContents[] = "class index extends Controller";
+                    $indexContents[] = "{";
+                    $indexContents[] = "\tpublic \$enableView = true;";
+                    $indexContents[] = "\tpublic function __construct()\n\t{";
+                    $indexContents[] = "\t\tparent::__construct();";
+                    $indexContents[] = "\t}";
+                    $indexContents[] = "\tpublic function indexAction()\n\t{";
+                    $indexContents[] = "\t\t return new \Qii\Base\Response(array('format' => 'html', 'body' => '请重写 '. __FILE__ . ' 中的 indexAction 方法, 第 ' . __LINE__ . ' 行'));";
+                    $indexContents[] = "\t}";
+                    $indexContents[] = "}";
+                    $indexContents[] = "?>";
+                    file_put_contents($realPath . "/Controller/index.php", join("\n", $indexContents));
+                }
+                //apache rewrite file
+                $htaccessFile = $param['workspace'] . "/.htaccess";
+                if(!file_exists($htaccessFile)){
+                    if(!copy('_cli/.htaccess', $htaccessFile)){
+                        $this->stdout($this->stdout("拷贝 .htaccess 到 ". $htaccessFile . ' 失败, 拒绝访问') . PHP_EOL);
+                    }
+                }
+            }
+        } else if($param['create'] == 'no'){
+            $this->stdout('您已经取消');
+        }
+    }
+
+    /**
+     * 获取文件相对路径
+     *
+     * @param String $cur 路径1
+     * @param String $absp 路径2
+     * @return String 路径2相对于路径1的路径
+     */
+    public function getRelatePath($cur, $absp)
+    {
+        $cur = str_replace('\\', '/', $cur);
+        $absp = str_replace('\\', '/', $absp);
+        $sabsp = explode('/', $absp);
+        $scur = explode('/', $cur);
+        $la = count($sabsp) - 1;
+        $lb = count($scur) - 1;
+        $l = max($la, $lb);
+
+        for ($i = 0; $i <= $l; $i++) {
+            if ($sabsp[$i] != $scur[$i])
+                break;
+        }
+        $k = $i - 1;
+        $path = "";
+        for ($i = 1; $i <= ($lb - $k - 1); $i++)
+            $path .= "../";
+        for ($i = $k + 1; $i <= ($la - 1); $i++)
+            $path .= $sabsp[$i] . "/";
+        $path .= $sabsp[$la];
+        return $path;
+    }
+
+    /**
+     * 获取相对目录
+     *
+     * @param String $workspace 目标路径
+     * @return String 目标路径相对于当期路径的相对路径
+     */
+    public function getRealPath($workspace)
+    {
+        $currentDir = str_replace("\\", "/", dirname(__FILE__));
+        $workspace = str_replace("\\", "/", $workspace);
+
+        if ($workspace[0] == '/') {
+            return $workspace;
+        } else {
+            $workspaceArray = explode("/", $workspace);
+            $currentDirArray = explode("/", $currentDir);
+
+            $work = array();
+            foreach ($workspaceArray AS $k) {
+                if ($k == '..') {
+                    array_pop($currentDirArray);
+                } elseif ($k == '.') {
+
+                } else {
+                    $work[] = $k;
+                }
+            }
+            if (!empty($currentDirArray)) {
+                return join("/", $currentDirArray) . "/" . join("/", $work);
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * 创建工作区目录
+     *
+     * @param String $dir
+     * @return Bool
+     */
+    public function workspace($dir)
+    {
+        return true;
+        if (!empty($dir)) {
+            if (!is_dir($dir)) {
+                return mkdir($dir, 0777, true);
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 匹配命令行参数
+     *
+     * @param String $argvs
+     * @return Array 返回参数对应的值
+     */
+    public function parseArgvs($argvs)
+    {
+        $keyValue = array();
+        foreach ($argvs AS $value) {
+            $valueArray = explode("=", $value);
+            $k = $valueArray[0];
+            $v = stripslashes($valueArray[1]);
+            $keyValue[$k] = $v;
+        }
+        return $keyValue;
+    }
+    /**
+     * 在windows cmd 情况下的中文输出乱码问题
+     * @param string $string
+     * @return bool|int
+     */
+    public function stdout($string)
+    {
+        $string = iconv('utf-8', 'gbk', $string);
+        fwrite(\STDOUT, $string);
+    }
+}
+
+array_shift($argv);
+new cmd($argv);
+?>

+ 13 - 0
_cli/.htaccess

@@ -0,0 +1,13 @@
+##
+#
+#	$Id: .htaccess 268 2009-12-16 06:18:19Z Jinhui.Zhu $
+#
+#	Copyright (C) 2008-2009 www.qiiframework.com. All Rights Reserved.
+#  
+##
+RewriteEngine On
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteCond %{REQUEST_FILENAME} !-f
+
+RewriteCond $1 !^(index.php|images|robots.txt)
+RewriteRule (.*)$ index.php/$1 [L,QSA,PT]

+ 112 - 0
_cli/app.ini

@@ -0,0 +1,112 @@
+;通用配置,如果没有指定环境将使用通用配置,指定了环境,指定环境的配置将覆盖默认配置中的配置信息
+[author]
+name = 朱金辉
+email = jinhui.zhu@live.cn
+qq = 119328118
+
+[common]
+;程序是否使用命名空间
+namespace['use'] = true
+namespace[list.Controller] = true
+namespace[list.Model] = true
+namespace[list.Library] = true
+namespace[list.Action] = true
+;rewrite 方法, 此定义不能省略
+rewriteMethod = Short
+;rewrite匹配规则,可选
+rewriteRules = Normal
+;hosts中的属性将会覆盖掉默认的属性,当在不同域名上使用不同配置上很有用处
+;hosts[0.domain] = test.com
+;hosts[0.path] = test
+;hosts[0.password] = test
+
+;hosts[1.domain] = admin.test.com
+;hosts[1.path] = admin
+;hosts[1.password] = admin
+
+;用于检查系统环境的时候用到的密码,如果不填写就可以直接通过url进入
+admin[user] = admin
+admin[password] = 119328118
+;是否开启调试模式,调试模式下,所有的错误都将抛出来,并终止运行
+debug = 1
+;错误页面
+errorPage = Error:Index
+;时间区域
+timezone = Asia/Shanghai
+;文档类型
+contentType = text/html
+;文档编码
+charset = UTF-8
+;模板引擎
+view[engine] = smarty
+view[path] = view
+;smarty 引擎的相关配置
+view[smarty.view] = view
+view[smarty.path] = view
+view[smarty.ldelimiter] = {#
+view[smarty.rdelimiter] = #}
+view[smarty.compile] = tmp/compile
+view[smarty.cache] = tmp/cache
+view[smarty.lifetime] = 300
+;缓存类型
+cache = memcache
+
+;是否开启安全验证,enable:是否开启安全验证;key:POST数据的时候安全字符串加密用到的key
+security[enable] = true
+security[name] = security_sid
+security[expired] = 3600
+security[key] = 4cd780a986d5c30e03bdcb67d16c8320
+
+;memcache配置,多个服务器IP和端口以;隔开
+memcache[servers] = 127.0.0.1
+memcache[ports] = 11211
+
+
+;搜索文件路径
+xpath[] = controller
+xpath[] = model
+xpath[] = class
+xpath[] = plugin
+
+;map:为参数的顺序,当启用短URI标签的情况下会按照这个顺序去遍历参数;
+query[] = controller
+query[] = action
+query[] = param
+
+;controller、action配置  name:参数名 ext:后缀;default:默认方法 
+controller[name] = controller
+controller[prefix] = Controller
+controller[default] = index
+
+action[name] = action
+action[suffix] = Action
+action[default] = index
+
+;url相关配置,用于生成链接用
+[uri]
+
+;url模式,短链接模式
+mode = short
+controllerName = controller
+actionName = action
+
+normal[mode] = normal
+normal[trim] = 0
+normal[symbol] = "&"
+normal[extenstion] = .html
+
+middle[mode] = middle
+middle[trim] = 1
+middle[symbol] = "/"
+middle[extenstion] = .html
+
+short[mode] = short
+short[trim] = 1
+short[symbol] = "/"
+short[extenstion] = .html
+;以下这种写法将会继承:后边的section,如果是"."开头的话就放在当前key下边
+[dev:common:.uri]
+password = 12345
+[product:common:.uri]
+password = 119328118
+

+ 24 - 0
_cli/db.ini

@@ -0,0 +1,24 @@
+;数据库配置
+[common]
+;是否读写分离
+readOrWriteSeparation = 0
+driver = pdo
+;使用的数据库类型
+use_db_driver = mysql
+master[db] = test
+master[host] = 127.0.0.1
+master[user] = root
+master[password] = 
+
+slave[0.db] = test
+slave[0.host] = 127.0.0.1
+slave[0.user] = root
+slave[0.password] = 
+
+
+slave[1.db] = test
+slave[1.host] = 127.0.0.1
+slave[1.user] = root
+slave[1.password] = 
+
+[product:common]

+ 5 - 0
_cli/router.config.php

@@ -0,0 +1,5 @@
+<?php
+return [
+    //'home:index' => 'index:index',
+    //'manage:*' => 'manage\{1}:*'
+];

+ 2 - 0
private/Controller/index.php

@@ -7,6 +7,8 @@ class index extends \Qii\Base\Controller
     public $enableView = true;
     public function indexAction()
     {
+        return $this->setResponse(new \Qii\Base\Response(array('format' => 'html', 'body' => 'This is html')));
+        return;
         $data = array();
         $data['lists'][] = $this->db->getRow('SELECT * FROM ipAddress ORDER BY id DESC LIMIT 1');
         $data['lists'][] = $this->db->getRow('SELECT * FROM ipAddress ORDER BY id ASC LIMIT 1');

+ 3 - 3
private/configure/db.ini

@@ -9,17 +9,17 @@ use_db_driver = mysql
 master[db] = wecv
 master[host] = 127.0.0.1
 master[user] = root
-master[password] = 119328118
+master[password] = A119328118a
 
 slave[0.db] = istudy
 slave[0.host] = 127.0.0.1
 slave[0.user] = wecv
-slave[0.password] = 119328118
+slave[0.password] = A119328118a
 
 
 slave[1.db] = istudy
 slave[1.host] = 127.0.0.1
 slave[1.user] = wecv
-slave[1.password] = 119328118
+slave[1.password] = A119328118a
 
 [product:common]