Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

No commit message

  • Loading branch information...
commit 662798d8a5a4d6e73dfb5c491a9279f10a951eb3 1 parent f94b8d2
qiang.xue authored
Showing with 43,434 additions and 0 deletions.
  1. +3 −0  CHANGELOG
  2. +31 −0 COPYRIGHT
  3. +31 −0 LICENSE
  4. +61 −0 README
  5. +14 −0 UPGRADE
  6. +21 −0 build/build
  7. +23 −0 build/build.bat
  8. +157 −0 build/build.xml
  9. +290 −0 build/commands/ApiCommand.php
  10. +79 −0 build/commands/AutoloadCommand.php
  11. +325 −0 build/commands/CldrCommand.php
  12. +221 −0 build/commands/LiteCommand.php
  13. +643 −0 build/commands/api/ApiModel.php
  14. +80 −0 build/commands/api/assets/css/api.css
  15. +32 −0 build/commands/api/assets/css/style.css
  16. +3,549 −0 build/commands/api/assets/js/jquery.js
  17. +44 −0 build/commands/api/layouts/main.php
  18. +35 −0 build/commands/api/views/chmContents.php
  19. +42 −0 build/commands/api/views/chmIndex.php
  20. +22 −0 build/commands/api/views/chmProject.php
  21. +29 −0 build/commands/api/views/class.php
  22. +38 −0 build/commands/api/views/classSummary.php
  23. +26 −0 build/commands/api/views/eventDetails.php
  24. +20 −0 build/commands/api/views/eventSummary.php
  25. +18 −0 build/commands/api/views/index.php
  26. +47 −0 build/commands/api/views/methodDetails.php
  27. +22 −0 build/commands/api/views/methodSummary.php
  28. +27 −0 build/commands/api/views/propertyDetails.php
  29. +23 −0 build/commands/api/views/propertySummary.php
  30. +9 −0 build/commands/api/views/seeAlso.php
  31. +107 −0 build/commands/lite/css/form.css
  32. +112 −0 build/commands/lite/css/main.css
  33. +4 −0 build/commands/lite/index.php
  34. +1 −0  build/commands/lite/protected/.htaccess
  35. +25 −0 build/commands/lite/protected/components/WebUser.php
  36. +26 −0 build/commands/lite/protected/config/main.php
  37. +15 −0 build/commands/lite/protected/controllers/HomeController.php
  38. +168 −0 build/commands/lite/protected/controllers/PostController.php
  39. +71 −0 build/commands/lite/protected/controllers/UserController.php
  40. BIN  build/commands/lite/protected/data/source.db
  41. +60 −0 build/commands/lite/protected/models/Post.php
  42. +44 −0 build/commands/lite/protected/views/home/index.php
  43. +39 −0 build/commands/lite/protected/views/layouts/main.php
  44. +34 −0 build/commands/lite/protected/views/post/create.php
  45. +29 −0 build/commands/lite/protected/views/post/list.php
  46. +40 −0 build/commands/lite/protected/views/post/show.php
  47. +35 −0 build/commands/lite/protected/views/post/update.php
  48. +27 −0 build/commands/lite/protected/views/user/login.php
  49. +76 −0 build/tasks/YiiInitTask.php
  50. +1 −0  framework/.htaccess
  51. +532 −0 framework/YiiBase.php
  52. +100 −0 framework/caching/CApcCache.php
  53. +259 −0 framework/caching/CCache.php
  54. +227 −0 framework/caching/CDbCache.php
  55. +252 −0 framework/caching/CMemCache.php
  56. +62 −0 framework/caching/dependencies/CCacheDependency.php
  57. +68 −0 framework/caching/dependencies/CChainedCacheDependency.php
  58. +86 −0 framework/caching/dependencies/CDbCacheDependency.php
  59. +134 −0 framework/caching/dependencies/CDirectoryCacheDependency.php
  60. +53 −0 framework/caching/dependencies/CFileCacheDependency.php
  61. +54 −0 framework/caching/dependencies/CGlobalStateCacheDependency.php
  62. +193 −0 framework/cli/commands/MessageCommand.php
  63. +112 −0 framework/cli/commands/ShellCommand.php
  64. +73 −0 framework/cli/commands/WebAppCommand.php
  65. +111 −0 framework/cli/commands/shell/ControllerCommand.php
  66. +139 −0 framework/cli/commands/shell/CrudCommand.php
  67. +64 −0 framework/cli/commands/shell/HelpCommand.php
  68. +126 −0 framework/cli/commands/shell/ModelCommand.php
  69. 0  framework/cli/runtime/.yii
  70. +43 −0 framework/cli/views/shell/controller/controller.php
  71. +2 −0  framework/cli/views/shell/controller/view.php
  72. +168 −0 framework/cli/views/shell/crud/controller.php
  73. +24 −0 framework/cli/views/shell/crud/create.php
  74. +29 −0 framework/cli/views/shell/crud/list.php
  75. +18 −0 framework/cli/views/shell/crud/show.php
  76. +25 −0 framework/cli/views/shell/crud/update.php
  77. +57 −0 framework/cli/views/shell/model/model.php
  78. 0  framework/cli/views/webapp/assets/.yii
  79. +107 −0 framework/cli/views/webapp/css/form.css
  80. +112 −0 framework/cli/views/webapp/css/main.css
  81. 0  framework/cli/views/webapp/images/.yii
  82. +11 −0 framework/cli/views/webapp/index.php
  83. +1 −0  framework/cli/views/webapp/protected/.htaccess
  84. 0  framework/cli/views/webapp/protected/commands/.yii
  85. +25 −0 framework/cli/views/webapp/protected/components/WebUser.php
  86. +7 −0 framework/cli/views/webapp/protected/config/console.php
  87. +19 −0 framework/cli/views/webapp/protected/config/main.php
  88. +15 −0 framework/cli/views/webapp/protected/controllers/HomeController.php
  89. +71 −0 framework/cli/views/webapp/protected/controllers/UserController.php
  90. 0  framework/cli/views/webapp/protected/extensions/.yii
  91. 0  framework/cli/views/webapp/protected/messages/.yii
  92. 0  framework/cli/views/webapp/protected/models/.yii
  93. 0  framework/cli/views/webapp/protected/runtime/.yii
  94. +44 −0 framework/cli/views/webapp/protected/views/home/index.php
  95. +39 −0 framework/cli/views/webapp/protected/views/layouts/main.php
  96. 0  framework/cli/views/webapp/protected/views/system/.yii
  97. +27 −0 framework/cli/views/webapp/protected/views/user/login.php
  98. +16 −0 framework/cli/views/webapp/protected/yiic
  99. +16 −0 framework/cli/views/webapp/protected/yiic.bat
  100. 0  framework/cli/views/webapp/themes/.yii
  101. +159 −0 framework/collections/CAttributeCollection.php
  102. +149 −0 framework/collections/CConfiguration.php
  103. +426 −0 framework/collections/CList.php
  104. +403 −0 framework/collections/CMap.php
  105. +253 −0 framework/collections/CQueue.php
  106. +254 −0 framework/collections/CStack.php
  107. +52 −0 framework/collections/CTypedList.php
  108. +156 −0 framework/console/CConsoleApplication.php
  109. +224 −0 framework/console/CConsoleCommand.php
  110. +141 −0 framework/console/CConsoleCommandRunner.php
  111. +70 −0 framework/console/CHelpCommand.php
  112. +946 −0 framework/core/CApplication.php
  113. +47 −0 framework/core/CApplicationComponent.php
  114. +542 −0 framework/core/CComponent.php
  115. +302 −0 framework/core/CErrorHandler.php
  116. +22 −0 framework/core/CException.php
  117. +40 −0 framework/core/CHttpException.php
  118. +210 −0 framework/core/CModel.php
  119. +245 −0 framework/core/CSecurityManager.php
  120. +105 −0 framework/core/CStatePersister.php
  121. +52 −0 framework/core/functions.php
  122. +207 −0 framework/core/interfaces.php
  123. +171 −0 framework/core/log/CDbLogRoute.php
  124. +122 −0 framework/core/log/CEmailLogRoute.php
  125. +162 −0 framework/core/log/CFileLogRoute.php
  126. +88 −0 framework/core/log/CLogRoute.php
  127. +109 −0 framework/core/log/CLogRouter.php
  128. +167 −0 framework/core/log/CLogger.php
  129. +183 −0 framework/core/log/CProfileLogRoute.php
  130. +57 −0 framework/core/log/CWebLogRoute.php
  131. +288 −0 framework/db/CDbCommand.php
  132. +551 −0 framework/db/CDbConnection.php
  133. +221 −0 framework/db/CDbDataReader.php
  134. +21 −0 framework/db/CDbException.php
  135. +106 −0 framework/db/CDbTransaction.php
  136. +800 −0 framework/db/ar/CActiveFinder.php
  137. +1,586 −0 framework/db/ar/CActiveRecord.php
  138. +143 −0 framework/db/schema/CDbColumnSchema.php
  139. +527 −0 framework/db/schema/CDbCommandBuilder.php
  140. +69 −0 framework/db/schema/CDbCriteria.php
  141. +126 −0 framework/db/schema/CDbSchema.php
  142. +76 −0 framework/db/schema/CDbTableSchema.php
  143. +44 −0 framework/db/schema/mysql/CMysqlColumnSchema.php
  144. +210 −0 framework/db/schema/mysql/CMysqlSchema.php
  145. +26 −0 framework/db/schema/mysql/CMysqlTableSchema.php
  146. +56 −0 framework/db/schema/pgsql/CPgsqlColumnSchema.php
  147. +255 −0 framework/db/schema/pgsql/CPgsqlSchema.php
  148. +25 −0 framework/db/schema/pgsql/CPgsqlTableSchema.php
  149. +40 −0 framework/db/schema/sqlite/CSqliteCommandBuilder.php
  150. +117 −0 framework/db/schema/sqlite/CSqliteSchema.php
  151. +502 −0 framework/i18n/CDateFormatter.php
  152. +114 −0 framework/i18n/CDbMessageSource.php
  153. +243 −0 framework/i18n/CLocale.php
  154. +88 −0 framework/i18n/CMessageSource.php
  155. +254 −0 framework/i18n/CNumberFormatter.php
  156. +96 −0 framework/i18n/CPhpMessageSource.php
  157. +667 −0 framework/i18n/CTimestamp.php
  158. +10 −0 framework/i18n/data/README.txt
  159. +159 −0 framework/i18n/data/aa.php
  160. +150 −0 framework/i18n/data/aa_dj.php
  161. +159 −0 framework/i18n/data/aa_er.php
  162. +159 −0 framework/i18n/data/aa_er_saaho.php
  163. +159 −0 framework/i18n/data/aa_et.php
  164. +157 −0 framework/i18n/data/af.php
  165. +157 −0 framework/i18n/data/af_na.php
  166. +157 −0 framework/i18n/data/af_za.php
  167. +157 −0 framework/i18n/data/ak.php
  168. +157 −0 framework/i18n/data/ak_gh.php
  169. +158 −0 framework/i18n/data/am.php
  170. +158 −0 framework/i18n/data/am_et.php
  171. +180 −0 framework/i18n/data/ar.php
  172. +180 −0 framework/i18n/data/ar_ae.php
  173. +180 −0 framework/i18n/data/ar_bh.php
  174. +180 −0 framework/i18n/data/ar_dz.php
  175. +180 −0 framework/i18n/data/ar_eg.php
  176. +180 −0 framework/i18n/data/ar_iq.php
  177. +180 −0 framework/i18n/data/ar_jo.php
  178. +180 −0 framework/i18n/data/ar_kw.php
  179. +180 −0 framework/i18n/data/ar_lb.php
  180. +180 −0 framework/i18n/data/ar_ly.php
  181. +180 −0 framework/i18n/data/ar_ma.php
  182. +180 −0 framework/i18n/data/ar_om.php
  183. +180 −0 framework/i18n/data/ar_qa.php
  184. +180 −0 framework/i18n/data/ar_sa.php
  185. +180 −0 framework/i18n/data/ar_sd.php
  186. +180 −0 framework/i18n/data/ar_sy.php
  187. +180 −0 framework/i18n/data/ar_tn.php
  188. +180 −0 framework/i18n/data/ar_ye.php
  189. +156 −0 framework/i18n/data/as.php
  190. +156 −0 framework/i18n/data/as_in.php
  191. +164 −0 framework/i18n/data/az.php
  192. +164 −0 framework/i18n/data/az_az.php
  193. +164 −0 framework/i18n/data/az_cyrl.php
  194. +164 −0 framework/i18n/data/az_cyrl_az.php
  195. +164 −0 framework/i18n/data/az_latn.php
  196. +164 −0 framework/i18n/data/az_latn_az.php
  197. +159 −0 framework/i18n/data/be.php
  198. +159 −0 framework/i18n/data/be_by.php
  199. +254 −0 framework/i18n/data/bg.php
  200. +254 −0 framework/i18n/data/bg_bg.php
  201. +158 −0 framework/i18n/data/bn.php
  202. +158 −0 framework/i18n/data/bn_bd.php
  203. +158 −0 framework/i18n/data/bn_in.php
  204. +158 −0 framework/i18n/data/bs.php
  205. +158 −0 framework/i18n/data/bs_ba.php
  206. +158 −0 framework/i18n/data/byn.php
  207. +158 −0 framework/i18n/data/byn_er.php
  208. +159 −0 framework/i18n/data/ca.php
  209. +159 −0 framework/i18n/data/ca_es.php
  210. +157 −0 framework/i18n/data/cch.php
  211. +157 −0 framework/i18n/data/cch_ng.php
  212. +156 −0 framework/i18n/data/cop.php
  213. +253 −0 framework/i18n/data/cs.php
  214. +253 −0 framework/i18n/data/cs_cz.php
  215. +156 −0 framework/i18n/data/cy.php
  216. +156 −0 framework/i18n/data/cy_gb.php
  217. +251 −0 framework/i18n/data/da.php
  218. +251 −0 framework/i18n/data/da_dk.php
  219. +255 −0 framework/i18n/data/de.php
  220. +234 −0 framework/i18n/data/de_at.php
  221. +244 −0 framework/i18n/data/de_be.php
  222. +255 −0 framework/i18n/data/de_ch.php
  223. +255 −0 framework/i18n/data/de_de.php
  224. +255 −0 framework/i18n/data/de_li.php
  225. +256 −0 framework/i18n/data/de_lu.php
  226. +157 −0 framework/i18n/data/dv.php
  227. +157 −0 framework/i18n/data/dv_mv.php
  228. +157 −0 framework/i18n/data/dz.php
  229. +157 −0 framework/i18n/data/dz_bt.php
  230. +158 −0 framework/i18n/data/ee.php
  231. +158 −0 framework/i18n/data/ee_gh.php
  232. +158 −0 framework/i18n/data/ee_tg.php
  233. +246 −0 framework/i18n/data/el.php
  234. +246 −0 framework/i18n/data/el_cy.php
  235. +246 −0 framework/i18n/data/el_gr.php
  236. +234 −0 framework/i18n/data/el_polyton.php
  237. +271 −0 framework/i18n/data/en.php
  238. +271 −0 framework/i18n/data/en_as.php
  239. +271 −0 framework/i18n/data/en_au.php
  240. +271 −0 framework/i18n/data/en_be.php
  241. +272 −0 framework/i18n/data/en_bw.php
  242. +271 −0 framework/i18n/data/en_bz.php
  243. +271 −0 framework/i18n/data/en_ca.php
  244. +271 −0 framework/i18n/data/en_dsrt.php
  245. +271 −0 framework/i18n/data/en_dsrt_us.php
  246. +271 −0 framework/i18n/data/en_gb.php
  247. +271 −0 framework/i18n/data/en_gu.php
  248. +271 −0 framework/i18n/data/en_hk.php
  249. +271 −0 framework/i18n/data/en_ie.php
  250. +271 −0 framework/i18n/data/en_in.php
  251. +271 −0 framework/i18n/data/en_jm.php
  252. +271 −0 framework/i18n/data/en_mh.php
  253. +271 −0 framework/i18n/data/en_mp.php
  254. +271 −0 framework/i18n/data/en_mt.php
  255. +271 −0 framework/i18n/data/en_na.php
  256. +271 −0 framework/i18n/data/en_nz.php
Sorry, we could not display the entire diff because too many files (834) changed.
View
3  CHANGELOG
@@ -0,0 +1,3 @@
+Version 1.0a October 1, 2008
+=============================
+Initial release
View
31 COPYRIGHT
@@ -0,0 +1,31 @@
+The Yii framework is free software. It is released under the terms of
+the following BSD License.
+
+Copyright 2008, Yii Software LLC (http://www.yiisoft.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+- Neither the name of Yii Software LLC nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
31 LICENSE
@@ -0,0 +1,31 @@
+The Yii framework is free software. It is released under the terms of
+the following BSD License.
+
+Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Yii Software LLC nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
View
61 README
@@ -0,0 +1,61 @@
+
+ Yii Web Programming Framework
+ =============================
+
+Thank you for choosing Yii - a high-performance programming framework
+for developing Web applications in PHP 5.
+
+
+INSTALLATION
+------------
+Please make sure the release file is unpacked under a Web-accessible
+directory. You shall see the following files and directories:
+
+ framework/ containing the Yii framework source files
+ requirements/ containing the Yii requirement checker
+ CHANGELOG describing changes in every Yii release
+ LICENSE license of Yii
+ README this file
+ UPGRADE upgrading instructions
+
+
+REQUIREMENTS
+------------
+The minimum requirement by Yii is that your Web server supports
+PHP 5.2.1 or above. Yii has been tested with Apache HTTP server
+on Windows and Linux operating systems.
+
+Please access the following URL to check if your Web server reaches
+the requirements by Yii, assuming "YiiPath" is where Yii is installed:
+
+ http://hostname/YiiPath/requirements/index.php
+
+
+QUICK START
+-----------
+Yii comes with a command line tool called "yiic" that can create
+a skeleton Yii application for you to start with.
+
+On command line, type in the following commands:
+
+ $ cd YiiPath/framework (Linux)
+ cd YiiPath\framework (Windows)
+
+ $ ./yiic webapp ../testdrive (Linux)
+ yiic webapp ..\testdrive (Windows)
+
+The new Yii application will be created at "YiiPath/testdrive".
+You can access it with the following URL:
+
+ http://hostname/YiiPath/testdrive/index.php
+
+
+WHAT's NEXT
+-----------
+Please visit the project website for tutorials, class reference
+and join discussions with other Yii users.
+
+
+
+The Yii Team
+http://www.yiiframework.com
View
14 UPGRADE
@@ -0,0 +1,14 @@
+
+ Upgrading Instructions for Yii Framework v1.0a
+ ==============================================
+
+!!!IMPORTANT!!!
+
+The following upgrading instructions are cumulative. That is,
+if you want to upgrade from version A to version C and there is
+version B between A and C, you need to following the instructions
+for both A and B.
+
+
+Upgrading from v1.0a
+--------------------
View
21 build/build
@@ -0,0 +1,21 @@
+#!/usr/bin/env php
+<?php
+/**
+ * build script file.
+ *
+ * This is a command line script that provides various commands
+ * for building an Yii release.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version $Id$
+ */
+
+defined('YII_DEBUG') or define('YII_DEBUG',true);
+
+$root=dirname(__FILE__);
+require_once($root.'/../framework/yii.php');
+$config=array('basePath'=>$root);
+Yii::createConsoleApplication($config)->run();
View
23 build/build.bat
@@ -0,0 +1,23 @@
+@echo off
+
+rem -------------------------------------------------------------
+rem build script for Windows.
+rem
+rem This is the bootstrap script for running build on Windows.
+rem
+rem @author Qiang Xue <qiang.xue@gmail.com>
+rem @link http://www.yiiframework.com/
+rem @copyright Copyright &copy; 2008 Yii Software LLC
+rem @license http://www.yiiframework.com/license/
+rem @version $Id$
+rem -------------------------------------------------------------
+
+@setlocal
+
+set BUILD_PATH=%~dp0
+
+if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
+
+%PHP_COMMAND% "%BUILD_PATH%build" %*
+
+@endlocal
View
157 build/build.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Phing build file for Yii.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version $Id$
+ */
+-->
+<project name="yii" basedir="." default="help">
+ <!-- task definitions -->
+ <taskdef name="yii-init-build" classname="YiiInitTask" classpath="tasks" />
+
+ <!-- init yii.version, yii.revision and yii.winbuild -->
+ <yii-init-build />
+
+ <!-- these are required external commands -->
+ <property name="php" value="php" /> <!-- PHP parser -->
+ <property name="hhc" value="hhc" /> <!-- compile phpdoc into CHM -->
+ <property name="pdflatex" value="pdflatex" /> <!-- generates PDF from LaTex -->
+ <property name="zip" value="zip" /> <!-- zip compression -->
+
+ <property name="pkgname" value="${phing.project.name}-${yii.version}.r${yii.revision}"/>
+ <property name="docname" value="${phing.project.name}-docs-${yii.version}.r${yii.revision}"/>
+
+ <!-- directory definitions -->
+ <property name="build.base.dir" value="release"/>
+ <property name="build.dist.dir" value="${build.base.dir}/dist"/>
+ <property name="build.src.dir" value="${build.base.dir}/${pkgname}"/>
+ <property name="build.doc.dir" value="${build.base.dir}/${docname}"/>
+ <property name="build.web.dir" value="${build.base.dir}/web"/>
+
+ <!-- source files in the framework -->
+ <fileset dir=".." id="framework">
+ <exclude name="**/.svn"/>
+ <exclude name="**/*.bak"/>
+ <exclude name="**/*~"/>
+ <include name="framework/**/*"/>
+ <include name="requirements/*"/>
+ <include name="COPYRIGHT"/>
+ <include name="CHANGELOG"/>
+ <include name="UPGRADE"/>
+ <include name="LICENSE"/>
+ <include name="README"/>
+ </fileset>
+
+ <target name="build" depends="prebuild">
+ <echo>Building package ${pkgname}...</echo>
+ <echo>Copying files to build directory...</echo>
+ <copy todir="${build.src.dir}">
+ <fileset refid="framework"/>
+ </copy>
+ </target>
+
+ <target name="docs" depends="prebuild">
+ <echo>Building documentation...</echo>
+
+ <echo>Building API...</echo>
+ <mkdir dir="${build.doc.dir}" />
+ <exec command="build api ${build.doc.dir}" dir="." passthru="true" />
+
+ <echo>Building API CHM...</echo>
+ <exec command="${hhc} ${build.doc.dir}/api/manual.hhp" />
+ <move file="${build.doc.dir}/api/manual.chm" tofile="${build.doc.dir}/yii-api-${yii.version}.chm" />
+ <delete>
+ <fileset dir="${build.doc.dir}/api">
+ <include name="manual.*" />
+ </fileset>
+ </delete>
+ </target>
+
+ <target name="web" depends="prebuild">
+ <echo>Building online API...</echo>
+ <mkdir dir="${build.web.dir}/views/doc" />
+ <mkdir dir="${build.web.dir}/controllers/doc" />
+ <exec command="build api ${build.web.dir}/views/doc online" dir="." passthru="true" />
+ <move file="${build.web.dir}/views/doc/apiKeywords.txt" tofile="${build.web.dir}/controllers/doc/apiKeywords.txt" />
+ </target>
+
+ <target name="prebuild">
+ <echo>Preparing build ${pkgname}...</echo>
+
+ <echo>Building autoload map...</echo>
+ <exec command="build autoload" dir="." passthru="true"/>
+
+ <echo>Building yiilite.php...</echo>
+ <exec command="build lite" dir="." passthru="true"/>
+ </target>
+
+ <target name="rebuild" depends="clean,build">
+ </target>
+
+ <target name="dist" depends="clean,build,docs,web">
+ <echo>Generating release distributions...</echo>
+ <mkdir dir="${build.dist.dir}" />
+ <tar destfile="${build.dist.dir}/${pkgname}.tar.gz" compression="gzip">
+ <fileset dir="${build.base.dir}">
+ <include name="${pkgname}/**/*"/>
+ </fileset>
+ </tar>
+ <tar destfile="${build.dist.dir}/web.tar.gz" compression="gzip">
+ <fileset dir="${build.base.dir}">
+ <include name="web/**/*"/>
+ </fileset>
+ </tar>
+ <tar destfile="${build.dist.dir}/${docname}.tar.gz" compression="gzip">
+ <fileset dir="${build.base.dir}">
+ <include name="${docname}/**/*"/>
+ </fileset>
+ </tar>
+ <zip destfile="${build.dist.dir}/${pkgname}.zip">
+ <fileset dir="${build.base.dir}">
+ <include name="${pkgname}/**/*"/>
+ </fileset>
+ </zip>
+ <zip destfile="${build.dist.dir}/web.zip">
+ <fileset dir="${build.base.dir}">
+ <include name="web/**/*"/>
+ </fileset>
+ </zip>
+ <zip destfile="${build.dist.dir}/${docname}.zip">
+ <fileset dir="${build.base.dir}">
+ <include name="${docname}/**/*"/>
+ </fileset>
+ </zip>
+ </target>
+
+ <target name="clean">
+ <echo>Cleaning up the build...</echo>
+ <delete dir="${build.base.dir}"/>
+ </target>
+
+ <target name="help">
+ <echo>
+
+ Welcome to use Yii build script!
+ --------------------------------
+ You may use the following command format to build a target:
+
+ phing &lt;target name&gt;
+
+ where &lt;target name&gt; can be one of the following:
+
+ - dist : create a release;
+ - build : prepare a directory for distribution;
+ - clean : clean up the build directory;
+ - rebuild : clean first and then build;
+ - docs : generate documentation;
+ - pear : generate PEAR packages;
+ - snapshot : generate nightly snapshot;
+
+ </echo>
+ </target>
+</project>
View
290 build/commands/ApiCommand.php
@@ -0,0 +1,290 @@
+<?php
+/**
+ * ApiCommand class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+Yii::import('application.commands.api.ApiModel');
+
+/**
+ * MessageCommand extracts messages to be translated from source files.
+ * The extracted messages are saved as PHP message source files
+ * under the specified directory.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package system.build
+ * @since 1.0
+ */
+class ApiCommand extends CConsoleCommand
+{
+ const URL_PATTERN='/\{\{(.*?)\|(.*?)\}\}/s';
+ public $classes;
+ public $packages;
+ public $pageTitle;
+ public $themePath;
+ public $currentClass;
+
+ public function getHelp()
+ {
+ return <<<EOD
+USAGE
+ build api <output-path> [mode]
+
+DESCRIPTION
+ This command generates offline API documentation for the Yii framework.
+
+PARAMETERS
+ * output-path: required, the directory where the generated documentation
+ would be saved.
+ * mode: optional, either 'online' or 'offline' (default). This indicates
+ whether the generated documentation are for online or offline use.
+
+EOD;
+ }
+
+ /**
+ * Execute the action.
+ * @param array command line parameters specific for this command
+ */
+ public function run($args)
+ {
+ if(!isset($args[0]))
+ $this->usageError('the output directory is not specified.');
+ if(!is_dir($docPath=$args[0]))
+ $this->usageError("the output directory {$docPath} does not exist.");
+
+ $offline=true;
+ if(isset($args[1]) && $args[1]==='online')
+ $offline=false;
+
+ $options=array(
+ 'fileTypes'=>array('php'),
+ 'exclude'=>array(
+ '.svn',
+ 'yiilite.php',
+ '/cli',
+ '/i18n/data',
+ '/messages',
+ '/vendors',
+ '/views',
+ '/web/js',
+ ),
+ );
+ $this->pageTitle='Yii Framework Class Reference';
+ $themePath=dirname(__FILE__).'/api';
+
+ $model=$this->buildModel(YII_PATH,$options);
+
+ $this->classes=$model->classes;
+ $this->packages=$model->packages;
+
+ if($offline)
+ $this->buildOfflinePages($docPath.DIRECTORY_SEPARATOR.'api',$themePath);
+ else
+ {
+ $this->buildOnlinePages($docPath.DIRECTORY_SEPARATOR.'api',$themePath);
+ $this->buildKeywords($docPath);
+ }
+ }
+
+ protected function buildKeywords($docPath)
+ {
+ $keywords=array();
+ foreach($this->classes as $class)
+ $keywords[]=$class->name;
+ foreach($this->classes as $class)
+ {
+ $name=$class->name;
+ foreach($class->properties as $property)
+ {
+ if(!$property->isInherited)
+ $keywords[]=$name.'.'.$property->name;
+ }
+ foreach($class->methods as $method)
+ {
+ if(!$method->isInherited)
+ $keywords[]=$name.'.'.$method->name.'()';
+ }
+ }
+ file_put_contents($docPath.'/apiKeywords.txt',implode(',',$keywords));
+ }
+
+ public function render($view,$data=null,$return=false,$layout='main')
+ {
+ $viewFile=$this->themePath."/views/{$view}.php";
+ $layoutFile=$this->themePath."/layouts/{$layout}.php";
+ $content=$this->renderFile($viewFile,$data,true);
+ return $this->renderFile($layoutFile,array('content'=>$content),$return);
+ }
+
+ public function renderPartial($view,$data=null,$return=false)
+ {
+ $viewFile=$this->themePath."/views/{$view}.php";
+ return $this->renderFile($viewFile,$data,$return);
+ }
+
+ protected function buildOfflinePages($docPath,$themePath)
+ {
+ $this->themePath=$themePath;
+ @mkdir($docPath);
+ $content=$this->render('index',null,true);
+ $content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOfflineLink'),$content);
+ file_put_contents($docPath.'/index.html',$content);
+
+ foreach($this->classes as $name=>$class)
+ {
+ $this->currentClass=$name;
+ $this->pageTitle=$name;
+ $content=$this->render('class',array('class'=>$class),true);
+ $content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOfflineLink'),$content);
+ file_put_contents($docPath.'/'.$name.'.html',$content);
+ }
+
+ CFileHelper::copyDirectory($this->themePath.'/assets',$docPath,array('exclude'=>array('.svn')));
+
+ $content=$this->renderPartial('chmProject',null,true);
+ file_put_contents($docPath.'/manual.hhp',$content);
+
+ $content=$this->renderPartial('chmIndex',null,true);
+ file_put_contents($docPath.'/manual.hhk',$content);
+
+ $content=$this->renderPartial('chmContents',null,true);
+ file_put_contents($docPath.'/manual.hhc',$content);
+ }
+
+ protected function buildOnlinePages($docPath,$themePath)
+ {
+ $this->themePath=$themePath;
+ @mkdir($docPath);
+ $content=$this->renderPartial('index',null,true);
+ $content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOnlineLink'),$content);
+ file_put_contents($docPath.'/index.php',$content);
+
+ foreach($this->classes as $name=>$class)
+ {
+ $this->currentClass=$name;
+ $this->pageTitle=$name;
+ $content=$this->renderPartial('class',array('class'=>$class),true);
+ $content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOnlineLink'),$content);
+ file_put_contents($docPath.'/'.$name.'.php',$content);
+ }
+ }
+
+ protected function buildModel($sourcePath,$options)
+ {
+ $files=CFileHelper::findFiles($sourcePath,$options);
+ $model=new ApiModel;
+ $model->build($files);
+ return $model;
+ }
+
+ public function renderInheritance($class)
+ {
+ $parents=array($class->signature);
+ foreach($class->parentClasses as $parent)
+ {
+ if(isset($this->classes[$parent]))
+ $parents[]='{{'.$parent.'|'.$parent.'}}';
+ else
+ $parents[]=$parent;
+ }
+ return implode(" &raquo;\n",$parents);
+ }
+
+ public function renderImplements($class)
+ {
+ $interfaces=array();
+ foreach($class->interfaces as $interface)
+ {
+ if(isset($this->classes[$interface]))
+ $interfaces[]='{{'.$interface.'|'.$interface.'}}';
+ else
+ $interfaces[]=$interface;
+ }
+ return implode(', ',$interfaces);
+ }
+
+ public function renderSubclasses($class)
+ {
+ $subclasses=array();
+ foreach($class->subclasses as $subclass)
+ {
+ if(isset($this->classes[$subclass]))
+ $subclasses[]='{{'.$subclass.'|'.$subclass.'}}';
+ else
+ $subclasses[]=$subclass;
+ }
+ return implode(', ',$subclasses);
+ }
+
+ public function renderTypeUrl($type)
+ {
+ if(isset($this->classes[$type]) && $type!==$this->currentClass)
+ return '{{'.$type.'|'.$type.'}}';
+ else
+ return $type;
+ }
+
+ public function renderSubjectUrl($type,$subject,$text=null)
+ {
+ if($text===null)
+ $text=$subject;
+ if(isset($this->classes[$type]))
+ return '{{'.$type.'::'.$subject.'|'.$text.'}}';
+ else
+ return $text;
+ }
+
+ public function renderPropertySignature($property)
+ {
+ if(!empty($property->signature))
+ return $property->signature;
+ $sig='';
+ if(!empty($property->getter))
+ $sig=$property->getter->signature;
+ if(!empty($property->setter))
+ {
+ if($sig!=='')
+ $sig.='<br/>';
+ $sig.=$property->setter->signature;
+ }
+ return $sig;
+ }
+
+ protected function fixOfflineLink($matches)
+ {
+ if(($pos=strpos($matches[1],'::'))!==false)
+ {
+ $className=substr($matches[1],0,$pos);
+ $method=substr($matches[1],$pos+2);
+ return "<a href=\"{$className}.html#{$method}\">{$matches[2]}</a>";
+ }
+ else
+ return "<a href=\"{$matches[1]}.html\">{$matches[2]}</a>";
+ }
+
+ protected function fixOnlineLink($matches)
+ {
+ if(($pos=strpos($matches[1],'::'))!==false)
+ {
+ $className=substr($matches[1],0,$pos);
+ $method=substr($matches[1],$pos+2);
+ if($className==='index')
+ return "<a href=\"/doc/api/#{$method}\">{$matches[2]}</a>";
+ else
+ return "<a href=\"/doc/api/{$className}#{$method}\">{$matches[2]}</a>";
+ }
+ else
+ {
+ if($matches[1]==='index')
+ return "<a href=\"/doc/api/\">{$matches[2]}</a>";
+ else
+ return "<a href=\"/doc/api/{$matches[1]}\">{$matches[2]}</a>";
+ }
+ }
+}
View
79 build/commands/AutoloadCommand.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * AutoloadCommand class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version $Id$
+ */
+
+/**
+ * AutoloadCommand generates the class map for {@link YiiBase}.
+ * The class file YiiBase.php will be modified with updated class map.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package system.build
+ * @since 1.0
+ */
+class AutoloadCommand extends CConsoleCommand
+{
+ public function getHelp()
+ {
+ return <<<EOD
+USAGE
+ build autoload
+
+DESCRIPTION
+ This command updates YiiBase.php with the latest class map.
+ The class map is used by Yii::autoload() to quickly include a class on demand.
+
+ Do not run this command unless you change or add core framework classes.
+
+EOD;
+ }
+
+ /**
+ * Execute the action.
+ * @param array command line parameters specific for this command
+ */
+ public function run($args)
+ {
+ $options=array(
+ 'fileTypes'=>array('php'),
+ 'exclude'=>array(
+ '.svn',
+ '/messages',
+ '/views',
+ '/cli',
+ '/yii.php',
+ '/web/js',
+ '/vendors',
+ '/i18n/data',
+ ),
+ );
+ $files=CFileHelper::findFiles(YII_PATH,$options);
+ $map='';
+ foreach($files as $file)
+ {
+ if(($pos=strpos($file,YII_PATH))!==0)
+ die("Invalid file '$file' found.");
+ $path=str_replace('\\','/',substr($file,strlen(YII_PATH)));
+ $className=substr(basename($path),0,-4);
+ if($className[0]==='C')
+ $map.="\t\t'$className' => '$path',\n";
+ }
+
+ $yiiBase=file_get_contents(YII_PATH.'/YiiBase.php');
+ $newYiiBase=preg_replace('/private static \$_classes=array\([^\)]*\);/',"private static \$_classes=array(\n{$map}\t);",$yiiBase);
+ if($yiiBase!==$newYiiBase)
+ echo "Nothing changed.\n";
+ else
+ {
+ file_put_contents(YII_PATH.'/YiiBase.php',$newYiiBase);
+ echo "YiiBase.php is updated successfully.\n";
+ }
+ }
+}
View
325 build/commands/CldrCommand.php
@@ -0,0 +1,325 @@
+<?php
+/**
+ * CldrCommand class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version $Id$
+ */
+
+/**
+ * CldrCommand converts the locale data from the {@link http://www.unicode.org/cldr/ CLDR project}
+ * to PHP scripts so that they can be more easily used in PHP programming.
+ *
+ * The script respects locale inheritance so that the PHP data for a child locale
+ * will contain all its parents' locale data if they are not specified in the child locale.
+ * Therefore, to import the data for a locale, only the PHP script for that particular locale
+ * needs to be included.
+ *
+ * Note, only the data relevant to number and date formatting are extracted.
+ * Each PHP script file is named as the corresponding locale ID in lower case.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package system.build
+ * @since 1.0
+ */
+class CldrCommand extends CConsoleCommand
+{
+ public function getHelp()
+ {
+ return <<<EOD
+USAGE
+ build cldr <data-path>
+
+DESCRIPTION
+ This command converts the locale data from the CLDR project
+ to PHP scripts so that they can be more easily used in PHP programming.
+
+ The script respects locale inheritance so that the PHP data for
+ a child locale will contain all its parent locale data if they are
+ not specified in the child locale. Therefore, to import the data
+ for a locale, only the PHP script for that particular locale needs
+ to be included.
+
+ Note, only the data relevant to number and date formatting are extracted.
+ Each PHP script file is named as the corresponding locale ID in lower case.
+
+ The resulting PHP scripts are created under the same directory that
+ contains the original CLDR data.
+
+PARAMETERS
+ * data-path: required, the original CLDR data directory. This
+ directory should contain hundreds of XML files.
+
+EOD;
+ }
+
+ /**
+ * Execute the action.
+ * @param array command line parameters specific for this command
+ */
+ public function run($args)
+ {
+ if(!isset($args[0]))
+ $this->usageError('the CLDR data directory is not specified.');
+ if(!is_dir($path=$args[0]))
+ $this->usageError("directory '$path' does not exist.");
+
+ // collect XML files to be processed
+ $options=array(
+ 'exclude'=>array('.svn'),
+ 'fileTypes'=>array('xml'),
+ 'level'=>0,
+ );
+ $files=CFileHelper::findFiles(realpath($path),$options);
+ $sourceFiles=array();
+ foreach($files as $file)
+ $sourceFiles[basename($file)]=$file;
+
+ // sort by file name so that inheritances can be processed properly
+ ksort($sourceFiles);
+
+ // process root first because it is inherited by all
+ if(isset($sourceFiles['root.xml']))
+ {
+ $this->process($sourceFiles['root.xml']);
+ unset($sourceFiles['root.xml']);
+
+ foreach($sourceFiles as $sourceFile)
+ $this->process($sourceFile);
+ }
+ else
+ die('Unable to find the required root.xml under CLDR data directory.');
+ }
+
+ protected function process($path)
+ {
+ $source=basename($path);
+ echo "processing $source...";
+
+ $dir=dirname($path);
+ $locale=substr($source,0,-4);
+ $target=$locale.'.php';
+
+ // retrieve parent data first
+ if(($pos=strrpos($locale,'_'))!==false)
+ $data=require($dir.DIRECTORY_SEPARATOR.substr($locale,0,$pos).'.php');
+ else if($locale!=='root')
+ $data=require($dir.DIRECTORY_SEPARATOR.'root.php');
+ else
+ $data=array();
+
+ $xml=simplexml_load_file($path);
+
+ $this->parseVersion($xml,$data);
+
+ $this->parseNumberSymbols($xml,$data);
+ $this->parseNumberFormats($xml,$data);
+ $this->parseCurrencySymbols($xml,$data);
+
+ $this->parseMonthNames($xml,$data);
+ $this->parseWeekDayNames($xml,$data);
+ $this->parseEraNames($xml,$data);
+
+ $this->parseDateFormats($xml,$data);
+ $this->parseTimeFormats($xml,$data);
+ $this->parseDateTimeFormat($xml,$data);
+ $this->parsePeriodNames($xml,$data);
+
+ $data=var_export($data,true);
+ $locale=substr(basename($path),0,-4);
+ $content=<<<EOD
+/**
+ * Locale data for '$locale'.
+ *
+ * This file is automatically generated by yiic cldr command.
+ *
+ * Copyright © 1991-2007 Unicode, Inc. All rights reserved.
+ * Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+ *
+ * Copyright © 2008 Yii Software LLC (http://www.yiiframework.com/license/)
+ */
+return $data;
+EOD;
+
+ file_put_contents($dir.DIRECTORY_SEPARATOR.strtolower($locale).'.php',"<?php\n".$content."\n?>");
+
+ echo "done.\n";
+ }
+
+ protected function parseVersion($xml,&$data)
+ {
+ preg_match('/[\d\.]+/',(string)$xml->identity->version['number'],$matches);
+ $data['version']=$matches[0];
+ }
+
+ protected function parseNumberSymbols($xml,&$data)
+ {
+ foreach($xml->xpath('/ldml/numbers/symbols/*') as $symbol)
+ $data['numberSymbols'][$symbol->getName()]=(string)$symbol;
+ }
+
+ protected function parseNumberFormats($xml,&$data)
+ {
+ $pattern=$xml->xpath('/ldml/numbers/decimalFormats/decimalFormatLength/decimalFormat/pattern');
+ if(isset($pattern[0]))
+ $data['decimalFormat']=(string)$pattern[0];
+ $pattern=$xml->xpath('/ldml/numbers/scientificFormats/scientificFormatLength/scientificFormat/pattern');
+ if(isset($pattern[0]))
+ $data['scientificFormat']=(string)$pattern[0];
+ $pattern=$xml->xpath('/ldml/numbers/percentFormats/percentFormatLength/percentFormat/pattern');
+ if(isset($pattern[0]))
+ $data['percentFormat']=(string)$pattern[0];
+ $pattern=$xml->xpath('/ldml/numbers/currencyFormats/currencyFormatLength/currencyFormat/pattern');
+ if(isset($pattern[0]))
+ $data['currencyFormat']=(string)$pattern[0];
+ }
+
+ protected function parseCurrencySymbols($xml,&$data)
+ {
+ $currencies=$xml->xpath('/ldml/numbers/currencies/currency');
+ foreach($currencies as $currency)
+ {
+ if((string)$currency->symbol!='')
+ $data['currencySymbols'][(string)$currency['type']]=(string)$currency->symbol;
+ }
+ }
+
+ protected function parseMonthNames($xml,&$data)
+ {
+ $monthTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/months/monthContext[@type=\'format\']/monthWidth');
+ if(is_array($monthTypes))
+ {
+ foreach($monthTypes as $monthType)
+ {
+ $names=array();
+ foreach($monthType->xpath('month') as $month)
+ $names[(string)$month['type']]=(string)$month;
+ if($names!==array())
+ $data['monthNames'][(string)$monthType['type']]=$names;
+ }
+ }
+
+ if(!isset($data['monthNames']['abbreviated']))
+ $data['monthNames']['abbreviated']=$data['monthNames']['wide'];
+
+ $monthTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/months/monthContext[@type=\'stand-alone\']/monthWidth[@type=\'narrow\']');
+ if(is_array($monthTypes) && isset($monthTypes[0]))
+ {
+ foreach($monthTypes[0]->xpath('month') as $month)
+ $data['monthNames']['narrow'][(string)$month['type']]=(string)$month;
+ }
+ }
+
+ protected function parseWeekDayNames($xml,&$data)
+ {
+ static $mapping=array(
+ 'sun'=>0,
+ 'mon'=>1,
+ 'tue'=>2,
+ 'wed'=>3,
+ 'thu'=>4,
+ 'fri'=>5,
+ 'sat'=>6,
+ );
+ $dayTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/days/dayContext[@type=\'format\']/dayWidth');
+ if(is_array($dayTypes))
+ {
+ foreach($dayTypes as $dayType)
+ {
+ $names=array();
+ foreach($dayType->xpath('day') as $day)
+ $names[$mapping[(string)$day['type']]]=(string)$day;
+ if($names!==array())
+ $data['weekDayNames'][(string)$dayType['type']]=$names;
+ }
+ }
+
+ if(!isset($data['weekDayNames']['abbreviated']))
+ $data['weekDayNames']['abbreviated']=$data['weekDayNames']['wide'];
+
+ $dayTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/days/dayContext[@type=\'stand-alone\']/dayWidth[@type=\'narrow\']');
+ if(is_array($dayTypes) && isset($dayTypes[0]))
+ {
+ foreach($dayTypes[0]->xpath('day') as $day)
+ $data['weekDayNames']['narrow'][(string)$day['type']]=(string)$day;
+ }
+ }
+
+ protected function parsePeriodNames($xml,&$data)
+ {
+ $am=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/am');
+ if(is_array($am) && isset($am[0]))
+ $data['amName']=(string)$am[0];
+ $pm=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/pm');
+ if(is_array($pm) && isset($pm[0]))
+ $data['pmName']=(string)$pm[0];
+ }
+
+ protected function parseEraNames($xml,&$data)
+ {
+ $era=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/eras/eraAbbr');
+ if(is_array($era) && isset($era[0]))
+ {
+ foreach($era[0]->xpath('era') as $e)
+ $data['eraNames']['abbreviated'][(string)$e['type']]=(string)$e;
+ }
+
+ $era=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/eras/eraNames');
+ if(is_array($era) && isset($era[0]))
+ {
+ foreach($era[0]->xpath('era') as $e)
+ $data['eraNames']['wide'][(string)$e['type']]=(string)$e;
+ }
+ else if(!isset($data['eraNames']['wide']))
+ $data['eraNames']['wide']=$data['eraNames']['abbreviated'];
+
+ $era=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/eras/eraNarrow');
+ if(is_array($era) && isset($era[0]))
+ {
+ foreach($era[0]->xpath('era') as $e)
+ $data['eraNames']['narrow'][(string)$e['type']]=(string)$e;
+ }
+ else if(!isset($data['eraNames']['narrow']))
+ $data['eraNames']['narrow']=$data['eraNames']['abbreviated'];
+ }
+
+ protected function parseDateFormats($xml,&$data)
+ {
+ $types=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/dateFormats/dateFormatLength');
+ if(is_array($types))
+ {
+ foreach($types as $type)
+ {
+ $pattern=$type->xpath('dateFormat/pattern');
+ $data['dateFormats'][(string)$type['type']]=(string)$pattern[0];
+ }
+ }
+ }
+
+ protected function parseTimeFormats($xml,&$data)
+ {
+ $types=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/timeFormats/timeFormatLength');
+ if(is_array($types))
+ {
+ foreach($types as $type)
+ {
+ $pattern=$type->xpath('timeFormat/pattern');
+ $data['timeFormats'][(string)$type['type']]=(string)$pattern[0];
+ }
+ }
+ }
+
+ protected function parseDateTimeFormat($xml,&$data)
+ {
+ $types=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/dateTimeFormats/dateTimeFormatLength');
+ if(is_array($types) && isset($types[0]))
+ {
+ $pattern=$types[0]->xpath('dateTimeFormat/pattern');
+ $data['dateTimeFormat']=(string)$pattern[0];
+ }
+ }
+}
View
221 build/commands/LiteCommand.php
@@ -0,0 +1,221 @@
+<?php
+/**
+ * LiteCommand class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version $Id$
+ */
+
+/**
+ * LiteCommand generates yiilite.php by merging commonly used Yii class
+ * files into a single one and removes all comments and trace statements.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package system.build
+ * @since 1.0
+ */
+class LiteCommand extends CConsoleCommand
+{
+ public function getHelp()
+ {
+ return <<<EOD
+USAGE
+ build lite
+
+DESCRIPTION
+ This command generates yiilite.php by merging commonly used Yii class
+ files into a single one and removes all comments and trace statements.
+
+ You should not execute this command unless you change some framework
+ file and need to update yii.php accordingly.
+
+EOD;
+ }
+
+ /**
+ * Execute the action.
+ * @param array command line parameters specific for this command
+ */
+ public function run($args)
+ {
+ $lastupdate=date('Y/m/d H:i:s');
+ $comments="
+/**
+ * Yii bootstrap file.
+ *
+ * This file is automatically generated using 'build lite' command.
+ * It is the result of merging commonly used Yii class files with
+ * comments and trace statements removed away.
+ *
+ * By using this file instead of yii.php, an Yii application may
+ * improve performance due to the reduction of PHP parsing time.
+ * The performance improvement is especially obvious when PHP APC extension
+ * is enabled.
+ *
+ * DO NOT modify this file manually.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version \$Id: \$
+ * @since 1.0
+ */
+
+";
+
+ $content=$this->minifyYii(dirname(__FILE__).'/lite/index.php');
+ $content="<?php\n".preg_replace('/^(\?>|<\?php)/mu','',$content)."\n?>";
+ $content=$this->stripComments($content);
+ $content=preg_replace('/^require_once.*\s*;\s*$/mu','',$content);
+ $content=preg_replace('/^\s*Yii::trace.*\s*;\s*$/mu','',$content);
+ $content=preg_replace('/^\s*Yii::(begin|end)Profile.*\s*;\s*$/mu','',$content);
+ $content=$this->stripEmptyLines($content);
+ $content=substr_replace($content,$comments,5,0);
+ file_put_contents(YII_PATH.DIRECTORY_SEPARATOR.'yiilite.php',$content);
+ echo "Done.\n";
+ }
+
+ protected function minifyYii($entryScript)
+ {
+ try
+ {
+ ob_start();
+ $this->runRequest($entryScript);
+ $this->runRequest($entryScript,array('r'=>'post/list'));
+ ob_end_clean();
+ }
+ catch(CException $e)
+ {
+ echo $e;
+ die();
+ }
+ $classes=array_merge(get_declared_classes(),get_declared_interfaces());
+ $results=array();
+ foreach($classes as $class)
+ {
+ $c=new ReflectionClass($class);
+ if(strpos($c->getFileName(),YII_PATH)===0 && strpos($c->getFileName(),YII_PATH.DIRECTORY_SEPARATOR.'console')!==0)
+ $results[$class]=$c->getFileName();
+ }
+ $results=$this->sortByInheritance($results);
+
+ $content='';
+ foreach($results as $fileName=>$class)
+ $content.="\n".file_get_contents($fileName);
+ $content.="\n".file_get_contents(YII_PATH.'/core/functions.php');
+
+ return $content;
+ }
+
+ protected function sortByInheritance($classes)
+ {
+ $results=array();
+ foreach($classes as $class=>$fileName)
+ $this->processClass($class,$classes,$results);
+ return $results;
+ }
+
+ protected function processClass($class,$classes,&$results)
+ {
+ $parentClass=get_parent_class($class);
+ if($parentClass!==false && isset($classes[$parentClass]))
+ {
+ if(!isset($results[$classes[$parentClass]]))
+ $this->processClass($parentClass,$classes,$results);
+ }
+ if(!isset($results[$classes[$class]]))
+ {
+ // some file may contain multiple classes
+ // we only want to include when the primary one appears
+ if($class[0]!=='C' || $class===substr(basename($classes[$class]),0,-4))
+ $results[$classes[$class]]=$class;
+ }
+ }
+
+ protected function runRequest($entryScript,$params=array())
+ {
+ restore_error_handler();
+ restore_exception_handler();
+ Yii::setApplication(null);
+ Yii::setPathOfAlias('application',null);
+ $_GET=$params;
+ require($entryScript);
+ }
+
+ protected function stripComments($source)
+ {
+ $tokens = token_get_all($source);
+ $output = '';
+ foreach ($tokens as $token)
+ {
+ if (is_string($token))
+ {
+ // simple 1-character token
+ $output .= $token;
+ }
+ else
+ {
+ // token array
+ list($id, $text) = $token;
+ switch ($id) {
+ case T_DOC_COMMENT: // and this
+ // no action on comments
+ break;
+ default:
+ // anything else -> output "as is"
+ $output .= $text;
+ break;
+ }
+ }
+ }
+ return $output;
+ }
+
+ protected function stripEmptyLines($string)
+ {
+ $string = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/", "\n", $string);
+ $string = preg_replace("/^[\s\t]*[\r\n]+/", "", $string);
+ return $string;
+ }
+
+ protected function unfoldFile($fileName)
+ {
+ static $unfoldedFiles=array();
+ $pattern='^(Yii::import|require_once|include_once)\s*\(.*?[\'"]([^\*]*?)[\'"].*?\);';
+ echo "adding $fileName...\n";
+ $content=file_get_contents($fileName);
+ while(preg_match("/$pattern/m",$content,$matches,PREG_OFFSET_CAPTURE))
+ {
+ $offset=$matches[0][1];
+ $length=strlen($matches[0][0]);
+ $type=$matches[1][0];
+ $file=trim($matches[2][0],"'\"");
+ if($type==='Yii::import')
+ {
+ // replace system with framework path and dot with directory separator
+ $file=substr_replace(strtr($file,'.',DIRECTORY_SEPARATOR),YII_PATH,0,6).'.php';
+ }
+ else
+ {
+ $file=YII_PATH.$file;
+ }
+ if(($file=realpath($file))===false || !is_file($file))
+ die('Unable to process file '.$fileName.' about '.$matches[0][0]);
+ if(isset($unfoldedFiles[$file]))
+ {
+ $content=substr_replace($content,'',$offset,$length);
+ }
+ else
+ {
+ $unfoldedFiles[$file]=true;
+ $content=substr_replace($content,$this->unfoldFile($file),$offset,$length);
+ }
+ }
+ return $content;
+ }
+}
View
643 build/commands/api/ApiModel.php
@@ -0,0 +1,643 @@
+<?php
+/**
+ * ApiModel class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ * @version $Id$
+ */
+
+/**
+ * ApiModel represents the documentation for the Yii framework.
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package system.build
+ * @since 1.0
+ */
+class ApiModel
+{
+ public $classes=array();
+ public $packages;
+
+ private $_currentClass;
+
+ public function build($sourceFiles)
+ {
+ $this->findClasses($sourceFiles);
+ $this->processClasses();
+ }
+
+ protected function findClasses($sourceFiles)
+ {
+ $this->classes=array();
+
+ foreach($sourceFiles as $file)
+ require_once($file);
+
+ $classes=array_merge(get_declared_classes(),get_declared_interfaces());
+ foreach($classes as $class)
+ {
+ $r=new ReflectionClass($class);
+ if(in_array($r->getFileName(),$sourceFiles))
+ $this->classes[$class]=true;
+ }
+ ksort($this->classes);
+ }
+
+ protected function processClasses()
+ {
+ $this->packages=array();
+ foreach($this->classes as $class=>$value)
+ {
+ $doc=$this->processClass(new ReflectionClass($class));
+ $this->classes[$class]=$doc;
+ $this->packages[$doc->package][]=$class;
+ }
+ ksort($this->packages);
+
+ // find out child classes for each class or interface
+ foreach($this->classes as $class)
+ {
+ if(isset($class->parentClasses[0]))
+ {
+ $parent=$class->parentClasses[0];
+ if(isset($this->classes[$parent]))
+ $this->classes[$parent]->subclasses[]=$class->name;
+ }
+ foreach($class->interfaces as $interface)
+ {
+ if(isset($this->classes[$interface]))
+ $this->classes[$interface]->subclasses[]=$class->name;
+ }
+ }
+ }
+
+ protected function processClass($class)
+ {
+ $doc=new ClassDoc;
+ $doc->name=$class->getName();
+ $this->_currentClass=$doc->name;
+ for($parent=$class;$parent=$parent->getParentClass();)
+ $doc->parentClasses[]=$parent->getName();
+ foreach($class->getInterfaces() as $interface)
+ $doc->interfaces[]=$interface->getName();
+ $doc->isInterface=$class->isInterface();
+ $doc->isAbstract=$class->isAbstract();
+ $doc->isFinal=$class->isFinal();
+ $doc->methods=$this->processMethods($class);
+ $doc->properties=$this->processProperties($class);
+ $doc->signature=($doc->isInterface?'interface ':'class ').$doc->name;
+ if($doc->isFinal)
+ $doc->signature='final '.$doc->signature;
+ if($doc->isAbstract && !$doc->isInterface)
+ $doc->signature='abstract '.$doc->signature;
+ if(in_array('CComponent',$doc->parentClasses))
+ {
+ $doc->properties=array_merge($doc->properties,$this->processComponentProperties($class));
+ $doc->events=$this->processComponentEvents($class);
+ }
+ ksort($doc->properties);
+
+ foreach($doc->properties as $property)
+ {
+ if($property->isProtected)
+ $doc->protectedPropertyCount++;
+ else
+ $doc->publicPropertyCount++;
+ if(!$property->isInherited)
+ $doc->nativePropertyCount++;
+ }
+ foreach($doc->methods as $method)
+ {
+ if($method->isProtected)
+ $doc->protectedMethodCount++;
+ else
+ $doc->publicMethodCount++;
+ if(!$method->isInherited)
+ $doc->nativeMethodCount++;
+ }
+ foreach($doc->events as $event)
+ {
+ if(!$event->isInherited)
+ $doc->nativeEventCount++;
+ }
+ $this->processComment($doc,$class->getDocComment());
+
+ return $doc;
+ }
+
+ protected function processComment($doc,$comment)
+ {
+ $comment=strtr(trim(preg_replace('/^\s*\**( |\t)?/m','',trim($comment,'/'))),"\r",'');
+ if(preg_match('/^\s*@\w+/m',$comment,$matches,PREG_OFFSET_CAPTURE))
+ {
+ $meta=substr($comment,$matches[0][1]);
+ $comment=trim(substr($comment,0,$matches[0][1]));
+ }
+ else
+ $meta='';
+ if(($pos=strpos($comment,"\n"))!==false)
+ $doc->introduction=$this->processDescription(substr($comment,0,$pos));
+ else
+ $doc->introduction=$this->processDescription($comment);
+
+ $doc->description=$this->processDescription($comment);
+
+ $this->processTags($doc,$meta);
+ }
+
+ protected function processDescription($text)
+ {
+ if(($text=trim($text))==='')
+ return '';
+ $text=preg_replace_callback('/\{@include\s+([^\s\}]+)\s*\}/s',array($this,'processInclude'),$text);
+ $text=preg_replace('/^(\r| |\t)*$/m',"<br/><br/>",$text);
+ $text=preg_replace_callback('/<pre>(.*?)<\/pre>/is',array($this,'processCode'),$text);
+ $text=preg_replace_callback('/\{@link\s+([^\s\}]+)(.*?)\}/s',array($this,'processLink'),$text);
+ return $text;
+ }
+
+ protected function processCode($matches)
+ {
+ return preg_replace('/<br\/><br\/>/','',$matches[0]);
+ }
+
+ protected function resolveInternalUrl($url)
+ {
+ $url=rtrim($url,'()');
+ if(($pos=strpos($url,'::'))!==false)
+ {
+ $class=substr($url,0,$pos);
+ $method=substr($url,$pos+2);
+ }
+ else if(isset($this->classes[$url]))
+ return $url;
+ else
+ {
+ $class=$this->_currentClass;
+ $method=$url;
+ }
+ return $this->getMethodUrl($class,$method);
+ }
+
+ protected function getMethodUrl($class,$method)
+ {
+ if(!isset($this->classes[$class]))
+ return '';
+ if(method_exists($class,$method) || property_exists($class,$method))
+ return $class.'::'.$method;
+ if(method_exists($class,'get'.$method) || method_exists($class,'set'.$method))
+ return $class.'::'.$method;
+ if(($parent=get_parent_class($class))!==false)
+ return $this->getMethodUrl($parent,$method);
+ else
+ return '';
+ }
+
+ protected function processLink($matches)
+ {
+ $url=$matches[1];
+ if(($text=trim($matches[2]))==='')
+ $text=$url;
+
+ if(preg_match('/^(http|ftp):\/\//i',$url)) // an external URL
+ return "<a href=\"$url\">$text</a>";
+ $url=$this->resolveInternalUrl($url);
+ return $url===''?$text:'{{'.$url.'|'.$text.'}}';
+ }
+
+ protected function processInclude($matches)
+ {
+ $class=new ReflectionClass($this->_currentClass);
+ $fileName=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$matches[1];
+ if(is_file($fileName))
+ return file_get_contents($fileName);
+ else
+ return $matches[0];
+ }
+
+ protected function processTags($object,$comment)
+ {
+ $tags=preg_split('/^\s*@/m',$comment,-1,PREG_SPLIT_NO_EMPTY);
+ foreach($tags as $tag)
+ {
+ $segs=preg_split('/\s+/',trim($tag),2);
+ $tagName=$segs[0];
+ $param=isset($segs[1])?trim($segs[1]):'';
+ $tagMethod='tag'.ucfirst($tagName);
+ if(method_exists($this,$tagMethod))
+ $this->$tagMethod($object,$param);
+ else if(property_exists($object,$tagName))
+ $object->$tagName=$param;
+ }
+ }
+
+ protected function processMethods($class)
+ {
+ $methods=array();
+ foreach($class->getMethods() as $method)
+ {
+ if($method->isPublic() || $method->isProtected())
+ {
+ $doc=$this->processMethod($class,$method);
+ $methods[$doc->name]=$doc;
+ }
+ }
+ ksort($methods);
+ return $methods;
+ }
+
+ protected function processMethod($class,$method)
+ {
+ $doc=new MethodDoc;
+ $doc->name=$method->getName();
+ $doc->definedBy=$method->getDeclaringClass()->getName();
+ $doc->isAbstract=$method->isAbstract();
+ $doc->isFinal=$method->isFinal();
+ $doc->isProtected=$method->isProtected();
+ $doc->isStatic=$method->isStatic();
+ $doc->isInherited=$doc->definedBy!==$class->getName();
+
+ $doc->input=array();
+ foreach($method->getParameters() as $param)
+ {
+ $p=new ParamDoc;
+ $p->name=$param->getName();
+ $p->isOptional=$param->isOptional();
+ if($param->isDefaultValueAvailable())
+ $p->defaultValue=$param->getDefaultValue();
+ $doc->input[]=$p;
+ }
+ reset($doc->input);
+
+ $this->processComment($doc,$method->getDocComment());
+
+ $params=array();
+ foreach($doc->input as $param)
+ {
+ $type=empty($param->type)?'':$this->getTypeUrl($param->type).' ';
+ if($param->isOptional)
+ $params[]=$type.'$'.$param->name.'='.var_export($param->defaultValue,true);
+ else
+ $params[]=$type.'$'.$param->name;
+ }
+ $doc->signature='{{'.$class->name.'::'.$doc->name.'|<b>'.$doc->name.'</b>}}('.implode(', ',$params).')';
+ if($doc->output!==null)
+ $doc->signature=$this->getTypeUrl($doc->output->type).' '.$doc->signature;
+ else
+ $doc->signature='void '.$doc->signature;
+ if(($modifier=implode(' ',Reflection::getModifierNames($method->getModifiers())))!=='')
+ $doc->signature=$modifier.' '.$doc->signature;
+
+ return $doc;
+ }
+
+ protected function getTypeUrl($type)
+ {
+ if(isset($this->classes[$type]) && $type!==$this->_currentClass)
+ return '{{'.$type.'|'.$type.'}}';
+ else
+ return $type;
+ }
+
+ protected function processProperties($class)
+ {
+ $properties=array();
+ foreach($class->getProperties() as $property)
+ {
+ if($property->isPublic() || $property->isProtected())
+ {
+ $p=$this->processProperty($class,$property);
+ $properties[$p->name]=$p;
+ }
+ }
+ return $properties;
+ }
+
+ protected function processProperty($class,$property)
+ {
+ $doc=new PropertyDoc;
+ $doc->name=$property->getName();
+ $doc->definedBy=$property->getDeclaringClass()->getName();
+ $doc->readOnly=false;
+ $doc->isStatic=$property->isStatic();
+ $doc->isProtected=$property->isProtected();
+ $doc->isInherited=$doc->definedBy!==$class->getName();
+
+ $this->processComment($doc,$property->getDocComment());
+
+ $doc->signature='<b>$'.$doc->name.'</b>;';
+ if($doc->type!==null)
+ $doc->signature=$this->getTypeUrl($doc->type) . ' ' . $doc->signature;
+ if(($modifier=implode(' ',Reflection::getModifierNames($property->getModifiers())))!=='')
+ $doc->signature=$modifier.' '.$doc->signature;
+
+ return $doc;
+ }
+
+ protected function processComponentProperties($class)
+ {
+ $properties=array();
+ foreach($class->getMethods() as $method)
+ {
+ if($this->isPropertyMethod($method) && ($method->isPublic() || $method->isProtected()))
+ {
+ $p=$this->processComponentProperty($class,$method);
+ $properties[$p->name]=$p;
+ }
+ }
+ return $properties;
+ }
+
+ protected function processComponentProperty($class,$method)
+ {
+ $doc=new PropertyDoc;
+ $name=$method->getName();
+ $doc->name=strtolower($name[3]).substr($name,4);
+ $doc->isProtected=$method->isProtected();
+ $doc->isStatic=false;
+ $doc->readOnly=!$class->hasMethod('set'.substr($name,3));
+ $doc->definedBy=$method->getDeclaringClass()->getName();
+ $doc->isInherited=$doc->definedBy!==$class->getName();
+ $doc->getter=$this->processMethod($class,$method);
+ if(!$doc->readOnly)
+ $doc->setter=$this->processMethod($class,$class->getMethod('set'.substr($name,3)));
+
+ $this->processComment($doc,$method->getDocComment());
+
+ return $doc;
+ }
+
+ protected function processComponentEvents($class)
+ {
+ $events=array();
+ foreach($class->getMethods() as $method)
+ {
+ if($this->isEventMethod($method) && ($method->isPublic() || $method->isProtected()))
+ {
+ $e=$this->processComponentEvent($class,$method);
+ $events[$e->name]=$e;
+ }
+ }
+ return $events;
+ }
+
+ protected function processComponentEvent($class,$method)
+ {
+ $doc=new EventDoc;
+ $doc->name=$method->getName();
+ $doc->definedBy=$method->getDeclaringClass()->getName();
+ $doc->isInherited=$doc->definedBy!==$class->getName();
+ $doc->trigger=$this->processMethod($class,$method);
+
+ $this->processComment($doc,$method->getDocComment());
+
+ return $doc;
+ }
+
+ protected function tagParam($object,$comment)
+ {
+ if($object instanceof FunctionDoc)
+ {
+ $param=current($object->input);
+ if($param!==false)
+ {
+ $segs=preg_split('/\s+/',$comment,2);
+ $param->type=$segs[0];
+ if(preg_match('/\[\s*\]/',$param->type))
+ $param->type='array';
+ if(isset($segs[1]))
+ $param->description=$this->processDescription($segs[1]);
+ next($object->input);
+ }
+ }
+ }
+
+ protected function tagReturn($object,$comment)
+ {
+ $segs=preg_split('/\s+/',$comment,2);
+ if($object instanceof FunctionDoc)
+ {
+ $object->output=new ParamDoc;
+ $object->output->type=$segs[0];
+ if(isset($segs[1]))
+ $object->output->description=$this->processDescription($segs[1]);
+ }
+ else if($object instanceof PropertyDoc)