PageRenderTime 122ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/protected/test.txt

http://github.com/phpnode/YiiJS
Plain Text | 13930 lines | 13545 code | 385 blank | 0 comment | 0 complexity | 29c971761f8a835f00acf162c4fa918b MD5 | raw file
  1. /*global php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2. /**
  3. * Yii is a helper class serving common framework functionalities.
  4. *
  5. * It encapsulates {@link YiiBase} which provides the actual implementation.
  6. * By writing your own Yii class, you can customize some functionalities of YiiBase.
  7. *
  8. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9. * @version $Id: yii.js 2799 2011-01-01 19:31:13Z qiang.xue $
  10. * @package system
  11. * @since 1.0
  12. * @author Charles Pick
  13. * @class
  14. * @extends Yii.YiiBase
  15. */
  16. var YII_DEBUG = true, YII_TRACE_LEVEL = 3, YII_BEGIN_TIME = new Date().getTime() / 1000, Yii = /** @lends Yii.prototype */{
  17. /**
  18. * @property {Array} class map used by the Yii autoloading mechanism.
  19. * The array keys are the class names and the array values are the corresponding class file paths.
  20. * @since 1.1.5
  21. */
  22. classMap: {},
  23. _aliases: {},
  24. _imports: {},
  25. _includePaths: {},
  26. _app: null,
  27. _logger: null,
  28. /**
  29. * @property {Array} class map for core Yii classes.
  30. * NOTE, DO NOT MODIFY THIS ARRAY MANUALLY. IF YOU CHANGE OR ADD SOME CORE CLASSES,
  31. * PLEASE RUN 'build autoload' COMMAND TO UPDATE THIS ARRAY.
  32. */
  33. _coreClasses: {'CApplication':'/base/CApplication.js','CApplicationComponent':'/base/CApplicationComponent.js','CBehavior':'/base/CBehavior.js','CComponent':'/base/CComponent.js','CErrorEvent':'/base/CErrorEvent.js','CErrorHandler':'/base/CErrorHandler.js','CException':'/base/CException.js','CExceptionEvent':'/base/CExceptionEvent.js','CHttpException':'/base/CHttpException.js','CModel':'/base/CModel.js','CModelBehavior':'/base/CModelBehavior.js','CModelEvent':'/base/CModelEvent.js','CModule':'/base/CModule.js','CSecurityManager':'/base/CSecurityManager.js','CStatePersister':'/base/CStatePersister.js','CApcCache':'/caching/CApcCache.js','CCache':'/caching/CCache.js','CDbCache':'/caching/CDbCache.js','CDummyCache':'/caching/CDummyCache.js','CEAcceleratorCache':'/caching/CEAcceleratorCache.js','CFileCache':'/caching/CFileCache.js','CMemCache':'/caching/CMemCache.js','CWinCache':'/caching/CWinCache.js','CXCache':'/caching/CXCache.js','CZendDataCache':'/caching/CZendDataCache.js','CCacheDependency':'/caching/dependencies/CCacheDependency.js','CChainedCacheDependency':'/caching/dependencies/CChainedCacheDependency.js','CDbCacheDependency':'/caching/dependencies/CDbCacheDependency.js','CDirectoryCacheDependency':'/caching/dependencies/CDirectoryCacheDependency.js','CExpressionDependency':'/caching/dependencies/CExpressionDependency.js','CFileCacheDependency':'/caching/dependencies/CFileCacheDependency.js','CGlobalStateCacheDependency':'/caching/dependencies/CGlobalStateCacheDependency.js','CAttributeCollection':'/collections/CAttributeCollection.js','CConfiguration':'/collections/CConfiguration.js','CList':'/collections/CList.js','CListIterator':'/collections/CListIterator.js','CMap':'/collections/CMap.js','CMapIterator':'/collections/CMapIterator.js','CQueue':'/collections/CQueue.js','CQueueIterator':'/collections/CQueueIterator.js','CStack':'/collections/CStack.js','CStackIterator':'/collections/CStackIterator.js','CTypedList':'/collections/CTypedList.js','CTypedMap':'/collections/CTypedMap.js','CConsoleApplication':'/console/CConsoleApplication.js','CConsoleCommand':'/console/CConsoleCommand.js','CConsoleCommandRunner':'/console/CConsoleCommandRunner.js','CHelpCommand':'/console/CHelpCommand.js','CDbCommand':'/db/CDbCommand.js','CDbConnection':'/db/CDbConnection.js','CDbDataReader':'/db/CDbDataReader.js','CDbException':'/db/CDbException.js','CDbMigration':'/db/CDbMigration.js','CDbTransaction':'/db/CDbTransaction.js','CActiveFinder':'/db/ar/CActiveFinder.js','CActiveRecord':'/db/ar/CActiveRecord.js','CActiveRecordBehavior':'/db/ar/CActiveRecordBehavior.js','CDbColumnSchema':'/db/schema/CDbColumnSchema.js','CDbCommandBuilder':'/db/schema/CDbCommandBuilder.js','CDbCriteria':'/db/schema/CDbCriteria.js','CDbExpression':'/db/schema/CDbExpression.js','CDbSchema':'/db/schema/CDbSchema.js','CDbTableSchema':'/db/schema/CDbTableSchema.js','CMssqlColumnSchema':'/db/schema/mssql/CMssqlColumnSchema.js','CMssqlCommandBuilder':'/db/schema/mssql/CMssqlCommandBuilder.js','CMssqlPdoAdapter':'/db/schema/mssql/CMssqlPdoAdapter.js','CMssqlSchema':'/db/schema/mssql/CMssqlSchema.js','CMssqlTableSchema':'/db/schema/mssql/CMssqlTableSchema.js','CMysqlColumnSchema':'/db/schema/mysql/CMysqlColumnSchema.js','CMysqlSchema':'/db/schema/mysql/CMysqlSchema.js','CMysqlTableSchema':'/db/schema/mysql/CMysqlTableSchema.js','COciColumnSchema':'/db/schema/oci/COciColumnSchema.js','COciCommandBuilder':'/db/schema/oci/COciCommandBuilder.js','COciSchema':'/db/schema/oci/COciSchema.js','COciTableSchema':'/db/schema/oci/COciTableSchema.js','CPgsqlColumnSchema':'/db/schema/pgsql/CPgsqlColumnSchema.js','CPgsqlSchema':'/db/schema/pgsql/CPgsqlSchema.js','CPgsqlTableSchema':'/db/schema/pgsql/CPgsqlTableSchema.js','CSqliteColumnSchema':'/db/schema/sqlite/CSqliteColumnSchema.js','CSqliteCommandBuilder':'/db/schema/sqlite/CSqliteCommandBuilder.js','CSqliteSchema':'/db/schema/sqlite/CSqliteSchema.js','CChoiceFormat':'/i18n/CChoiceFormat.js','CDateFormatter':'/i18n/CDateFormatter.js','CDbMessageSource':'/i18n/CDbMessageSource.js','CGettextMessageSource':'/i18n/CGettextMessageSource.js','CLocale':'/i18n/CLocale.js','CMessageSource':'/i18n/CMessageSource.js','CNumberFormatter':'/i18n/CNumberFormatter.js','CPhpMessageSource':'/i18n/CPhpMessageSource.js','CGettextFile':'/i18n/gettext/CGettextFile.js','CGettextMoFile':'/i18n/gettext/CGettextMoFile.js','CGettextPoFile':'/i18n/gettext/CGettextPoFile.js','CDbLogRoute':'/logging/CDbLogRoute.js','CEmailLogRoute':'/logging/CEmailLogRoute.js','CFileLogRoute':'/logging/CFileLogRoute.js','CLogFilter':'/logging/CLogFilter.js','CLogRoute':'/logging/CLogRoute.js','CLogRouter':'/logging/CLogRouter.js','CLogger':'/logging/CLogger.js','CProfileLogRoute':'/logging/CProfileLogRoute.js','CWebLogRoute':'/logging/CWebLogRoute.js','CDateTimeParser':'/utils/CDateTimeParser.js','CFileHelper':'/utils/CFileHelper.js','CFormatter':'/utils/CFormatter.js','CMarkdownParser':'/utils/CMarkdownParser.js','CPropertyValue':'/utils/CPropertyValue.js','CTimestamp':'/utils/CTimestamp.js','CVarDumper':'/utils/CVarDumper.js','CBooleanValidator':'/validators/CBooleanValidator.js','CCaptchaValidator':'/validators/CCaptchaValidator.js','CCompareValidator':'/validators/CCompareValidator.js','CDateValidator':'/validators/CDateValidator.js','CDefaultValueValidator':'/validators/CDefaultValueValidator.js','CEmailValidator':'/validators/CEmailValidator.js','CExistValidator':'/validators/CExistValidator.js','CFileValidator':'/validators/CFileValidator.js','CFilterValidator':'/validators/CFilterValidator.js','CInlineValidator':'/validators/CInlineValidator.js','CNumberValidator':'/validators/CNumberValidator.js','CRangeValidator':'/validators/CRangeValidator.js','CRegularExpressionValidator':'/validators/CRegularExpressionValidator.js','CRequiredValidator':'/validators/CRequiredValidator.js','CSafeValidator':'/validators/CSafeValidator.js','CStringValidator':'/validators/CStringValidator.js','CTypeValidator':'/validators/CTypeValidator.js','CUniqueValidator':'/validators/CUniqueValidator.js','CUnsafeValidator':'/validators/CUnsafeValidator.js','CUrlValidator':'/validators/CUrlValidator.js','CValidator':'/validators/CValidator.js','CActiveDataProvider':'/web/CActiveDataProvider.js','CArrayDataProvider':'/web/CArrayDataProvider.js','CAssetManager':'/web/CAssetManager.js','CBaseController':'/web/CBaseController.js','CCacheHttpSession':'/web/CCacheHttpSession.js','CClientScript':'/web/CClientScript.js','CController':'/web/CController.js','CDataProvider':'/web/CDataProvider.js','CDbHttpSession':'/web/CDbHttpSession.js','CExtController':'/web/CExtController.js','CFormModel':'/web/CFormModel.js','CHttpCookie':'/web/CHttpCookie.js','CHttpRequest':'/web/CHttpRequest.js','CHttpSession':'/web/CHttpSession.js','CHttpSessionIterator':'/web/CHttpSessionIterator.js','COutputEvent':'/web/COutputEvent.js','CPagination':'/web/CPagination.js','CSort':'/web/CSort.js','CSqlDataProvider':'/web/CSqlDataProvider.js','CTheme':'/web/CTheme.js','CThemeManager':'/web/CThemeManager.js','CUploadedFile':'/web/CUploadedFile.js','CUrlManager':'/web/CUrlManager.js','CWebApplication':'/web/CWebApplication.js','CWebModule':'/web/CWebModule.js','CWidgetFactory':'/web/CWidgetFactory.js','CAction':'/web/actions/CAction.js','CInlineAction':'/web/actions/CInlineAction.js','CViewAction':'/web/actions/CViewAction.js','CAccessControlFilter':'/web/auth/CAccessControlFilter.js','CAuthAssignment':'/web/auth/CAuthAssignment.js','CAuthItem':'/web/auth/CAuthItem.js','CAuthManager':'/web/auth/CAuthManager.js','CBaseUserIdentity':'/web/auth/CBaseUserIdentity.js','CDbAuthManager':'/web/auth/CDbAuthManager.js','CPhpAuthManager':'/web/auth/CPhpAuthManager.js','CUserIdentity':'/web/auth/CUserIdentity.js','CWebUser':'/web/auth/CWebUser.js','CFilter':'/web/filters/CFilter.js','CFilterChain':'/web/filters/CFilterChain.js','CInlineFilter':'/web/filters/CInlineFilter.js','CForm':'/web/form/CForm.js','CFormButtonElement':'/web/form/CFormButtonElement.js','CFormElement':'/web/form/CFormElement.js','CFormElementCollection':'/web/form/CFormElementCollection.js','CFormInputElement':'/web/form/CFormInputElement.js','CFormStringElement':'/web/form/CFormStringElement.js','CGoogleApi':'/web/helpers/CGoogleApi.js','CHtml':'/web/helpers/CHtml.js','CJSON':'/web/helpers/CJSON.js','CJavaScript':'/web/helpers/CJavaScript.js','CPradoViewRenderer':'/web/renderers/CPradoViewRenderer.js','CViewRenderer':'/web/renderers/CViewRenderer.js','CWebService':'/web/services/CWebService.js','CWebServiceAction':'/web/services/CWebServiceAction.js','CWsdlGenerator':'/web/services/CWsdlGenerator.js','CActiveForm':'/web/widgets/CActiveForm.js','CAutoComplete':'/web/widgets/CAutoComplete.js','CClipWidget':'/web/widgets/CClipWidget.js','CContentDecorator':'/web/widgets/CContentDecorator.js','CFilterWidget':'/web/widgets/CFilterWidget.js','CFlexWidget':'/web/widgets/CFlexWidget.js','CHtmlPurifier':'/web/widgets/CHtmlPurifier.js','CInputWidget':'/web/widgets/CInputWidget.js','CMarkdown':'/web/widgets/CMarkdown.js','CMaskedTextField':'/web/widgets/CMaskedTextField.js','CMultiFileUpload':'/web/widgets/CMultiFileUpload.js','COutputCache':'/web/widgets/COutputCache.js','COutputProcessor':'/web/widgets/COutputProcessor.js','CStarRating':'/web/widgets/CStarRating.js','CTabView':'/web/widgets/CTabView.js','CTextHighlighter':'/web/widgets/CTextHighlighter.js','CTreeView':'/web/widgets/CTreeView.js','CWidget':'/web/widgets/CWidget.js','CCaptcha':'/web/widgets/captcha/CCaptcha.js','CCaptchaAction':'/web/widgets/captcha/CCaptchaAction.js','CBasePager':'/web/widgets/pagers/CBasePager.js','CLinkPager':'/web/widgets/pagers/CLinkPager.js','CListPager':'/web/widgets/pagers/CListPager.js'},
  34. /**
  35. * Augments a class with properties from another class
  36. * @param {Object} receivingClass The class that should be augmented
  37. * @param {Object} givingClass The class that donates the properties
  38. */
  39. augment: function (receivingClass, givingClass) {
  40. var methodName;
  41. for (methodName in givingClass.prototype) {
  42. if(!receivingClass.prototype[methodName]) {
  43. receivingClass.prototype[methodName] = givingClass.prototype[methodName];
  44. }
  45. }
  46. },
  47. /**
  48. * @returns {String} the version of Yii framework
  49. */
  50. getVersion: function () {
  51. return '1.1.8-dev';
  52. },
  53. /**
  54. * Creates a Web application instance.
  55. * @param {Mixed} config application configuration.
  56. * If a string, it is treated as the path of the file that contains the configuration;
  57. * If an array, it is the actual configuration information.
  58. * Please make sure you specify the {@link CApplication::basePath basePath} property in the configuration,
  59. * which should point to the directory containing all application logic, template and data.
  60. * If not, the directory will be defaulted to 'protected'.
  61. */
  62. createWebApplication: function (config) {
  63. if (config === undefined) {
  64. config = null;
  65. }
  66. return Yii.createApplication('CWebApplication',config);
  67. },
  68. /**
  69. * Creates a console application instance.
  70. * @param {Mixed} config application configuration.
  71. * If a string, it is treated as the path of the file that contains the configuration;
  72. * If an array, it is the actual configuration information.
  73. * Please make sure you specify the {@link CApplication::basePath basePath} property in the configuration,
  74. * which should point to the directory containing all application logic, template and data.
  75. * If not, the directory will be defaulted to 'protected'.
  76. */
  77. createConsoleApplication: function (config) {
  78. if (config === undefined) {
  79. config = null;
  80. }
  81. return Yii.createApplication('CConsoleApplication',config);
  82. },
  83. /**
  84. * Creates an application of the specified class.
  85. * @param {String} classVar the application class name
  86. * @param {Mixed} config application configuration. This parameter will be passed as the parameter
  87. * to the constructor of the application class.
  88. * @returns {Mixed} the application instance
  89. * @since 1.0.10
  90. */
  91. createApplication: function (classVar, config) {
  92. if (config === undefined) {
  93. config = null;
  94. }
  95. return new Yii[classVar](config);
  96. },
  97. /**
  98. * Returns the application singleton, null if the singleton has not been created yet.
  99. * @returns {Yii.CApplication} the application singleton, null if the singleton has not been created yet.
  100. */
  101. app: function () {
  102. return Yii._app;
  103. },
  104. /**
  105. * Stores the application instance in the class static member.
  106. * This method helps implement a singleton pattern for CApplication.
  107. * Repeated invocation of this method or the CApplication constructor
  108. * will cause the throw of an exception.
  109. * To retrieve the application instance, use {@link app()}.
  110. * @param {Yii.CApplication} app the application instance. If this is null, the existing
  111. * application singleton will be removed.
  112. * @throws {Yii.CException} if multiple application instances are registered.
  113. */
  114. setApplication: function (app) {
  115. var _app;
  116. if(Yii._app===null || app===null) {
  117. Yii._app=app;
  118. }
  119. else {
  120. throw new Yii.CException(Yii.t('yii','Yii application can only be created once.'));
  121. }
  122. },
  123. /**
  124. * @returns {String} the path of the framework
  125. */
  126. getFrameworkPath: function () {
  127. return YII_PATH;
  128. },
  129. /**
  130. * Creates an object and initializes it based on the given configuration.
  131. *
  132. * The specified configuration can be either a string or an array.
  133. * If the former, the string is treated as the object type which can
  134. * be either the class name or {@link Yii::getPathOfAlias class path alias}.
  135. * If the latter, the 'class' element is treated as the object type,
  136. * and the rest name-value pairs in the array are used to initialize
  137. * the corresponding object properties.
  138. *
  139. * Any additional parameters passed to this method will be
  140. * passed to the constructor of the object being created.
  141. *
  142. * NOTE: the array-typed configuration has been supported since version 1.0.1.
  143. *
  144. * @param {Mixed} config the configuration. It can be either a string or an array.
  145. * @returns {Mixed} the created object
  146. * @throws {Yii.CException} if the configuration does not have a 'class' element.
  147. */
  148. createComponent: function (config) {
  149. var type, n, args, object, classVar, key, value;
  150. if(typeof(config) === 'string') {
  151. type=config;
  152. config=[];
  153. }
  154. else if(config['class'] !== undefined) {
  155. type=config['class'];
  156. delete config['class'];
  157. }
  158. else {
  159. throw new Yii.CException(Yii.t('yii','Object configuration must be an array containing a "class" element.'));
  160. }
  161. if(!Yii[type]) {
  162. type=Yii.imports(type,true);
  163. }
  164. if((n=arguments.length)>1) {
  165. args=arguments;
  166. if(n===2) {
  167. object=new Yii[type](args[1]);
  168. }
  169. else if(n===3) {
  170. object=new Yii[type](args[1],args[2]);
  171. }
  172. else if(n===4) {
  173. object=new Yii[type](args[1],args[2],args[3]);
  174. }
  175. else if(n===4) {
  176. object=new Yii[type](args[1],args[2],args[3]);
  177. }
  178. else if(n===5) {
  179. object=new Yii[type](args[1],args[2],args[3],args[4]);
  180. }
  181. }
  182. else {
  183. object=new Yii[type]();
  184. }
  185. for (key in config) {
  186. if (config.hasOwnProperty(key)) {
  187. value = config[key];
  188. object.set(key,value);
  189. }
  190. }
  191. return object;
  192. },
  193. /**
  194. * Imports a class or a directory.
  195. *
  196. * Importing a class is like including the corresponding class file.
  197. * The main difference is that importing a class is much lighter because it only
  198. * includes the class file when the class is referenced the first time.
  199. *
  200. * Importing a directory is equivalent to adding a directory into the PHP include path.
  201. * If multiple directories are imported, the directories imported later will take
  202. * precedence in class file searching (i.e., they are added to the front of the PHP include path).
  203. *
  204. * Path aliases are used to import a class or directory. For example,
  205. * <ul>
  206. * <li><code>application.components.GoogleMap</code>: import the <code>GoogleMap</code> class.</li>
  207. * <li><code>application.components.*</code>: import the <code>components</code> directory.</li>
  208. * </ul>
  209. *
  210. * The same path alias can be imported multiple times, but only the first time is effective.
  211. * Importing a directory does not import any of its subdirectories.
  212. *
  213. * Starting from version 1.1.5, this method can also be used to import a class in namespace format
  214. * (available for PHP 5.3 or above only). It is similar to importing a class in path alias format,
  215. * except that the dot separator is replaced by the backslash separator. For example, importing
  216. * <code>application\components\GoogleMap</code> is similar to importing <code>application.components.GoogleMap</code>.
  217. * The difference is that the former class is using qualified name, while the latter unqualified.
  218. *
  219. * Note, importing a class in namespace format requires that the namespace is corresponding to
  220. * a valid path alias if we replace the backslash characters with dot characters.
  221. * For example, the namespace <code>application\components</code> must correspond to a valid
  222. * path alias <code>application.components</code>.
  223. *
  224. * @param {String} alias path alias to be imported
  225. * @param {Boolean} forceInclude whether to include the class file immediately. If false, the class file
  226. * will be included only when the class is being used. This parameter is used only when
  227. * the path alias refers to a class.
  228. * @returns {String} the class name or the directory that this alias refers to
  229. * @throws {Yii.CException} if the alias is invalid
  230. */
  231. imports: function (alias, forceInclude) {
  232. var result, _imports, pos, namespace, path, classFile, classMap, className, isClass, _includePaths;
  233. if (forceInclude === undefined) {
  234. forceInclude = true;
  235. }
  236. if(Yii._imports[alias] !== undefined) { // previously imported
  237. return Yii._imports[alias];
  238. }
  239. if(Yii[alias] !== undefined) {
  240. return (Yii._imports[alias]=alias);
  241. }
  242. if ((pos = alias.indexOf("/")) !== -1) {
  243. className = String(alias.split("/").pop());
  244. if (className.slice(-3) == ".js") {
  245. className = className.slice(0,-3);
  246. }
  247. if (Yii[className] !== undefined) {
  248. return (Yii._imports[alias] = className);
  249. }
  250. Yii.include(alias,!forceInclude);
  251. Yii.classMap[className] = alias;
  252. Yii._imports[alias] = className;
  253. return className;
  254. }
  255. if((pos=alias.indexOf('.'))===-1) { // a simple class name
  256. result = Yii.autoload(alias, !forceInclude);
  257. if(forceInclude && !result) {
  258. throw new Yii.CException(Yii.t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',
  259. {'{alias}':alias}));
  260. }
  261. Yii._imports[alias]=alias;
  262. return alias;
  263. }
  264. className=String(alias.split(".").pop());
  265. isClass=className!=='*';
  266. if (!isClass) {
  267. throw new Yii.CException("YiiJS does not support importing directories");
  268. }
  269. if(Yii[className] !== undefined) {
  270. return (Yii._imports[alias]=className);
  271. }
  272. else if((path=Yii.getPathOfAlias(alias))!==false) {
  273. Yii.include(path + ".js",!forceInclude);
  274. Yii.classMap[className]=path+'.js';
  275. return className;
  276. }
  277. else {
  278. throw new Yii.CException(Yii.t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',
  279. {'{alias}':alias}));
  280. }
  281. },
  282. /**
  283. * Translates an alias into a file path.
  284. * Note, this method does not ensure the existence of the resulting file path.
  285. * It only checks if the root alias is valid or not.
  286. * @param {String} alias alias (e.g. system.web.CController)
  287. * @returns {Mixed} file path corresponding to the alias, false if the alias is invalid.
  288. */
  289. getPathOfAlias: function (alias) {
  290. var _aliases, pos, rootAlias, _app;
  291. if(Yii._aliases[alias] !== undefined) {
  292. return Yii._aliases[alias];
  293. }
  294. else if((pos=php.strpos(alias,'.'))!==false) {
  295. rootAlias=alias.slice(0, pos);
  296. if(Yii._aliases[rootAlias] !== undefined) {
  297. return (Yii._aliases[alias]=php.rtrim(Yii._aliases[rootAlias]+'/'+php.str_replace('.','/',alias.slice(pos+1)),'*'+'/'));
  298. }
  299. else if(Yii._app !== null && Yii._app instanceof Yii.CWebApplication){
  300. if(Yii._app.findModule(rootAlias)!==null) {
  301. return Yii.getPathOfAlias(alias);
  302. }
  303. }
  304. }
  305. return false;
  306. },
  307. /**
  308. * Create a path alias.
  309. * Note, this method neither checks the existence of the path nor normalizes the path.
  310. * @param {String} alias alias to the path
  311. * @param {String} path the path corresponding to the alias. If this is null, the corresponding
  312. * path alias will be removed.
  313. */
  314. setPathOfAlias: function (alias, path) {
  315. var _aliases;
  316. if(php.empty(path)) {
  317. delete Yii._aliases[alias];
  318. }
  319. else {
  320. Yii._aliases[alias]=php.rtrim(path,'\\/');
  321. }
  322. },
  323. /**
  324. * Class autoload loader.
  325. * @param {String} className class name
  326. * @param {Boolean} async Whether to load this class
  327. * via an asynchronous AJAX request, otherwise a blocking request is used, defaults to false.
  328. * @returns {Boolean} whether the class has been loaded successfully
  329. */
  330. autoload: function (className, async) {
  331. var _coreClasses, classMap, namespace, path, result;
  332. if (async === undefined) {
  333. async = true;
  334. }
  335. if(Yii._coreClasses[className] !== undefined) {
  336. if (Yii[className] !== undefined) {
  337. return true;
  338. }
  339. result = Yii.include(YII_PATH+Yii._coreClasses[className], async);
  340. if (!async) {
  341. return result;
  342. }
  343. }
  344. else if(Yii.classMap[className] !== undefined) {
  345. if (Yii[className] !== undefined) {
  346. return true;
  347. }
  348. result = Yii.include(Yii.classMap[className], async);
  349. if (!async) {
  350. return result;
  351. }
  352. }
  353. else {
  354. return Yii[className] !== undefined;
  355. }
  356. return true;
  357. },
  358. /**
  359. * Includes a remote file, this will be evaled!
  360. * @param {String} url The URL to load the file from
  361. * @param {Boolean} async Whether to perform an asynchronous request or not, defaults to true.
  362. * @param {Function} callback The callback to execute after the included file is evaled
  363. * @returns {Mixed} either the jQuery ajax request if this is async, or
  364. * if this is a blocking request returns the content or false depending on whether
  365. * it succeeded or not.
  366. */
  367. include: function (url, async, callback) {
  368. var options = {}, request;
  369. if (async === undefined) {
  370. async = true;
  371. }
  372. if (callback === undefined) {
  373. callback = function () {};
  374. }
  375. if(Yii._includePaths[url] !== undefined) { // previously imported
  376. return Yii._includePaths[url];
  377. }
  378. options.url = url;
  379. options.async = async;
  380. options.cache = false;
  381. if (async) {
  382. options.success = function (res) {
  383. Yii._includePaths[url] = eval(res);
  384. callback(Yii._includePaths[url]);
  385. };
  386. options.error = function () {
  387. throw new Yii.CHttpException(404, Yii.t("system", "No such file"));
  388. };
  389. return jQuery.ajax(options);
  390. }
  391. else {
  392. request = jQuery.ajax(options);
  393. if (request.status > 399) {
  394. return false;
  395. }
  396. Yii._includePaths[url] = eval(request.responseText);
  397. callback(Yii._includePaths[url]);
  398. return Yii._includePaths[url];
  399. }
  400. },
  401. /**
  402. * Writes a trace message.
  403. * This method will only log a message when the application is in debug mode.
  404. * @param {String} msg message to be logged
  405. * @param {String} category category of the message
  406. * @see log
  407. */
  408. trace: function (msg, category) {
  409. if (category === undefined) {
  410. category = 'application';
  411. }
  412. if(YII_DEBUG) {
  413. Yii.log(msg,Yii.CLogger.prototype.LEVEL_TRACE,category);
  414. }
  415. },
  416. /**
  417. * Logs a message.
  418. * Messages logged by this method may be retrieved via {@link CLogger::getLogs}
  419. * and may be recorded in different media, such as file, email, database, using
  420. * {@link CLogRouter}.
  421. * @param {String} msg message to be logged
  422. * @param {String} level level of the message (e.g. 'trace', 'warning', 'error'). It is case-insensitive.
  423. * @param {String} category category of the message (e.g. 'system.web'). It is case-insensitive.
  424. */
  425. log: function (msg, level, category) {
  426. var _logger, traces, count, i, limit, trace, cmd;
  427. if (level === undefined) {
  428. level = 'info';
  429. }
  430. if (category === undefined) {
  431. category = 'application';
  432. }
  433. if(Yii._logger===null) {
  434. Yii._logger=new Yii.CLogger();
  435. }
  436. if(window['console'] !== undefined && YII_DEBUG && YII_TRACE_LEVEL>0 && level!==Yii.CLogger.prototype.LEVEL_PROFILE) {
  437. cmd = "log";
  438. if (level === Yii.CLogger.prototype.LEVEL_ERROR) {
  439. cmd = "error";
  440. }
  441. else if (level === Yii.CLogger.prototype.LEVEL_WARNING) {
  442. cmd = "warn";
  443. }
  444. console[cmd](level + "\t" + php.str_pad(category,30," ") + "\t" + msg);
  445. }
  446. Yii._logger.log(msg,level,category);
  447. },
  448. /**
  449. * Marks the begin of a code block for profiling.
  450. * This has to be matched with a call to {@link endProfile()} with the same token.
  451. * The begin- and end- calls must also be properly nested, e.g.,
  452. * <pre>
  453. * Yii.beginProfile('block1');
  454. * Yii.beginProfile('block2');
  455. * Yii.endProfile('block2');
  456. * Yii.endProfile('block1');
  457. * </pre>
  458. * The following sequence is not valid:
  459. * <pre>
  460. * Yii.beginProfile('block1');
  461. * Yii.beginProfile('block2');
  462. * Yii.endProfile('block1');
  463. * Yii.endProfile('block2');
  464. * </pre>
  465. * @param {String} token token for the code block
  466. * @param {String} category the category of this log message
  467. * @see endProfile
  468. */
  469. beginProfile: function (token, category) {
  470. if (category === undefined) {
  471. category = 'application';
  472. }
  473. Yii.log('begin:'+token,Yii.CLogger.prototype.LEVEL_PROFILE,category);
  474. },
  475. /**
  476. * Marks the end of a code block for profiling.
  477. * This has to be matched with a previous call to {@link beginProfile()} with the same token.
  478. * @param {String} token token for the code block
  479. * @param {String} category the category of this log message
  480. * @see beginProfile
  481. */
  482. endProfile: function (token, category) {
  483. if (category === undefined) {
  484. category = 'application';
  485. }
  486. Yii.log('end:'+token,Yii.CLogger.prototype.LEVEL_PROFILE,category);
  487. },
  488. /**
  489. * @returns {Yii.CLogger} message logger
  490. */
  491. getLogger: function () {
  492. var _logger;
  493. if(Yii._logger!==null) {
  494. return Yii._logger;
  495. }
  496. else {
  497. return (Yii._logger=new Yii.CLogger);
  498. }
  499. },
  500. /**
  501. * Returns a string that can be displayed on your Web page showing Powered-by-Yii information
  502. * @returns {String} a string that can be displayed on your Web page showing Powered-by-Yii information
  503. */
  504. powered: function () {
  505. return 'Powered by <a href="http://www.yiiframework.com/" rel="external">Yii Framework</a>.';
  506. },
  507. /**
  508. * Translates a message to the specified language.
  509. * Starting from version 1.0.2, this method supports choice format (see {@link CChoiceFormat}),
  510. * i.e., the message returned will be chosen from a few candidates according to the given
  511. * number value. This feature is mainly used to solve plural format issue in case
  512. * a message has different plural forms in some languages.
  513. * @param {String} category message category. Please use only word letters. Note, category 'yii' is
  514. * reserved for Yii framework core code use. See {@link CPhpMessageSource} for
  515. * more interpretation about message category.
  516. * @param {String} message the original message
  517. * @param {Array} params parameters to be applied to the message using <code>strtr</code>.
  518. * Starting from version 1.0.2, the first parameter can be a number without key.
  519. * And in this case, the method will call {@link CChoiceFormat::format} to choose
  520. * an appropriate message translation.
  521. * Starting from version 1.1.6 you can pass parameter for {@link CChoiceFormat::format}
  522. * or plural forms format without wrapping it with array.
  523. * @param {String} source which message source application component to use.
  524. * Defaults to null, meaning using 'coreMessages' for messages belonging to
  525. * the 'yii' category and using 'messages' for the rest messages.
  526. * @param {String} language the target language. If null (default), the {@link CApplication::getLanguage application language} will be used.
  527. * This parameter has been available since version 1.0.3.
  528. * @returns {String} the translated message
  529. * @see CMessageSource
  530. */
  531. t: function (category, message, params, source, language) {
  532. var _app, chunks, expressions, n, i;
  533. if (params === undefined) {
  534. params = {};
  535. }
  536. if (source === undefined) {
  537. source = null;
  538. }
  539. if (language === undefined) {
  540. language = null;
  541. }
  542. if(Yii._app!==null) {
  543. if(source===null) {
  544. source=(category==='yii'||category==='zii')?'coreMessages':'messages';
  545. }
  546. if((source=Yii._app.getComponent(source))!==null && source !== undefined) {
  547. message=source.translate(category,message,language);
  548. }
  549. }
  550. if(params==={} || params === []) {
  551. return message;
  552. }
  553. if(params[0] !== undefined) {
  554. // number choice
  555. if(php.strpos(message,'|')!==false) {
  556. if(php.strpos(message,'#')===false) {
  557. chunks=message.split('|');
  558. expressions=Yii._app.getLocale(language).getPluralRules();
  559. n=php.min(php.count(chunks),php.count(expressions));
  560. if(n) {
  561. for(i=0;i<n;i++) {
  562. chunks[i]=expressions[i]+'#'+chunks[i];
  563. }
  564. message=chunks.join('|');
  565. }
  566. }
  567. message=Yii.CChoiceFormat.format(message,params[0]);
  568. }
  569. if(params['{n}'] === undefined) {
  570. params['{n}']=params[0];
  571. }
  572. delete params[0];
  573. }
  574. if (params !== {}) {
  575. return php.strtr(message,params);
  576. }
  577. return message;
  578. },
  579. /**
  580. * Registers a new class autoloader.
  581. * The new autoloader will be placed before {@link autoload} and after
  582. * any other existing autoloaders.
  583. * @param {Function} callback a valid PHP callback (function name or array($className,$methodName)).
  584. * @since 1.0.10
  585. */
  586. registerAutoloader: function (callback) {
  587. },
  588. /**
  589. * Removes JSDoc comments from a string
  590. * TODO: move this somewhere else
  591. * @param {String} str the string to strip
  592. * @returns {String} the stripped string
  593. */
  594. removeComments: function (str) {
  595. var uid = '_' + (new Date()),
  596. primatives = [],
  597. primIndex = 0;
  598. return (
  599. str
  600. .replace(/(['"])(\\\1|.)+?\1/g, function(match){
  601. primatives[primIndex] = match;
  602. return (uid + '') + primIndex++;
  603. })
  604. .replace(/([^\/])(\/(?!\*|\/)(\\\/|.)+?\/[gim]{0,3})/g, function(match, $1, $2){
  605. primatives[primIndex] = $2;
  606. return $1 + (uid + '') + primIndex++;
  607. })
  608. .replace(/\/\/.*?\/?\*.+?(?=\n|\r|$)|\/\*[\s\S]*?\/\/[\s\S]*?\*\//g, '')
  609. .replace(/\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g, '')
  610. .replace(RegExp('\\/\\*[\\s\\S]+' + uid + '\\d+', 'g'), '')
  611. .replace(RegExp(uid + '(\\d+)', 'g'), function(match, n){
  612. return primatives[n];
  613. })
  614. );
  615. },
  616. /**
  617. * Similar to PHP's preg_match_all
  618. * @param {RegExp} regex The regular expression to match against
  619. * @param {String} haystack The string to perform the regex on
  620. * @returns {Array} an array of matches
  621. */
  622. matchAll: function (regex, haystack) {
  623. var matches = [], i, match;
  624. match = regex.exec(haystack);
  625. while (match !== null) {
  626. matches.push(match);
  627. match = regex.exec(haystack);
  628. }
  629. return matches;
  630. },
  631. /**
  632. * Extends a class
  633. */
  634. extend: function (childClass, parentClass, properties) {
  635. childClass.prototype = new Yii[parentClass](false);
  636. childClass.prototype.constructor = childClass;
  637. if (properties !== undefined) {
  638. Yii.forEach(properties, function(name, value) {
  639. childClass.prototype[name] = value;
  640. });
  641. }
  642. },
  643. /**
  644. * Implements foreach in JavaScript
  645. * @param {Mixed} itemList a list of items to iterate through
  646. * @param {Function} callback The callback function, it will recieve 2 parameters, key and value
  647. * if the callback returns false, the loop will break.
  648. */
  649. forEach: function (itemList, callback) {
  650. var i, limit;
  651. if (typeof itemList === "function") {
  652. return Yii.forEach(itemList(), callback);
  653. }
  654. if (Object.prototype.toString.call(itemList) === '[object Array]' || itemList instanceof Yii.CList || itemList instanceof Yii.CStack) {
  655. limit = itemList.length;
  656. for (i = 0; i < limit; i++) {
  657. if (i === "forEach") {
  658. continue;
  659. }
  660. else if (callback(i, itemList[i]) === false) {
  661. break;
  662. }
  663. }
  664. }
  665. else {
  666. for (i in itemList) {
  667. if (itemList.hasOwnProperty(i)) {
  668. if (i === "forEach") {
  669. continue;
  670. }
  671. else if (callback(i, itemList[i]) === false) {
  672. break;
  673. }
  674. }
  675. }
  676. }
  677. return itemList;
  678. },
  679. /**
  680. * Filter an array of items
  681. */
  682. filter: function (items, block) {
  683. var values = [];
  684. var thisp = arguments[1];
  685. for (var i = 0; i < items.length; i++)
  686. if (block.call(thisp, items[i]))
  687. values.push(items[i]);
  688. return values;
  689. }
  690. };
  691. /**
  692. * A shortcut to application properties.
  693. * Supports virtual getters and setters, e.g:
  694. * <pre>
  695. * $app("securityManager.validationKey") === Yii.app().getSecurityManager().getValidationKey();
  696. * </pre>
  697. */
  698. var $app = function(selector, setVal) {
  699. var stack, parts, i, limit, item, getter, last;
  700. if (selector === undefined || php.trim(selector).length === 0) {
  701. return Yii.app();
  702. }
  703. parts = selector.split(".");
  704. limit = parts.length;
  705. last = limit - 1;
  706. stack = Yii.app();
  707. for (i = 0; i < limit; i++) {
  708. if (stack instanceof Yii.CComponent) {
  709. if (setVal !== undefined) {
  710. return stack.set(parts.join("."),setVal);
  711. }
  712. return stack.get(parts.join("."));
  713. }
  714. item = parts.shift();
  715. if (i === last && setVal !== undefined) {
  716. if (stack[item] !== undefined) {
  717. stack[item] = setVal;
  718. return setVal;
  719. }
  720. else if (stack.get !== undefined) {
  721. stack = stack.set.call(stack, item, setVal);
  722. return setVal;
  723. }
  724. else {
  725. throw new Yii.CException("No such property: " + item);
  726. }
  727. }
  728. else {
  729. if (stack[item] !== undefined) {
  730. stack = stack[item];
  731. }
  732. else if (stack.get !== undefined) {
  733. stack = stack.get.call(stack, item);
  734. }
  735. else {
  736. throw new Yii.CException("No such property: " + item);
  737. }
  738. }
  739. }
  740. return stack;
  741. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  742. /**
  743. * CComponent is the base class for all components.
  744. *
  745. * CComponent implements the protocol of defining, using properties and events.
  746. *
  747. * A property is defined by a getter method, and/or a setter method.
  748. * Properties can be accessed in the way like accessing normal object members.
  749. * Reading or writing a property will cause the invocation of the corresponding
  750. * getter or setter method, e.g
  751. * <pre>
  752. * a=component.text; // equivalent to $a=$component->getText();
  753. * component.text='abc'; // equivalent to $component->setText('abc');
  754. * </pre>
  755. * The signatures of getter and setter methods are as follows,
  756. * <pre>
  757. * // getter, defines a readable property 'text'
  758. * public function getText() { +++ }
  759. * // setter, defines a writable property 'text' with $value to be set to the property
  760. * public function setText(value) { +++ }
  761. * </pre>
  762. *
  763. * An event is defined by the presence of a method whose name starts with 'on'.
  764. * The event name is the method name. When an event is raised, functions
  765. * (called event handlers) attached to the event will be invoked automatically.
  766. *
  767. * An event can be raised by calling {@link raiseEvent} method, upon which
  768. * the attached event handlers will be invoked automatically in the order they
  769. * are attached to the event. Event handlers must have the following signature,
  770. * <pre>
  771. * function eventHandler(event) { +++ }
  772. * </pre>
  773. * where $event includes parameters associated with the event.
  774. *
  775. * To attach an event handler to an event, see {@link attachEventHandler}.
  776. * You can also use the following syntax:
  777. * <pre>
  778. * component.onClick=callback; // or $component->onClick->add($callback);
  779. * </pre>
  780. * where $callback refers to a valid PHP callback. Below we show some callback examples:
  781. * <pre>
  782. * 'handleOnClick' // handleOnClick() is a global function
  783. * [object,'handleOnClick'] // using $object->handleOnClick()
  784. * ['Page','handleOnClick'] // using Page::handleOnClick()
  785. * </pre>
  786. *
  787. * To raise an event, use {@link raiseEvent}. The on-method defining an event is
  788. * commonly written like the following:
  789. * <pre>
  790. * public function onClick(event)
  791. * {
  792. * this.raiseEvent('onClick',event);
  793. * }
  794. * </pre>
  795. * where <code>$event</code> is an instance of {@link CEvent} or its child class.
  796. * One can then raise the event by calling the on-method instead of {@link raiseEvent} directly.
  797. *
  798. * Both property names and event names are case-insensitive.
  799. *
  800. * Starting from version 1.0.2, CComponent supports behaviors. A behavior is an
  801. * instance of {@link IBehavior} which is attached to a component. The methods of
  802. * the behavior can be invoked as if they belong to the component. Multiple behaviors
  803. * can be attached to the same component.
  804. *
  805. * To attach a behavior to a component, call {@link attachBehavior}; and to detach the behavior
  806. * from the component, call {@link detachBehavior}.
  807. *
  808. * A behavior can be temporarily enabled or disabled by calling {@link enableBehavior}
  809. * or {@link disableBehavior}, respectively. When disabled, the behavior methods cannot
  810. * be invoked via the component.
  811. *
  812. * Starting from version 1.1.0, a behavior's properties (either its public member variables or
  813. * its properties defined via getters and/or setters) can be accessed through the component it
  814. * is attached to.
  815. *
  816. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  817. * @version $Id: CComponent.php 3066 2011-03-13 14:22:55Z qiang.xue $
  818. * @package system.base
  819. * @since 1.0
  820. * @author Charles Pick
  821. * @class
  822. */
  823. Yii.CComponent = function CComponent() {
  824. };
  825. Yii.CComponent.prototype._e = null;
  826. Yii.CComponent.prototype._m = null;
  827. /**
  828. * Gets the class name for this item.
  829. * Since JavaScript doesn't really support this we
  830. * abuse function declarations to implement it,
  831. * for example instead of:
  832. * <pre>
  833. * Yii.Blah = function() { ... }
  834. * </pre>
  835. * we use:
  836. * <pre>
  837. * Yii.Blah = function Blah() { ... }
  838. * </pre>
  839. * We can now retrieve the name of the class by inspecting the constructor.
  840. */
  841. Yii.CComponent.prototype.getClassName = function() {
  842. var matches, className;
  843. matches = /function(.*)\((.*)\)/.exec((this).constructor);
  844. if (matches) {
  845. return php.trim(matches[1]);
  846. }
  847. };
  848. /**
  849. * Returns a property value, an event handler list or a behavior based on its name.
  850. * Do not call this method. This is a PHP magic method that we override
  851. * to allow using the following syntax to read a property or obtain event handlers:
  852. * <pre>
  853. * value=component.propertyName;
  854. * handlers=component.eventName;
  855. * </pre>
  856. * @param {String} name the property name or event name
  857. * @returns {Mixed} the property value, event handlers attached to the event, or the named behavior (since version 1.0.2)
  858. * @throws {Yii.CException} if the property or event is not defined
  859. * @see __set
  860. */
  861. Yii.CComponent.prototype.get = function (name) {
  862. var getter, i, object, nameParts = [], limit;
  863. if (name.indexOf !== undefined && name.indexOf(".") !== -1) {
  864. nameParts = name.split(".");
  865. name = nameParts.shift();
  866. }
  867. if (this[name] !== undefined) {
  868. object = this[name];
  869. if (nameParts.length > 0) {
  870. if (object instanceof Yii.CComponent) {
  871. return object.get(nameParts.join("."));
  872. }
  873. limit = nameParts.length;
  874. for (i = 0; i < limit; i++) {
  875. name = nameParts.shift();
  876. object = object[name];
  877. if (nameParts.length === 0) {
  878. return object;
  879. }
  880. if (object instanceof Yii.CComponent) {
  881. return object.get(nameParts.join("."));
  882. }
  883. }
  884. }
  885. return object;
  886. }
  887. getter='get'+php.ucfirst(name);
  888. if(php.method_exists(this,getter)) {
  889. object = this[getter]();
  890. if (nameParts.length > 0) {
  891. if (object instanceof Yii.CComponent) {
  892. return object.get(nameParts.join("."));
  893. }
  894. limit = nameParts.length;
  895. for (i = 0; i < limit; i++) {
  896. name = nameParts.shift();
  897. object = object[name];
  898. if (nameParts.length === 0) {
  899. return object;
  900. }
  901. if (object instanceof Yii.CComponent) {
  902. return object.get(nameParts.join("."));
  903. }
  904. }
  905. }
  906. return object;
  907. }
  908. else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name)) {
  909. // duplicating getEventHandlers() here for performance
  910. name=name.toLowerCase();
  911. if(this._e[name] === undefined) {
  912. this._e[name]=new Yii.CList();
  913. }
  914. return this._e[name];
  915. }
  916. else if(this._m !== null && this._m[name] !== undefined) {
  917. return this._m[name];
  918. }
  919. else if(this._m !== null) {
  920. for (i in this._m) {
  921. if (this._m.hasOwnProperty(i)) {
  922. object = this._m[i];
  923. try {
  924. if(object.getEnabled() && (php.property_exists(object,name) || object.canGetProperty(name))) {
  925. if (nameParts.length > 0) {
  926. return object.get(nameParts.join("."));
  927. }
  928. return object.get(name);
  929. }
  930. }
  931. catch (e) {
  932. console.log(e);
  933. }
  934. }
  935. }
  936. }
  937. console.log(this.getClassName() + " : " + name);
  938. throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is not defined.',
  939. {'{class}':this.getClassName(), '{property}':name}));
  940. };
  941. /**
  942. * Sets value of a component property.
  943. * Do not call this method. This is a PHP magic method that we override
  944. * to allow using the following syntax to set a property or attach an event handler
  945. * <pre>
  946. * this.propertyName=value;
  947. * this.eventName=callback;
  948. * </pre>
  949. * @param {String} name the property name or the event name
  950. * @param {Mixed} value the property value or callback
  951. * @throws {Yii.CException} if the property/event is not defined or the property is read only.
  952. * @see __get
  953. */
  954. Yii.CComponent.prototype.set = function (name, value) {
  955. var setter, i, object, nameParts = [];
  956. if (name.indexOf(".") !== -1) {
  957. nameParts = name.split(".");
  958. name = nameParts.pop();
  959. return (this.get(nameParts.join("."))[name] = value);
  960. }
  961. if (this[name] !== undefined) {
  962. return (this[name] = value);
  963. }
  964. setter='set'+php.ucfirst(name);
  965. if(php.method_exists(this,setter)) {
  966. return this[setter](value);
  967. }
  968. else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name)) {
  969. // duplicating getEventHandlers() here for performance
  970. name=name.toLowerCase();
  971. if(this._e[name] === undefined) {
  972. this._e[name]=new Yii.CList();
  973. }
  974. return this._e[name].add(value);
  975. }
  976. else if(this._m !== null) {
  977. for (i in this._m) {
  978. if (this._m.hasOwnProperty(i)) {
  979. object = this._m[i];
  980. if(object.getEnabled() && (php.property_exists(object,name) || object.canSetProperty(name))) {
  981. return (object.set(name,value));
  982. }
  983. }
  984. }
  985. }
  986. if(php.method_exists(this,'get'+php.ucfirst(name))) {
  987. throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is read only.',
  988. {'{class}':this.getClassName(), '{property}':name}));
  989. }
  990. else {
  991. throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is not defined.',
  992. {'{class}':this.getClassName(), '{property}':name}));
  993. }
  994. };
  995. /**
  996. * Checks if a property value is null.
  997. * Do not call this method. This is a PHP magic method that we override
  998. * to allow using isset() to detect if a component property is set or not.
  999. * @param {String} name the property name or the event name
  1000. * @since 1.0.1
  1001. */
  1002. Yii.CComponent.prototype.isset = function (name) {
  1003. var getter, i, object, nameParts = [], value;
  1004. if (name.indexOf(".") !== -1) {
  1005. nameParts = name.split(".");
  1006. name = nameParts.pop();
  1007. try {
  1008. value = this.get(nameParts.join("."))[name];
  1009. if (value !== undefined && value !== null) {
  1010. return true;
  1011. }
  1012. return false;
  1013. }
  1014. catch (e) {
  1015. return false;
  1016. }
  1017. }
  1018. if (this[name] !== undefined) {
  1019. return true;
  1020. }
  1021. getter='get'+php.ucfirst(name);
  1022. if(php.method_exists(this,getter)) {
  1023. return (this[getter]()!==null);
  1024. }
  1025. else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name))
  1026. {
  1027. name=name.toLowerCase();
  1028. return this._e !== null && this._e[name] !== undefined && this._e[name].getCount();
  1029. }
  1030. else if(this._m !== null) {
  1031. if(this._m[name] !== undefined) {
  1032. return true;
  1033. }
  1034. for (i in this._m) {
  1035. if (this._m.hasOwnProperty(i)) {
  1036. object = this._m[i];
  1037. if(object.getEnabled() && (php.property_exists(object,name) || object.canGetProperty(name))) {
  1038. return true;
  1039. }
  1040. }
  1041. }
  1042. }
  1043. return false;
  1044. };
  1045. /**
  1046. * Sets a component property to be null.
  1047. * Do not call this method. This is a PHP magic method that we override
  1048. * to allow using unset() to set a component property to be null.
  1049. * @param {String} name the property name or the event name
  1050. * @throws {Yii.CException} if the property is read only.
  1051. * @since 1.0.1
  1052. */
  1053. Yii.CComponent.prototype.unset = function (name) {
  1054. var setter, i, object, nameParts = [];
  1055. if (name.indexOf(".") !== -1) {
  1056. nameParts = name.split(".");
  1057. name = nameParts.pop();
  1058. object = this.get(nameParts.join("."))[name];
  1059. if (object.unset !== undefined) {
  1060. return object.unset(name);
  1061. }
  1062. return (this.get(nameParts.join("."))[name] = null);
  1063. }
  1064. setter='set'+php.ucfirst(name);
  1065. if (this[name] !== undefined) {
  1066. this[name] = null;
  1067. return;
  1068. }
  1069. else if(php.method_exists(this,setter)) {
  1070. this[setter](null);
  1071. }
  1072. else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name)) {
  1073. delete this._e[name.toLowerCase()];
  1074. }
  1075. else if(this._m !== null)
  1076. {
  1077. if(this._m[name] !== undefined) {
  1078. this.detachBehavior(name);
  1079. }
  1080. else
  1081. {
  1082. for (i in this._m) {
  1083. if (this._m.hasOwnProperty(i)) {
  1084. object = this._m[i];
  1085. if(object.getEnabled()) {
  1086. if(php.property_exists(object,name)) {
  1087. return (object[name]=null);
  1088. }
  1089. else if(object.canSetProperty(name)) {
  1090. return object[setter](null);
  1091. }
  1092. }
  1093. }
  1094. }
  1095. }
  1096. }
  1097. else if(php.method_exists(this,'get'+name)) {
  1098. throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is read only.',
  1099. {'{class}':this.getClassName(), '{property}':name}));
  1100. }
  1101. };
  1102. /**
  1103. * Calls the named method which is not a class method.
  1104. * Do not call this method. This is a PHP magic method that we override
  1105. * to implement the behavior feature.
  1106. * @param {String} name the method name
  1107. * @param {Array} parameters method parameters
  1108. * @returns {Mixed} the method return value
  1109. * @since 1.0.2
  1110. */
  1111. Yii.CComponent.prototype.call = function (name, parameters) {
  1112. var i, object;
  1113. if (this[name] !== undefined) {
  1114. return php.call_user_func_array([this,name],parameters);
  1115. }
  1116. else if(this._m!==null) {
  1117. for (i in this._m) {
  1118. if (this._m.hasOwnProperty(i)) {
  1119. object = this._m[i];
  1120. if(object.getEnabled() && php.method_exists(object,name)) {
  1121. return php.call_user_func_array([object,name],parameters);
  1122. }
  1123. }
  1124. }
  1125. }
  1126. throw new Yii.CException(Yii.t('yii','{class} does not have a method named "{name}".',
  1127. {'{class}':this.getClassName(), '{name}':name}));
  1128. };
  1129. /**
  1130. * Returns the named behavior object.
  1131. * The name 'asa' stands for 'as a'.
  1132. * @param {String} behavior the behavior name
  1133. * @returns {IBehavior} the behavior object, or null if the behavior does not exist
  1134. * @since 1.0.2
  1135. */
  1136. Yii.CComponent.prototype.asa = function (behavior) {
  1137. return this._m !== null && this._m[behavior] !== undefined ? this._m[behavior] : null;
  1138. };
  1139. /**
  1140. * Attaches a list of behaviors to the component.
  1141. * Each behavior is indexed by its name and should be an instance of
  1142. * {@link IBehavior}, a string specifying the behavior class, or an
  1143. * array of the following structure:
  1144. * <pre>
  1145. * {
  1146. * 'class':'path.to.BehaviorClass',
  1147. * 'property1':'value1',
  1148. * 'property2':'value2',
  1149. * }
  1150. * </pre>
  1151. * @param {Array} behaviors list of behaviors to be attached to the component
  1152. * @since 1.0.2
  1153. */
  1154. Yii.CComponent.prototype.attachBehaviors = function (behaviors) {
  1155. var name, behavior;
  1156. for (name in behaviors) {
  1157. if (behaviors.hasOwnProperty(name)) {
  1158. behavior = behaviors[name];
  1159. this.attachBehavior(name,behavior);
  1160. }
  1161. }
  1162. };
  1163. /**
  1164. * Detaches all behaviors from the component.
  1165. * @since 1.0.2
  1166. */
  1167. Yii.CComponent.prototype.detachBehaviors = function () {
  1168. var name, behavior;
  1169. if(this._m!==null) {
  1170. for (name in this._m) {
  1171. if (this._m.hasOwnProperty(name)) {
  1172. behavior = this._m[name];
  1173. this.detachBehavior(name);
  1174. }
  1175. }
  1176. this._m=null;
  1177. }
  1178. };
  1179. /**
  1180. * Attaches a behavior to this component.
  1181. * This method will create the behavior object based on the given
  1182. * configuration. After that, the behavior object will be initialized
  1183. * by calling its {@link IBehavior::attach} method.
  1184. * @param {String} name the behavior's name. It should uniquely identify this behavior.
  1185. * @param {Mixed} behavior the behavior configuration. This is passed as the first
  1186. * parameter to {@link YiiBase::createComponent} to create the behavior object.
  1187. * @returns {IBehavior} the behavior object
  1188. * @since 1.0.2
  1189. */
  1190. Yii.CComponent.prototype.attachBehavior = function (name, behavior) {
  1191. if(!(behavior instanceof Yii.CBehavior)) {
  1192. behavior=Yii.createComponent(behavior);
  1193. }
  1194. behavior.setEnabled(true);
  1195. behavior.attach(this);
  1196. if (this._m === null) {
  1197. this._m = {};
  1198. }
  1199. return (this._m[name]=behavior);
  1200. };
  1201. /**
  1202. * Detaches a behavior from the component.
  1203. * The behavior's {@link IBehavior::detach} method will be invoked.
  1204. * @param {String} name the behavior's name. It uniquely identifies the behavior.
  1205. * @returns {IBehavior} the detached behavior. Null if the behavior does not exist.
  1206. * @since 1.0.2
  1207. */
  1208. Yii.CComponent.prototype.detachBehavior = function (name) {
  1209. var behavior;
  1210. if(this._m[name] !== undefined) {
  1211. this._m[name].detach(this);
  1212. behavior=this._m[name];
  1213. delete this._m[name];
  1214. return behavior;
  1215. }
  1216. };
  1217. /**
  1218. * Enables all behaviors attached to this component.
  1219. * @since 1.0.2
  1220. */
  1221. Yii.CComponent.prototype.enableBehaviors = function () {
  1222. var i, behavior;
  1223. if(this._m!==null) {
  1224. for (i in this._m) {
  1225. if (this._m.hasOwnProperty(i)) {
  1226. behavior = this._m[i];
  1227. behavior.setEnabled(true);
  1228. }
  1229. }
  1230. }
  1231. };
  1232. /**
  1233. * Disables all behaviors attached to this component.
  1234. * @since 1.0.2
  1235. */
  1236. Yii.CComponent.prototype.disableBehaviors = function () {
  1237. var i, behavior;
  1238. if(this._m!==null) {
  1239. for (i in this._m) {
  1240. if (this._m.hasOwnProperty(i)) {
  1241. behavior = this._m[i];
  1242. behavior.setEnabled(false);
  1243. }
  1244. }
  1245. }
  1246. };
  1247. /**
  1248. * Enables an attached behavior.
  1249. * A behavior is only effective when it is enabled.
  1250. * A behavior is enabled when first attached.
  1251. * @param {String} name the behavior's name. It uniquely identifies the behavior.
  1252. * @since 1.0.2
  1253. */
  1254. Yii.CComponent.prototype.enableBehavior = function (name) {
  1255. if(this._m !== null && this._m[name] !== undefined) {
  1256. this._m[name].setEnabled(true);
  1257. }
  1258. };
  1259. /**
  1260. * Disables an attached behavior.
  1261. * A behavior is only effective when it is enabled.
  1262. * @param {String} name the behavior's name. It uniquely identifies the behavior.
  1263. * @since 1.0.2
  1264. */
  1265. Yii.CComponent.prototype.disableBehavior = function (name) {
  1266. if(this._m !== null && this._m[name] !== undefined) {
  1267. this._m[name].setEnabled(false);
  1268. }
  1269. };
  1270. /**
  1271. * Determines whether a property is defined.
  1272. * A property is defined if there is a getter or setter method
  1273. * defined in the class. Note, property names are case-insensitive.
  1274. * @param {String} name the property name
  1275. * @returns {Boolean} whether the property is defined
  1276. * @see canGetProperty
  1277. * @see canSetProperty
  1278. */
  1279. Yii.CComponent.prototype.hasProperty = function (name) {
  1280. return this[name] !== undefined || php.method_exists(this,'get'+php.ucfirst(name)) || php.method_exists(this,'set'+php.ucfirst(name));
  1281. };
  1282. /**
  1283. * Determines whether a property can be read.
  1284. * A property can be read if the class has a getter method
  1285. * for the property name. Note, property name is case-insensitive.
  1286. * @param {String} name the property name
  1287. * @returns {Boolean} whether the property can be read
  1288. * @see canSetProperty
  1289. */
  1290. Yii.CComponent.prototype.canGetProperty = function (name) {
  1291. return this[name] !== undefined || php.method_exists(this,'get'+php.ucfirst(name));
  1292. };
  1293. /**
  1294. * Determines whether a property can be set.
  1295. * A property can be written if the class has a setter method
  1296. * for the property name. Note, property name is case-insensitive.
  1297. * @param {String} name the property name
  1298. * @returns {Boolean} whether the property can be written
  1299. * @see canGetProperty
  1300. */
  1301. Yii.CComponent.prototype.canSetProperty = function (name) {
  1302. return this[name] !== undefined || php.method_exists(this,'set'+php.ucfirst(name));
  1303. };
  1304. /**
  1305. * Determines whether an event is defined.
  1306. * An event is defined if the class has a method named like 'onXXX'.
  1307. * Note, event name is case-insensitive.
  1308. * @param {String} name the event name
  1309. * @returns {Boolean} whether an event is defined
  1310. */
  1311. Yii.CComponent.prototype.hasEvent = function (name) {
  1312. return !php.strncasecmp(name,'on',2) && php.method_exists(this,name);
  1313. };
  1314. /**
  1315. * Checks whether the named event has attached handlers.
  1316. * @param {String} name the event name
  1317. * @returns {Boolean} whether an event has been attached one or several handlers
  1318. */
  1319. Yii.CComponent.prototype.hasEventHandler = function (name) {
  1320. return this._e !== null && this._e[name] !== undefined && this._e[name].getCount()>0;
  1321. };
  1322. /**
  1323. * Returns the list of attached event handlers for an event.
  1324. * @param {String} name the event name
  1325. * @returns {Yii.CList} list of attached event handlers for the event
  1326. * @throws {Yii.CException} if the event is not defined
  1327. */
  1328. Yii.CComponent.prototype.getEventHandlers = function (name) {
  1329. if(this.hasEvent(name)) {
  1330. if (this._e === null) {
  1331. this._e = {};
  1332. }
  1333. if(this._e[name] === undefined) {
  1334. this._e[name]=new Yii.CList();
  1335. }
  1336. return this._e[name];
  1337. }
  1338. else {
  1339. throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is not defined.',
  1340. {'{class}':this.getClassName(), '{event}':name}));
  1341. }
  1342. };
  1343. /**
  1344. * Attaches an event handler to an event.
  1345. *
  1346. * An event handler must be a valid PHP callback, i.e., a string referring to
  1347. * a global function name, or an array containing two elements with
  1348. * the first element being an object and the second element a method name
  1349. * of the object.
  1350. *
  1351. * An event handler must be defined with the following signature,
  1352. * <pre>
  1353. * function handlerName(event) {}
  1354. * </pre>
  1355. * where $event includes parameters associated with the event.
  1356. *
  1357. * This is a convenient method of attaching a handler to an event.
  1358. * It is equivalent to the following code:
  1359. * <pre>
  1360. * component.getEventHandlers(eventName).add(eventHandler);
  1361. * </pre>
  1362. *
  1363. * Using {@link getEventHandlers}, one can also specify the excution order
  1364. * of multiple handlers attaching to the same event. For example:
  1365. * <pre>
  1366. * component.getEventHandlers(eventName).insertAt(0,eventHandler);
  1367. * </pre>
  1368. * makes the handler to be invoked first.
  1369. *
  1370. * @param {String} name the event name
  1371. * @param {Yii.Callback} handler the event handler
  1372. * @throws {Yii.CException} if the event is not defined
  1373. * @see detachEventHandler
  1374. */
  1375. Yii.CComponent.prototype.attachEventHandler = function (name, handler) {
  1376. this.getEventHandlers(name).add(handler);
  1377. };
  1378. /**
  1379. * Detaches an existing event handler.
  1380. * This method is the opposite of {@link attachEventHandler}.
  1381. * @param {String} name event name
  1382. * @param {Yii.Callback} handler the event handler to be removed
  1383. * @returns {Boolean} if the detachment process is successful
  1384. * @see attachEventHandler
  1385. */
  1386. Yii.CComponent.prototype.detachEventHandler = function (name, handler) {
  1387. if(this.hasEventHandler(name)) {
  1388. return this.getEventHandlers(name).remove(handler)!==false;
  1389. }
  1390. else {
  1391. return false;
  1392. }
  1393. };
  1394. /**
  1395. * Raises an event.
  1396. * This method represents the happening of an event. It invokes
  1397. * all attached handlers for the event.
  1398. * @param {String} name the event name
  1399. * @param {Yii.CEvent} event the event parameter
  1400. * @throws {Yii.CException} if the event is undefined or an event handler is invalid.
  1401. */
  1402. Yii.CComponent.prototype.raiseEvent = function (name, event) {
  1403. var i, handler, object, method, limit;
  1404. if(this._e !== null && this._e[name] !== undefined) {
  1405. limit = this._e[name].length;
  1406. for (i = 0; i < limit; i++) {
  1407. handler = this._e[name][i];
  1408. if(typeof(handler) === 'string') {
  1409. php.call_user_func(handler,event);
  1410. }
  1411. if(Object.prototype.toString.call(handler) === '[object Array]') {
  1412. // an array: 0 - object, 1 - method name
  1413. object = handler[0];
  1414. method = handler[1];
  1415. if(typeof(object) === 'string') { // static method call
  1416. php.call_user_func(handler,event);
  1417. }
  1418. else if(php.method_exists(object,method)) {
  1419. object[method](event);
  1420. }
  1421. else {
  1422. throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
  1423. {'{class}':this.getClassName(), '{event}':name, '{handler}':handler[1]}));
  1424. }
  1425. }
  1426. else if (typeof handler === "function") { // callback function
  1427. php.call_user_func(handler,event);
  1428. }
  1429. else {
  1430. console.log(i);
  1431. console.log(name);
  1432. console.log(handler);
  1433. throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
  1434. {'{class}':this.getClassName(), '{event}':name, '{handler}':handler}));
  1435. }
  1436. // stop further handling if param.handled is set true
  1437. if((event instanceof Yii.CEvent) && event.handled) {
  1438. return;
  1439. }
  1440. }
  1441. }
  1442. else if(YII_DEBUG && !this.hasEvent(name)) {
  1443. throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is not defined.',
  1444. {'{class}':this.getClassName(), '{event}':name}));
  1445. }
  1446. };
  1447. /**
  1448. * Evaluates a PHP expression or callback under the context of this component.
  1449. *
  1450. * Valid PHP callback can be class method name in the form of
  1451. * array(ClassName/Object, MethodName), or anonymous function (only available in PHP 5.3.0 or above).
  1452. *
  1453. * If a PHP callback is used, the corresponding function/method signature should be
  1454. * <pre>
  1455. * function foo(param1, param2, +++, component) { +++ }
  1456. * </pre>
  1457. * where the array elements in the second parameter to this method will be passed
  1458. * to the callback as $param1, $param2, ...; and the last parameter will be the component itself.
  1459. *
  1460. * If a PHP expression is used, the second parameter will be "extracted" into PHP variables
  1461. * that can be directly accessed in the expression. See {@link http://us.php.net/manual/en/function.extract.php PHP extract}
  1462. * for more details. In the expression, the component object can be accessed using $this.
  1463. *
  1464. * @param {Mixed} _expression_ a PHP expression or PHP callback to be evaluated.
  1465. * @param {Array} _data_ additional parameters to be passed to the above expression/callback.
  1466. * @returns {Mixed} the expression result
  1467. * @since 1.1.0
  1468. */
  1469. Yii.CComponent.prototype.evaluateExpression = function (_expression_, _data_) {
  1470. if (_data_ === undefined) {
  1471. _data_ = [];
  1472. }
  1473. if(typeof(_expression_) === 'string')
  1474. {
  1475. php.extract(_data_);
  1476. return eval('return '+_expression_+';');
  1477. }
  1478. else
  1479. {
  1480. _data_.push(this);
  1481. return php.call_user_func_array(_expression_, _data_);
  1482. }
  1483. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  1484. /**
  1485. * CApplicationComponent is the base class for application component classes.
  1486. *
  1487. * CApplicationComponent implements the basic methods required by {@link IApplicationComponent}.
  1488. *
  1489. * When developing an application component, try to put application component initialization code in
  1490. * the {@link init()} method instead of the constructor. This has the advantage that
  1491. * the application component can be customized through application configuration.
  1492. *
  1493. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  1494. * @version $Id: CApplicationComponent.php 2799 2011-01-01 19:31:13Z qiang.xue $
  1495. * @package system.base
  1496. * @since 1.0
  1497. * @author Charles Pick
  1498. * @class
  1499. * @extends Yii.CComponent
  1500. */
  1501. Yii.CApplicationComponent = function CApplicationComponent() {
  1502. };
  1503. Yii.CApplicationComponent.prototype = new Yii.CComponent();
  1504. Yii.CApplicationComponent.prototype.constructor = Yii.CApplicationComponent;
  1505. /**
  1506. * @var {Array} the behaviors that should be attached to this component.
  1507. * The behaviors will be attached to the component when {@link init} is called.
  1508. * Please refer to {@link CModel::behaviors} on how to specify the value of this property.
  1509. * @since 1.0.2
  1510. */
  1511. Yii.CApplicationComponent.prototype.behaviors = [];
  1512. Yii.CApplicationComponent.prototype._initialized = false;
  1513. /**
  1514. * Initializes the application component.
  1515. * This method is required by {@link IApplicationComponent} and is invoked by application.
  1516. * If you override this method, make sure to call the parent implementation
  1517. * so that the application component can be marked as initialized.
  1518. */
  1519. Yii.CApplicationComponent.prototype.init = function () {
  1520. this.attachBehaviors(this.behaviors);
  1521. this._initialized=true;
  1522. };
  1523. /**
  1524. * Checks if this application component bas been initialized.
  1525. * @returns {Boolean} whether this application component has been initialized (ie, {@link init()} is invoked).
  1526. */
  1527. Yii.CApplicationComponent.prototype.getIsInitialized = function () {
  1528. return this._initialized;
  1529. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  1530. /**
  1531. * CException represents a generic exception for all purposes.
  1532. *
  1533. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  1534. * @version $Id: CException.php 2799 2011-01-01 19:31:13Z qiang.xue $
  1535. * @package system.base
  1536. * @since 1.0
  1537. * @author Charles Pick
  1538. * @class
  1539. * @extends Yii.Exception
  1540. */
  1541. Yii.CException = function CException (message) {
  1542. if (message === false) {
  1543. return;
  1544. }
  1545. this.message = message;
  1546. };
  1547. Yii.CException.prototype = new Error();
  1548. Yii.CException.prototype.constructor = Yii.CException;
  1549. /**
  1550. * Gets a basic stack trace
  1551. * @returns {Array} An array of function calls
  1552. */
  1553. Yii.CException.prototype.stacktrace = function () {
  1554. function st2(f) {
  1555. return !f ? [] :
  1556. st2(f.caller).concat([f.toString().split('(')[0].substring(9) + '(' + Array.prototype.slice.call(f.arguments).join(',') + ')']);
  1557. }
  1558. return st2(arguments.callee.caller);
  1559. };
  1560. /**
  1561. * Gets the stack trace as a string
  1562. * @returns {String} the stack trace, latest item first
  1563. */
  1564. Yii.CException.prototype.getTraceAsString = function () {
  1565. return this.stacktrace().reverse().join("\n");
  1566. };
  1567. /**
  1568. * Gets the exception message
  1569. * @returns {String} the message associated with this error
  1570. */
  1571. Yii.CException.prototype.getMessage = function () {
  1572. return this.message;
  1573. }
  1574. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  1575. /**
  1576. * CEvent is the base class for all event classes.
  1577. *
  1578. * It encapsulates the parameters associated with an event.
  1579. * The {@link sender} property describes who raises the event.
  1580. * And the {@link handled} property indicates if the event is handled.
  1581. * If an event handler sets {@link handled} to true, those handlers
  1582. * that are not invoked yet will not be invoked anymore.
  1583. *
  1584. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  1585. * @version $Id: CComponent.php 3066 2011-03-13 14:22:55Z qiang.xue $
  1586. * @package system.base
  1587. * @since 1.0
  1588. * @author Charles Pick
  1589. * @class
  1590. * @extends Yii.CComponent
  1591. */
  1592. Yii.CEvent = function CEvent(sender, params) {
  1593. if (sender !== false) {
  1594. this.construct(sender, params);
  1595. }
  1596. };
  1597. Yii.CEvent.prototype = new Yii.CComponent();
  1598. Yii.CEvent.prototype.constructor = Yii.CEvent;
  1599. /**
  1600. * @var {Object} the sender of this event
  1601. */
  1602. Yii.CEvent.prototype.sender = null;
  1603. /**
  1604. * @var {Boolean} whether the event is handled. Defaults to false.
  1605. * When a handler sets this true, the rest of the uninvoked event handlers will not be invoked anymore.
  1606. */
  1607. Yii.CEvent.prototype.handled = false;
  1608. /**
  1609. * @var {Mixed} additional event parameters.
  1610. * @since 1.1.7
  1611. */
  1612. Yii.CEvent.prototype.params = null;
  1613. /**
  1614. * Constructor.
  1615. * @param {Mixed} sender sender of the event
  1616. * @param {Mixed} params additional parameters for the event
  1617. */
  1618. Yii.CEvent.prototype.construct = function (sender, params) {
  1619. if (sender === undefined) {
  1620. sender = null;
  1621. }
  1622. if (params === undefined) {
  1623. params = null;
  1624. }
  1625. this.sender=sender;
  1626. this.params=params;
  1627. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  1628. /**
  1629. * CEnumerable is the base class for all enumerable types.
  1630. *
  1631. * To define an enumerable type, extend CEnumberable and define string constants.
  1632. * Each constant represents an enumerable value.
  1633. * The constant name must be the same as the constant value.
  1634. * For example,
  1635. * <pre>
  1636. * class TextAlign extends Yii.CEnumerable
  1637. * {
  1638. * const Left='Left';
  1639. * const Right='Right';
  1640. * }
  1641. * </pre>
  1642. * Then, one can use the enumerable values such as TextAlign::Left and
  1643. * TextAlign::Right.
  1644. *
  1645. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  1646. * @version $Id: CComponent.php 3066 2011-03-13 14:22:55Z qiang.xue $
  1647. * @package system.base
  1648. * @since 1.0
  1649. * @author Charles Pick
  1650. * @class
  1651. */
  1652. Yii.CEnumerable = function CEnumerable () {
  1653. };
  1654. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  1655. /**
  1656. * CModule is the base class for module and application classes.
  1657. *
  1658. * CModule mainly manages application components and sub-modules.
  1659. *
  1660. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  1661. * @version $Id: CModule.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  1662. * @package system.base
  1663. * @since 1.0.4
  1664. * @author Charles Pick
  1665. * @class
  1666. * @extends Yii.CComponent
  1667. */
  1668. Yii.CModule = function CModule (id, parent, config) {
  1669. if (id !== false) {
  1670. this.models = {};
  1671. this.views = {};
  1672. this.controllers = {};
  1673. this.construct(id, parent, config);
  1674. }
  1675. };
  1676. Yii.CModule.prototype = new Yii.CComponent();
  1677. Yii.CModule.prototype.constructor = Yii.CModule;
  1678. /**
  1679. * @var {Array} the IDs of the application components that should be preloaded.
  1680. */
  1681. Yii.CModule.prototype.preload = [];
  1682. /**
  1683. * @var {Array} the behaviors that should be attached to the module.
  1684. * The behaviors will be attached to the module when {@link init} is called.
  1685. * Please refer to {@link CModel::behaviors} on how to specify the value of this property.
  1686. */
  1687. Yii.CModule.prototype.behaviors = {};
  1688. Yii.CModule.prototype._id = null;
  1689. Yii.CModule.prototype._parentModule = null;
  1690. Yii.CModule.prototype._basePath = null;
  1691. Yii.CModule.prototype._modulePath = null;
  1692. Yii.CModule.prototype._params = null;
  1693. Yii.CModule.prototype._modules = {};
  1694. Yii.CModule.prototype._moduleConfig = {};
  1695. Yii.CModule.prototype._components = {};
  1696. Yii.CModule.prototype._componentConfig = {};
  1697. /**
  1698. * jQuery events to delegate for this module.
  1699. * Array should be of the following format:
  1700. * <pre>
  1701. * [
  1702. * ['#selector a.someLink', 'click', function (e) { alert("clicked!")}],
  1703. * ['#selector form', 'submit', function (e) { alert('Submitted!'); e.preventDefault(); }]
  1704. * ]
  1705. * </pre>
  1706. * These events will be bound to their selectors when the module is run
  1707. * @var Array
  1708. */
  1709. Yii.CModule.prototype.delegates = [];
  1710. /**
  1711. * Holds a list of models belonging to this module
  1712. */
  1713. Yii.CModule.prototype.models = {};
  1714. /**
  1715. * Holds a list of views belonging to this module
  1716. */
  1717. Yii.CModule.prototype.views = {};
  1718. /**
  1719. * Holds a list of controllers belonging to this module
  1720. */
  1721. Yii.CModule.prototype.controllers = {};
  1722. /**
  1723. * Constructor.
  1724. * @param {String} id the ID of this module
  1725. * @param {Yii.CModule} parent the parent module (if any)
  1726. * @param {Mixed} config the module configuration. It can be either an array or
  1727. * the path of a PHP file returning the configuration array.
  1728. */
  1729. Yii.CModule.prototype.construct = function (id, parent, config) {
  1730. if (config === undefined) {
  1731. config = {};
  1732. }
  1733. this._id=id;
  1734. this._parentModule=parent;
  1735. // set basePath at early as possible to avoid trouble
  1736. if(config.basePath !== undefined) {
  1737. this.setBasePath(config.basePath);
  1738. delete config.basePath;
  1739. }
  1740. Yii.setPathOfAlias(id,this.getBasePath());
  1741. this.preinit();
  1742. this.configure(config);
  1743. this.attachBehaviors(this.behaviors);
  1744. this.preloadComponents();
  1745. this.init();
  1746. };
  1747. /**
  1748. * Getter magic method.
  1749. * This method is overridden to support accessing application components
  1750. * like reading module properties.
  1751. * @param {String} name application component or property name
  1752. * @returns {Mixed} the named property value
  1753. */
  1754. Yii.CModule.prototype.get = function (name) {
  1755. if(this.hasComponent(name)) {
  1756. return this.getComponent(name);
  1757. }
  1758. else {
  1759. return Yii.CComponent.prototype.get.call(this, name);
  1760. }
  1761. };
  1762. /**
  1763. * Checks if a property value is null.
  1764. * This method overrides the parent implementation by checking
  1765. * if the named application component is loaded.
  1766. * @param {String} name the property name or the event name
  1767. * @returns {Boolean} whether the property value is null
  1768. */
  1769. Yii.CModule.prototype.isset = function (name) {
  1770. if(this.hasComponent(name)) {
  1771. return this.getComponent(name)!==null;
  1772. }
  1773. else {
  1774. return Yii.CComponent.prototype.isset.call(this, name);
  1775. }
  1776. };
  1777. /**
  1778. * Returns the module ID.
  1779. * @returns {String} the module ID.
  1780. */
  1781. Yii.CModule.prototype.getId = function () {
  1782. return this._id;
  1783. };
  1784. /**
  1785. * Sets the module ID.
  1786. * @param {String} id the module ID
  1787. */
  1788. Yii.CModule.prototype.setId = function (id) {
  1789. this._id=id;
  1790. };
  1791. /**
  1792. * Returns the root directory of the module.
  1793. * @returns {String} the root directory of the module. Defaults to the directory containing the module class.
  1794. */
  1795. Yii.CModule.prototype.getBasePath = function () {
  1796. var classVar;
  1797. if(this._basePath===null) {
  1798. classVar=new ReflectionClass(php.get_class(this));
  1799. this._basePath=php.dirname(classVar.getFileName());
  1800. }
  1801. return this._basePath;
  1802. };
  1803. /**
  1804. * Sets the root directory of the module.
  1805. * This method can only be invoked at the beginning of the constructor.
  1806. * @param {String} path the root directory of the module.
  1807. */
  1808. Yii.CModule.prototype.setBasePath = function (path) {
  1809. this._basePath=path;
  1810. };
  1811. /**
  1812. * Returns user-defined parameters.
  1813. * @returns {Yii.CAttributeCollection} the list of user-defined parameters
  1814. */
  1815. Yii.CModule.prototype.getParams = function () {
  1816. if(this._params!==null) {
  1817. return this._params;
  1818. }
  1819. else
  1820. {
  1821. this._params=new Yii.CAttributeCollection();
  1822. this._params.caseSensitive=true;
  1823. return this._params;
  1824. }
  1825. };
  1826. /**
  1827. * Sets user-defined parameters.
  1828. * @param {Array} value user-defined parameters. This should be in name-value pairs.
  1829. */
  1830. Yii.CModule.prototype.setParams = function (value) {
  1831. var params, k, v;
  1832. params=this.getParams();
  1833. for (k in value) {
  1834. if (value.hasOwnProperty(k)) {
  1835. v = value[k];
  1836. params.add(k,v);
  1837. }
  1838. }
  1839. };
  1840. /**
  1841. * Returns the directory that contains the application modules.
  1842. * @returns {String} the directory that contains the application modules. Defaults to the 'modules' subdirectory of {@link basePath}.
  1843. */
  1844. Yii.CModule.prototype.getModulePath = function () {
  1845. if(this._modulePath!==null) {
  1846. return this._modulePath;
  1847. }
  1848. else {
  1849. return (this._modulePath=this.getBasePath()+"/"+'modules');
  1850. }
  1851. };
  1852. /**
  1853. * Sets the directory that contains the application modules.
  1854. * @param {String} value the directory that contains the application modules.
  1855. */
  1856. Yii.CModule.prototype.setModulePath = function (value) {
  1857. this._modulePath = value;
  1858. };
  1859. /**
  1860. * Sets the aliases that are used in the module.
  1861. * @param {Array} aliases list of aliases to be imported
  1862. */
  1863. Yii.CModule.prototype.setImport = function (aliases) {
  1864. var i, alias;
  1865. for (i in aliases) {
  1866. if (aliases.hasOwnProperty(i)) {
  1867. alias = aliases[i];
  1868. Yii.imports(alias);
  1869. }
  1870. }
  1871. };
  1872. /**
  1873. * Defines the root aliases.
  1874. * @param {Array} mappings list of aliases to be defined. The array keys are root aliases,
  1875. * while the array values are paths or aliases corresponding to the root aliases.
  1876. * For example,
  1877. * <pre>
  1878. * {
  1879. * 'models':'application.models', // an existing alias
  1880. * 'extensions':'application.extensions', // an existing alias
  1881. * 'backend':php.dirname(__FILE__)+'/../backend', // a directory
  1882. * }
  1883. * </pre>
  1884. * @since 1.0.5
  1885. */
  1886. Yii.CModule.prototype.setAliases = function (mappings) {
  1887. var path, alias, name;
  1888. for (name in mappings) {
  1889. if (mappings.hasOwnProperty(name)) {
  1890. alias = mappings[name];
  1891. if((path=Yii.getPathOfAlias(alias))!==false) {
  1892. Yii.setPathOfAlias(name,path);
  1893. }
  1894. else {
  1895. Yii.setPathOfAlias(name,alias);
  1896. }
  1897. }
  1898. }
  1899. };
  1900. /**
  1901. * Returns the parent module.
  1902. * @returns {Yii.CModule} the parent module. Null if this module does not have a parent.
  1903. */
  1904. Yii.CModule.prototype.getParentModule = function () {
  1905. return this._parentModule;
  1906. };
  1907. /**
  1908. * Retrieves the named application module.
  1909. * The module has to be declared in {@link modules}. A new instance will be created
  1910. * when calling this method with the given ID for the first time.
  1911. * @param {String} id application module ID (case-sensitive)
  1912. * @returns {Yii.CModule} the module instance, null if the module is disabled or does not exist.
  1913. */
  1914. Yii.CModule.prototype.getModule = function (id) {
  1915. var config, classVar, module;
  1916. if(this._modules[id] !== undefined) {
  1917. return this._modules[id];
  1918. }
  1919. else if(this._moduleConfig[id] !== undefined) {
  1920. config=this._moduleConfig[id];
  1921. if(config.enabled === undefined || config.enabled) {
  1922. Yii.trace("Loading \"" + id + "\" module",'system.base.CModule');
  1923. classVar=config['class'];
  1924. delete config['class'];
  1925. if(this===Yii.app()) {
  1926. module=Yii.createComponent(classVar,id,null,config);
  1927. }
  1928. else {
  1929. module=Yii.createComponent(classVar,this.getId()+'/'+id,this,config);
  1930. }
  1931. return (this._modules[id]=module);
  1932. }
  1933. }
  1934. };
  1935. /**
  1936. * Returns a value indicating whether the specified module is installed.
  1937. * @param {String} id the module ID
  1938. * @returns {Boolean} whether the specified module is installed.
  1939. * @since 1.1.2
  1940. */
  1941. Yii.CModule.prototype.hasModule = function (id) {
  1942. return this._moduleConfig[id] !== undefined || this._modules[id] !== undefined;
  1943. };
  1944. /**
  1945. * Returns the configuration of the currently installed modules.
  1946. * @returns {Array} the configuration of the currently installed modules (module ID => configuration)
  1947. */
  1948. Yii.CModule.prototype.getModules = function () {
  1949. return this._moduleConfig;
  1950. };
  1951. /**
  1952. * Configures the sub-modules of this module.
  1953. *
  1954. * Call this method to declare sub-modules and configure them with their initial property values.
  1955. * The parameter should be an array of module configurations. Each array element represents a single module,
  1956. * which can be either a string representing the module ID or an ID-configuration pair representing
  1957. * a module with the specified ID and the initial property values.
  1958. *
  1959. * For example, the following array declares two modules:
  1960. * <pre>
  1961. * {
  1962. * 'admin', // a single module ID
  1963. * 'payment':{ // ID-configuration pair
  1964. * 'server':'paymentserver.com',
  1965. * },
  1966. * }
  1967. * </pre>
  1968. *
  1969. * By default, the module class is determined using the expression <code>ucfirst($moduleID).'Module'</code>.
  1970. * And the class file is located under <code>modules/$moduleID</code>.
  1971. * You may override this default by explicitly specifying the 'class' option in the configuration.
  1972. *
  1973. * You may also enable or disable a module by specifying the 'enabled' option in the configuration.
  1974. *
  1975. * @param {Array} modules module configurations.
  1976. */
  1977. Yii.CModule.prototype.setModules = function (modules) {
  1978. var id, module;
  1979. for (id in modules) {
  1980. if (modules.hasOwnProperty(id)) {
  1981. module = modules[id];
  1982. if(php.is_int(id)) {
  1983. id=module;
  1984. module={};
  1985. }
  1986. if(module['class'] === undefined) {
  1987. Yii.setPathOfAlias(id,this.getModulePath()+"/"+id);
  1988. module['class'] = id+'.'+php.ucfirst(id)+'Module';
  1989. }
  1990. if(this._moduleConfig[id] !== undefined) {
  1991. this._moduleConfig[id]=Yii.CMap.mergeArray(this._moduleConfig[id],module);
  1992. }
  1993. else {
  1994. this._moduleConfig[id]=module;
  1995. }
  1996. }
  1997. }
  1998. };
  1999. /**
  2000. * Checks whether the named component exists.
  2001. * @param {String} id application component ID
  2002. * @returns {Boolean} whether the named application component exists (including both loaded and disabled.)
  2003. */
  2004. Yii.CModule.prototype.hasComponent = function (id) {
  2005. return this._components[id] !== undefined || this._componentConfig[id] !== undefined;
  2006. };
  2007. /**
  2008. * Retrieves the named application component.
  2009. * @param {String} id application component ID (case-sensitive)
  2010. * @param {Boolean} createIfNull whether to create the component if it doesn't exist yet. This parameter
  2011. * has been available since version 1.0.6.
  2012. * @returns {CApplicationComponent} the application component instance, null if the application component is disabled or does not exist.
  2013. * @see hasComponent
  2014. */
  2015. Yii.CModule.prototype.getComponent = function (id, createIfNull) {
  2016. var config, component;
  2017. if (createIfNull === undefined) {
  2018. createIfNull = true;
  2019. }
  2020. if(this._components[id] !== undefined) {
  2021. return this._components[id];
  2022. }
  2023. else if(this._componentConfig[id] !== undefined && createIfNull) {
  2024. config=this._componentConfig[id];
  2025. if(config.enabled === undefined || config.enabled) {
  2026. Yii.trace("Loading \"" + id + "\" application component",'system.CModule');
  2027. delete config.enabled;
  2028. component=Yii.createComponent(config);
  2029. component.init();
  2030. return (this._components[id]=component);
  2031. }
  2032. }
  2033. };
  2034. /**
  2035. * Puts a component under the management of the module.
  2036. * The component will be initialized by calling its {@link CApplicationComponent::init() init()}
  2037. * method if it has not done so.
  2038. * @param {String} id component ID
  2039. * @param {CApplicationComponent} component the component to be added to the module.
  2040. * If this parameter is null, it will unload the component from the module.
  2041. */
  2042. Yii.CModule.prototype.setComponent = function (id, component) {
  2043. if(component===null) {
  2044. delete this._components[id];
  2045. }
  2046. else {
  2047. this._components[id]=component;
  2048. if(!component.getIsInitialized()) {
  2049. component.init();
  2050. }
  2051. }
  2052. };
  2053. /**
  2054. * Returns the application components.
  2055. * @param {Boolean} loadedOnly whether to return the loaded components only. If this is set false,
  2056. * then all components specified in the configuration will be returned, whether they are loaded or not.
  2057. * Loaded components will be returned as objects, while unloaded components as configuration arrays.
  2058. * This parameter has been available since version 1.1.3.
  2059. * @returns {Array} the application components (indexed by their IDs)
  2060. */
  2061. Yii.CModule.prototype.getComponents = function (loadedOnly) {
  2062. if (loadedOnly === undefined) {
  2063. loadedOnly = true;
  2064. }
  2065. if(loadedOnly) {
  2066. return this._components;
  2067. }
  2068. else {
  2069. return php.array_merge(this._componentConfig, this._components);
  2070. }
  2071. };
  2072. /**
  2073. * Sets the application components.
  2074. *
  2075. * When a configuration is used to specify a component, it should consist of
  2076. * the component's initial property values (name-value pairs). Additionally,
  2077. * a component can be enabled (default) or disabled by specifying the 'enabled' value
  2078. * in the configuration.
  2079. *
  2080. * If a configuration is specified with an ID that is the same as an existing
  2081. * component or configuration, the existing one will be replaced silently.
  2082. *
  2083. * The following is the configuration for two components:
  2084. * <pre>
  2085. * {
  2086. * 'db':{
  2087. * 'class':'CDbConnection',
  2088. * 'connectionString':'sqlite:path/to/file.db',
  2089. * },
  2090. * 'cache':{
  2091. * 'class':'CDbCache',
  2092. * 'connectionID':'db',
  2093. * 'enabled':!YII_DEBUG, // enable caching in non-debug mode
  2094. * ),
  2095. * }
  2096. * </pre>
  2097. *
  2098. * @param {Array} components application components(id=>component configuration or instances)
  2099. * @param {Boolean} merge whether to merge the new component configuration with the existing one.
  2100. * Defaults to true, meaning the previously registered component configuration of the same ID
  2101. * will be merged with the new configuration. If false, the existing configuration will be replaced completely.
  2102. */
  2103. Yii.CModule.prototype.setComponents = function (components, merge) {
  2104. var component, id;
  2105. if (merge === undefined) {
  2106. merge = true;
  2107. }
  2108. for (id in components) {
  2109. if (components.hasOwnProperty(id)) {
  2110. component = components[id];
  2111. if(component instanceof Yii.CApplicationComponent) {
  2112. this.setComponent(id,component);
  2113. }
  2114. else if(this._componentConfig[id] !== undefined && merge) {
  2115. this._componentConfig[id]=Yii.CMap.prototype.mergeArray(this._componentConfig[id],component);
  2116. }
  2117. else {
  2118. this._componentConfig[id]=component;
  2119. }
  2120. }
  2121. }
  2122. };
  2123. /**
  2124. * Configures the module with the specified configuration.
  2125. * @param {Array} config the configuration array
  2126. */
  2127. Yii.CModule.prototype.configure = function (config) {
  2128. var key, value;
  2129. if(typeof config === 'object') {
  2130. for (key in config) {
  2131. if (config.hasOwnProperty(key)) {
  2132. value = config[key];
  2133. this.set(key,value);
  2134. }
  2135. }
  2136. }
  2137. };
  2138. /**
  2139. * Loads static application components.
  2140. */
  2141. Yii.CModule.prototype.preloadComponents = function () {
  2142. var i, id;
  2143. for (i in this.preload) {
  2144. if (this.preload.hasOwnProperty(i)) {
  2145. id = this.preload[i];
  2146. this.getComponent(id);
  2147. }
  2148. }
  2149. };
  2150. /**
  2151. * Preinitializes the module.
  2152. * This method is called at the beginning of the module constructor.
  2153. * You may override this method to do some customized preinitialization work.
  2154. * Note that at this moment, the module is not configured yet.
  2155. * @see init
  2156. */
  2157. Yii.CModule.prototype.preinit = function () {
  2158. };
  2159. /**
  2160. * Initializes the module.
  2161. * This method is called at the end of the module constructor.
  2162. * Note that at this moment, the module has been configured, the behaviors
  2163. * have been attached and the application components have been registered.
  2164. * @see preinit
  2165. */
  2166. Yii.CModule.prototype.init = function () {
  2167. Yii.forEach(this.delegates, function(i, item) {
  2168. jQuery("body").undelegate(item[0], item[1]).delegate(item[0], item[1], item[2]);
  2169. });
  2170. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2171. /**
  2172. * CList implements an integer-indexed collection class.
  2173. *
  2174. * You can access, append, insert, remove an item by using
  2175. * {@link itemAt}, {@link add}, {@link insertAt}, {@link remove}, and {@link removeAt}.
  2176. * To get the number of the items in the list, use {@link getCount}.
  2177. * CList can also be used like a regular array as follows,
  2178. * <pre>
  2179. * list.push(item); // append at the end
  2180. * list[index]=item; // $index must be between 0 and $list->Count
  2181. * delete list[index]; // remove the item at $index
  2182. * if(list[index] !== undefined) { // if the list has an item at $index
  2183. * for (index in list) // traverse each item in the list
  2184. * n=php.count(list);
  2185. * } // returns the number of items in the list
  2186. * </pre>
  2187. *
  2188. * To extend CList by doing additional operations with each addition or removal
  2189. * operation (e.g. performing type check), override {@link insertAt()}, and {@link removeAt()}.
  2190. *
  2191. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  2192. * @version $Id: CList.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  2193. * @package system.collections
  2194. * @since 1.0
  2195. * @author Charles Pick
  2196. * @class
  2197. * @extends Yii.CComponent
  2198. */
  2199. Yii.CList = function CList (data, readOnly) {
  2200. if (data !== false) {
  2201. this.construct(data, readOnly);
  2202. }
  2203. };
  2204. Yii.CList.prototype = new Array();
  2205. Yii.CList.prototype.constructor = Yii.CList;
  2206. Yii.augment(Yii.CList, Yii.CComponent);
  2207. /**
  2208. * @var {Boolean} whether this list is read-only
  2209. */
  2210. Yii.CList.prototype._r = false;
  2211. /**
  2212. * Constructor.
  2213. * Initializes the list with an array or an iterable object.
  2214. * @param {Array} data the initial data. Default is null, meaning no initialization.
  2215. * @param {Boolean} readOnly whether the list is read-only
  2216. * @throws {Yii.CException} If data is not null and neither an array nor an iterator.
  2217. */
  2218. Yii.CList.prototype.construct = function (data, readOnly) {
  2219. if (data === undefined) {
  2220. data = null;
  2221. }
  2222. if (readOnly === undefined) {
  2223. readOnly = false;
  2224. }
  2225. if(data!==null) {
  2226. this.copyFrom(data);
  2227. }
  2228. this.setReadOnly(readOnly);
  2229. };
  2230. /**
  2231. * @returns {Boolean} whether this list is read-only or not. Defaults to false.
  2232. */
  2233. Yii.CList.prototype.getReadOnly = function () {
  2234. return this._r;
  2235. };
  2236. /**
  2237. * @param {Boolean} value whether this list is read-only or not
  2238. */
  2239. Yii.CList.prototype.setReadOnly = function (value) {
  2240. this._r=value;
  2241. };
  2242. /**
  2243. * Returns the number of items in the list.
  2244. * @returns {Integer} the number of items in the list
  2245. */
  2246. Yii.CList.prototype.getCount = function () {
  2247. return this.length;
  2248. };
  2249. /**
  2250. * Returns the item at the specified offset.
  2251. * This method is exactly the same as {@link offsetGet}.
  2252. * @param {Integer} index the index of the item
  2253. * @returns {Mixed} the item at the index
  2254. * @throws {Yii.CException} if the index is out of the range
  2255. */
  2256. Yii.CList.prototype.itemAt = function (index) {
  2257. if(this[index] !== undefined) {
  2258. return this[index];
  2259. }
  2260. else {
  2261. throw new Yii.CException(Yii.t('yii','List index "{index}" is out of bound.',
  2262. {'{index}':index}));
  2263. }
  2264. };
  2265. /**
  2266. * Appends an item at the end of the list.
  2267. * @param {Mixed} item new item
  2268. * @returns {Integer} the zero-based index at which the item is added
  2269. */
  2270. Yii.CList.prototype.add = function (item) {
  2271. return this.push(item);
  2272. };
  2273. /**
  2274. * Appends an item at the end of the list, fails if the list is read only.
  2275. * @param {Mixed} item new item
  2276. * @returns {Integer} the zero-based index at which the item is added
  2277. */
  2278. Yii.CList.prototype.push = function (item) {
  2279. if (!this._r) {
  2280. return Array.prototype.push.call(this, item);
  2281. }
  2282. else {
  2283. throw new Yii.CException(Yii.t('yii','The list is read only.'));
  2284. }
  2285. };
  2286. /**
  2287. * Pops an item off the end of the list, fails if the list is read only.
  2288. * @returns {Mixed} the popped item
  2289. */
  2290. Yii.CList.prototype.pop = function () {
  2291. if (!this._r) {
  2292. return Array.prototype.pop.call(this);
  2293. }
  2294. else {
  2295. throw new Yii.CException(Yii.t('yii','The list is read only.'));
  2296. }
  2297. };
  2298. /**
  2299. * Shifts an item off the start of the list, fails if the list is read only.
  2300. * @returns {Mixed} the shifted item
  2301. */
  2302. Yii.CList.prototype.shift = function () {
  2303. if (!this._r) {
  2304. return Array.prototype.shift.call(this);
  2305. }
  2306. else {
  2307. throw new Yii.CException(Yii.t('yii','The list is read only.'));
  2308. }
  2309. };
  2310. /**
  2311. * Inserts an item at the specified position.
  2312. * Original item at the position and the next items
  2313. * will be moved one step towards the end.
  2314. * @param {Integer} index the specified position.
  2315. * @param {Mixed} item new item
  2316. * @throws {Yii.CException} If the index specified exceeds the bound or the list is read-only
  2317. */
  2318. Yii.CList.prototype.insertAt = function (index, item) {
  2319. if(!this._r)
  2320. {
  2321. if(index===this.length) {
  2322. this[this.length + 1]=item;
  2323. }
  2324. else if(index>=0 && index<this.length)
  2325. {
  2326. php.array_splice(this,index,0,[item]);
  2327. }
  2328. else {
  2329. throw new Yii.CException(Yii.t('yii','List index "{index}" is out of bound.',
  2330. {'{index}':index}));
  2331. }
  2332. }
  2333. else {
  2334. throw new Yii.CException(Yii.t('yii','The list is read only.'));
  2335. }
  2336. };
  2337. /**
  2338. * Removes an item from the list.
  2339. * The list will first search for the item.
  2340. * The first item found will be removed from the list.
  2341. * @param {Mixed} item the item to be removed.
  2342. * @returns {Integer} the index at which the item is being removed
  2343. * @throws {Yii.CException} If the item does not exist
  2344. */
  2345. Yii.CList.prototype.remove = function (item) {
  2346. var index;
  2347. if((index=this.indexOf(item))>=0)
  2348. {
  2349. this.removeAt(index);
  2350. return index;
  2351. }
  2352. else {
  2353. return false;
  2354. }
  2355. };
  2356. /**
  2357. * Removes an item at the specified position.
  2358. * @param {Integer} index the index of the item to be removed.
  2359. * @returns {Mixed} the removed item.
  2360. * @throws {Yii.CException} If the index specified exceeds the bound or the list is read-only
  2361. */
  2362. Yii.CList.prototype.removeAt = function (index) {
  2363. var item;
  2364. if(!this._r) {
  2365. if(index>=0 && index<this.length) {
  2366. if(index===this.length) {
  2367. return this.pop();
  2368. }
  2369. else
  2370. {
  2371. item=this[index];
  2372. php.array_splice(this,index,1);
  2373. return item;
  2374. }
  2375. }
  2376. else {
  2377. throw new Yii.CException(Yii.t('yii','List index "{index}" is out of bound.',
  2378. {'{index}':index}));
  2379. }
  2380. }
  2381. else {
  2382. throw new Yii.CException(Yii.t('yii','The list is read only.'));
  2383. }
  2384. };
  2385. /**
  2386. * Removes all items in the list.
  2387. */
  2388. Yii.CList.prototype.clear = function () {
  2389. var i;
  2390. for(i=this.length - 1; i >= 0; --i) {
  2391. this.removeAt(i);
  2392. }
  2393. };
  2394. /**
  2395. * @param {Mixed} item the item
  2396. * @returns {Boolean} whether the list contains the item
  2397. */
  2398. Yii.CList.prototype.contains = function (item) {
  2399. return this.indexOf(item) >= 0;
  2400. };
  2401. /**
  2402. * @returns {Array} the list of items in array
  2403. */
  2404. Yii.CList.prototype.toArray = function () {
  2405. var ret = [], i, limit;
  2406. limit = this.length;
  2407. for (i = 0; i < limit; i++) {
  2408. ret.push(this[i]);
  2409. }
  2410. return ret;
  2411. };
  2412. /**
  2413. * Copies iterable data into the list.
  2414. * Note, existing data in the list will be cleared first.
  2415. * @param {Mixed} data the data to be copied from, must be an array or object implementing Traversable
  2416. * @throws {Yii.CException} If data is neither an array nor a Traversable.
  2417. */
  2418. Yii.CList.prototype.copyFrom = function (data) {
  2419. var i, item, limit;
  2420. if(Object.prototype.toString.call(data) === '[object Array]' || (data instanceof Array)) {
  2421. if(this.length > 0) {
  2422. this.clear();
  2423. }
  2424. if(data instanceof Yii.CList) {
  2425. data=data.toArray();
  2426. }
  2427. for (i = 0, limit = data.length; i < limit; i++) {
  2428. item = data[i];
  2429. this.add(item);
  2430. }
  2431. }
  2432. else if(data!==null) {
  2433. throw new Yii.CException(Yii.t('yii','List data must be an array or an object implementing Traversable.'));
  2434. }
  2435. };
  2436. /**
  2437. * Merges iterable data into the map.
  2438. * New data will be appended to the end of the existing data.
  2439. * @param {Mixed} data the data to be merged with, must be an array or object implementing Traversable
  2440. * @throws {Yii.CException} If data is neither an array nor an iterator.
  2441. */
  2442. Yii.CList.prototype.mergeWith = function (data) {
  2443. var i, item;
  2444. if(Object.prototype.toString.call(data) === '[object Array]' || (data instanceof Array))
  2445. {
  2446. if(data instanceof Yii.CList) {
  2447. data=data.toArray();
  2448. }
  2449. for (i in data) {
  2450. if (data.hasOwnProperty(i)) {
  2451. item = data[i];
  2452. this.add(item);
  2453. }
  2454. }
  2455. }
  2456. else if(data!==null) {
  2457. throw new Yii.CException(Yii.t('yii','List data must be an array or an object implementing Traversable.'));
  2458. }
  2459. };
  2460. /**
  2461. * Provides convenient access to Yii.forEach()
  2462. * @param {Function} callback The callback function, this will receive 2 parameters, key and value
  2463. * @returns {Yii.CList} the list
  2464. */
  2465. Yii.CList.prototype.forEach = function(callback) {
  2466. return Yii.forEach(this,callback);
  2467. };
  2468. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2469. /**
  2470. * CMap implements a collection that takes key-value pairs.
  2471. *
  2472. * You can access, add or remove an item with a key by using
  2473. * {@link itemAt}, {@link add}, and {@link remove}.
  2474. * To get the number of the items in the map, use {@link getCount}.
  2475. * CMap can also be used like a regular array as follows,
  2476. * <pre>
  2477. * map[key]=value; // add a key-value pair
  2478. * delete map[key]; // remove the value with the specified key
  2479. * if(map[key] !== undefined) { // if the map contains the key
  2480. * for (key in map) // traverse the items in the map
  2481. * n=php.count(map);
  2482. * } // returns the number of items in the map
  2483. * </pre>
  2484. *
  2485. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  2486. * @version $Id: CMap.php 3153 2011-04-01 12:50:06Z qiang.xue $
  2487. * @package system.collections
  2488. * @since 1.0
  2489. * @author Charles Pick
  2490. * @class
  2491. * @extends Yii.CComponent
  2492. */
  2493. Yii.CMap = function CMap (data, readOnly) {
  2494. if (data !== false) {
  2495. this.construct(data, readOnly);
  2496. }
  2497. };
  2498. Yii.CMap.prototype = new Yii.CComponent();
  2499. Yii.CMap.prototype.constructor = Yii.CMap;
  2500. /**
  2501. * Constructor.
  2502. * Initializes the list with an array or an iterable object.
  2503. * @param {Object} data the intial data. Default is null, meaning no initialization.
  2504. * @throws {Yii.CException} If data is not null and neither an array nor an iterator.
  2505. */
  2506. Yii.CMap.prototype.construct = function (data) {
  2507. if (data === undefined) {
  2508. data = null;
  2509. }
  2510. if(data!==null) {
  2511. this.copyFrom(data);
  2512. }
  2513. };
  2514. /**
  2515. * Returns the number of items in the map.
  2516. * @returns {Integer} number of items in the map.
  2517. */
  2518. Yii.CMap.prototype.count = function () {
  2519. return this.getCount();
  2520. };
  2521. /**
  2522. * Returns the number of items in the map.
  2523. * @returns {Integer} the number of items in the map
  2524. */
  2525. Yii.CMap.prototype.getCount = function () {
  2526. var total = 0, i;
  2527. for (i in this) {
  2528. if (this.hasOwnProperty(i)) {
  2529. total++;
  2530. }
  2531. }
  2532. return total;
  2533. };
  2534. /**
  2535. * @returns {Array} the key list
  2536. */
  2537. Yii.CMap.prototype.getKeys = function () {
  2538. var i, keys = [];
  2539. for (i in this) {
  2540. if (this.hasOwnProperty(i)) {
  2541. keys.push(i);
  2542. }
  2543. }
  2544. return keys;
  2545. };
  2546. /**
  2547. * Returns the item with the specified key.
  2548. * @param {Mixed} key the key
  2549. * @returns {Mixed} the element at the offset, null if no element is found at the offset
  2550. */
  2551. Yii.CMap.prototype.itemAt = function (key) {
  2552. if(this[key] !== undefined) {
  2553. return this[key];
  2554. }
  2555. else {
  2556. return null;
  2557. }
  2558. };
  2559. /**
  2560. * Adds an item into the map.
  2561. * Note, if the specified key already exists, the old value will be overwritten.
  2562. * @param {Mixed} key key
  2563. * @param {Mixed} value value
  2564. * @throws {Yii.CException} if the map is read-only
  2565. */
  2566. Yii.CMap.prototype.add = function (key, value) {
  2567. if (key === null) {
  2568. key = this.count();
  2569. }
  2570. this[key] = value;
  2571. };
  2572. /**
  2573. * Removes an item from the map by its key.
  2574. * @param {Mixed} key the key of the item to be removed
  2575. * @returns {Mixed} the removed value, null if no such key exists.
  2576. * @throws {Yii.CException} if the map is read-only
  2577. */
  2578. Yii.CMap.prototype.remove = function (key) {
  2579. var value;
  2580. if(this[key] !== undefined) {
  2581. value=this[key];
  2582. delete this[key];
  2583. return value;
  2584. }
  2585. };
  2586. /**
  2587. * Removes all items in the map.
  2588. */
  2589. Yii.CMap.prototype.clear = function () {
  2590. var i, keyList, key;
  2591. for (i in this) {
  2592. if (this.hasOwnProperty(i)) {
  2593. this.remove(i);
  2594. }
  2595. }
  2596. };
  2597. /**
  2598. * @param {Mixed} key the key
  2599. * @returns {Boolean} whether the map contains an item with the specified key
  2600. */
  2601. Yii.CMap.prototype.contains = function (key) {
  2602. return this[key] !== undefined;
  2603. };
  2604. /**
  2605. * @returns {Array} the list of items in array
  2606. */
  2607. Yii.CMap.prototype.toArray = function () {
  2608. var i, ret = [];
  2609. for (i in this) {
  2610. if (this.hasOwnProperty(i)) {
  2611. ret.push(this[i]);
  2612. }
  2613. }
  2614. return ret;
  2615. };
  2616. /**
  2617. * @returns {Object} the list of items in object
  2618. */
  2619. Yii.CMap.prototype.toObject = function () {
  2620. var i, ret = {};
  2621. for (i in this) {
  2622. if (this.hasOwnProperty(i)) {
  2623. ret[i] = this[i];
  2624. }
  2625. }
  2626. return ret;
  2627. };
  2628. /**
  2629. * Copies iterable data into the map.
  2630. * Note, existing data in the map will be cleared first.
  2631. * @param {Mixed} data the data to be copied from, must be an array or object implementing Traversable
  2632. * @throws {Yii.CException} If data is neither an array nor an iterator.
  2633. */
  2634. Yii.CMap.prototype.copyFrom = function (data) {
  2635. var key, value;
  2636. if(typeof data === "object") {
  2637. if(this.getCount()>0) {
  2638. this.clear();
  2639. }
  2640. if(data instanceof Yii.CMap) {
  2641. data=data.toObject();
  2642. }
  2643. for (key in data) {
  2644. if (data.hasOwnProperty(key)) {
  2645. value = data[key];
  2646. this.add(key,value);
  2647. }
  2648. }
  2649. }
  2650. else if(data!==null) {
  2651. throw new Yii.CException(Yii.t('yii','Map data must be an array or an object implementing Traversable.'));
  2652. }
  2653. };
  2654. /**
  2655. * Merges iterable data into the map.
  2656. *
  2657. * Existing elements in the map will be overwritten if their keys are the same as those in the source.
  2658. * If the merge is recursive, the following algorithm is performed:
  2659. * <ul>
  2660. * <li>the map data is saved as $a, and the source data is saved as $b;</li>
  2661. * <li>if $a and $b both have an array indxed at the same string key, the arrays will be merged using this algorithm;</li>
  2662. * <li>any integer-indexed elements in $b will be appended to $a and reindxed accordingly;</li>
  2663. * <li>any string-indexed elements in $b will overwrite elements in $a with the same index;</li>
  2664. * </ul>
  2665. *
  2666. * @param {Mixed} data the data to be merged with, must be an array or object implementing Traversable
  2667. * @param {Boolean} recursive whether the merging should be recursive.
  2668. *
  2669. * @throws {Yii.CException} If data is neither an array nor an iterator.
  2670. */
  2671. Yii.CMap.prototype.mergeWith = function (data, recursive) {
  2672. var d, key, value;
  2673. if (recursive === undefined) {
  2674. recursive = true;
  2675. }
  2676. if(typeof data === "object") {
  2677. if(data instanceof Yii.CMap) {
  2678. data=data.toObject();
  2679. }
  2680. else if(data instanceof Yii.CList) {
  2681. data=data.toArray();
  2682. }
  2683. if(recursive) {
  2684. this.mergeArray(this,data);
  2685. }
  2686. else
  2687. {
  2688. for (key in data) {
  2689. if (data.hasOwnProperty(key)) {
  2690. value = data[key];
  2691. this.add(key,value);
  2692. }
  2693. }
  2694. }
  2695. }
  2696. else if(data!==null) {
  2697. throw new Yii.CException(Yii.t('yii','Map data must be an array or an object implementing Traversable.'));
  2698. }
  2699. };
  2700. /**
  2701. * Merges two arrays into one recursively.
  2702. * If each array has an element with the same string key value, the latter
  2703. * will overwrite the former (different from array_merge_recursive).
  2704. * Recursive merging will be conducted if both arrays have an element of array
  2705. * type and are having the same key.
  2706. * For integer-keyed elements, the elements from the latter array will
  2707. * be appended to the former array.
  2708. * @param {Array} a array to be merged to
  2709. * @param {Array} b array to be merged from
  2710. * @returns {Array} the merged array (the original arrays are not changed.)
  2711. * @see mergeWith
  2712. */
  2713. Yii.CMap.prototype.mergeArray = function (a, b) {
  2714. var k, v;
  2715. for (k in b) {
  2716. if (b.hasOwnProperty(k)) {
  2717. v = b[k];
  2718. if((typeof(k) === 'number' && (k % 1 ? false : true))) {
  2719. a[k] !== undefined ? a.push(v) : a[k]=v;
  2720. }
  2721. else if (a[k] !== undefined && typeof a[k] === "object") {
  2722. a[k]=this.mergeArray(a[k],v);
  2723. }
  2724. else {
  2725. a[k]=v;
  2726. }
  2727. }
  2728. }
  2729. return a;
  2730. };
  2731. /**
  2732. * Provides convenient access to Yii.forEach()
  2733. * @param {Function} callback The callback function, this will receive 2 parameters, key and value
  2734. * @returns {Yii.CMap} the map
  2735. */
  2736. Yii.CMap.prototype.forEach = function(callback) {
  2737. return Yii.forEach(this,callback);
  2738. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2739. /**
  2740. * CValidator is the base class for all validators.
  2741. *
  2742. * Child classes must implement the {@link validateAttribute} method.
  2743. *
  2744. * The following properties are defined in CValidator:
  2745. * <ul>
  2746. * <li>{@link attributes}: array, list of attributes to be validated;</li>
  2747. * <li>{@link message}: string, the customized error message. The message
  2748. * may contain placeholders that will be replaced with the actual content.
  2749. * For example, the "{attribute}" placeholder will be replaced with the label
  2750. * of the problematic attribute. Different validators may define additional
  2751. * placeholders.</li>
  2752. * <li>{@link on}: string, in which scenario should the validator be in effect.
  2753. * This is used to match the 'on' parameter supplied when calling {@link CModel::validate}.</li>
  2754. * </ul>
  2755. *
  2756. * When using {@link createValidator} to create a validator, the following aliases
  2757. * are recognized as the corresponding built-in validator classes:
  2758. * <ul>
  2759. * <li>required: {@link CRequiredValidator}</li>
  2760. * <li>filter: {@link CFilterValidator}</li>
  2761. * <li>match: {@link CRegularExpressionValidator}</li>
  2762. * <li>email: {@link CEmailValidator}</li>
  2763. * <li>url: {@link CUrlValidator}</li>
  2764. * <li>unique: {@link CUniqueValidator}</li>
  2765. * <li>compare: {@link CCompareValidator}</li>
  2766. * <li>length: {@link CStringValidator}</li>
  2767. * <li>in: {@link CRangeValidator}</li>
  2768. * <li>numerical: {@link CNumberValidator}</li>
  2769. * <li>captcha: {@link CCaptchaValidator}</li>
  2770. * <li>type: {@link CTypeValidator}</li>
  2771. * <li>file: {@link CFileValidator}</li>
  2772. * <li>default: {@link CDefaultValueValidator}</li>
  2773. * <li>exist: {@link CExistValidator}</li>
  2774. * <li>boolean: {@link CBooleanValidator}</li>
  2775. * <li>date: {@link CDateValidator}</li>
  2776. * <li>safe: {@link CSafeValidator}</li>
  2777. * <li>unsafe: {@link CUnsafeValidator}</li>
  2778. * </ul>
  2779. *
  2780. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  2781. * @version $Id: CValidator.php 3160 2011-04-03 01:08:23Z qiang.xue $
  2782. * @package system.validators
  2783. * @since 1.0
  2784. * @author Charles Pick
  2785. * @class
  2786. * @extends Yii.CComponent
  2787. */
  2788. Yii.CValidator = function CValidator() {
  2789. };
  2790. Yii.CValidator.prototype = new Yii.CComponent();
  2791. Yii.CValidator.prototype.constructor = Yii.CValidator;
  2792. /**
  2793. * @var {Object} list of built-in validators (name=>class)
  2794. */
  2795. Yii.CValidator.prototype.builtInValidators = {
  2796. 'required':'Yii.CRequiredValidator',
  2797. 'filter':'Yii.CFilterValidator',
  2798. 'match':'Yii.CRegularExpressionValidator',
  2799. 'email':'Yii.CEmailValidator',
  2800. 'url':'Yii.CUrlValidator',
  2801. 'unique':'Yii.CUniqueValidator',
  2802. 'compare':'Yii.CCompareValidator',
  2803. 'length':'Yii.CStringValidator',
  2804. 'in':'Yii.CRangeValidator',
  2805. 'numerical':'Yii.CNumberValidator',
  2806. 'captcha':'Yii.CCaptchaValidator',
  2807. 'type':'Yii.CTypeValidator',
  2808. 'file':'Yii.CFileValidator',
  2809. 'default':'Yii.CDefaultValueValidator',
  2810. 'exist':'Yii.CExistValidator',
  2811. 'boolean':'Yii.CBooleanValidator',
  2812. 'safe':'Yii.CSafeValidator',
  2813. 'unsafe':'Yii.CUnsafeValidator',
  2814. 'date':'Yii.CDateValidator'
  2815. };
  2816. /**
  2817. * @var {Array} list of attributes to be validated.
  2818. */
  2819. Yii.CValidator.prototype.attributes = null;
  2820. /**
  2821. * @var {String} the user-defined error message. Different validators may define various
  2822. * placeholders in the message that are to be replaced with actual values. All validators
  2823. * recognize "{attribute}" placeholder, which will be replaced with the label of the attribute.
  2824. */
  2825. Yii.CValidator.prototype.message = null;
  2826. /**
  2827. * @var {Boolean} whether this validation rule should be skipped if when there is already a validation
  2828. * error for the current attribute. Defaults to false.
  2829. * @since 1.1.1
  2830. */
  2831. Yii.CValidator.prototype.skipOnError = false;
  2832. /**
  2833. * @var {Array} list of scenarios that the validator should be applied.
  2834. * Each array value refers to a scenario name with the same name as its array key.
  2835. */
  2836. Yii.CValidator.prototype.on = null;
  2837. /**
  2838. * @var {Boolean} whether attributes listed with this validator should be considered safe for massive assignment.
  2839. * Defaults to true.
  2840. * @since 1.1.4
  2841. */
  2842. Yii.CValidator.prototype.safe = true;
  2843. /**
  2844. * @var {Boolean} whether to perform client-side validation. Defaults to true.
  2845. * Please refer to {@link CActiveForm::enableClientValidation} for more details about client-side validation.
  2846. * @since 1.1.7
  2847. */
  2848. Yii.CValidator.prototype.enableClientValidation = true;
  2849. /**
  2850. * Validates a single attribute.
  2851. * This method should be overridden by child classes.
  2852. * @param {Yii.CModel} object the data object being validated
  2853. * @param {String} attribute the name of the attribute to be validated.
  2854. */
  2855. Yii.CValidator.prototype.validateAttribute = function (object, attribute) {
  2856. };
  2857. /**
  2858. * Creates a validator object.
  2859. * @param {String} name the name or class of the validator
  2860. * @param {Yii.CModel} object the data object being validated that may contain the inline validation method
  2861. * @param {Mixed} attributes list of attributes to be validated. This can be either an array of
  2862. * the attribute names or a string of comma-separated attribute names.
  2863. * @param {Array} params initial values to be applied to the validator properties
  2864. * @returns {Yii.CValidator} the validator
  2865. */
  2866. Yii.CValidator.prototype.createValidator = function (name, object, attributes, params) {
  2867. var n, on, validator, builtInValidators, className, value, nameParts, i, limit, classObject;
  2868. if (params === undefined) {
  2869. params = [];
  2870. }
  2871. if(typeof(attributes) === 'string') {
  2872. attributes=attributes.split(/[\s,]+/);
  2873. }
  2874. if(params.on !== undefined) {
  2875. if(Object.prototype.toString.call(params.on) === '[object Array]') {
  2876. on=params.on;
  2877. }
  2878. else {
  2879. on=params.on.split(/[\s,]+/);
  2880. }
  2881. }
  2882. else {
  2883. on=[];
  2884. }
  2885. if (object[name] !== undefined && typeof object[name] === "function") {
  2886. validator=new Yii.CInlineValidator();
  2887. validator.attributes=attributes;
  2888. validator.method=name;
  2889. validator.params=params;
  2890. if(params.skipOnError !== undefined) {
  2891. validator.skipOnError=params.skipOnError;
  2892. }
  2893. }
  2894. else {
  2895. params.attributes = attributes;
  2896. if(this.builtInValidators[name] !== undefined) {
  2897. className = this.builtInValidators[name];
  2898. }
  2899. else {
  2900. className = name;
  2901. }
  2902. if (className.slice(0,3) === "Yii") {
  2903. validator=new Yii[className.slice(4)]();
  2904. }
  2905. else {
  2906. validator = new window[className]();
  2907. }
  2908. for (n in params) {
  2909. if (params.hasOwnProperty(n)) {
  2910. value = params[n];
  2911. validator[n]=value;
  2912. }
  2913. }
  2914. }
  2915. validator.on=php.empty(on) ? [] : php.array_combine(on,on);
  2916. return validator;
  2917. };
  2918. /**
  2919. * Validates the specified object.
  2920. * @param {Yii.CModel} object the data object being validated
  2921. * @param {Array} attributes the list of attributes to be validated. Defaults to null,
  2922. * meaning every attribute listed in {@link attributes} will be validated.
  2923. */
  2924. Yii.CValidator.prototype.validate = function (object, attributes) {
  2925. var i, attribute, self = this;
  2926. if (attributes === undefined) {
  2927. attributes = null;
  2928. }
  2929. if(Object.prototype.toString.call(attributes) === '[object Array]') {
  2930. attributes=php.array_intersect(this.attributes,attributes);
  2931. }
  2932. else {
  2933. attributes=this.attributes;
  2934. }
  2935. Yii.forEach(attributes, function(i,attribute) {
  2936. if(!self.skipOnError || !object.hasErrors(attribute)) {
  2937. self.validateAttribute(object,attribute);
  2938. }
  2939. });
  2940. };
  2941. /**
  2942. * Returns the JavaScript needed for performing client-side validation.
  2943. * Do not override this method if the validator does not support client-side validation.
  2944. * Two predefined JavaScript variables can be used:
  2945. * <ul>
  2946. * <li>value: the value to be validated</li>
  2947. * <li>messages: an array used to hold the validation error messages for the value</li>
  2948. * </ul>
  2949. * @param {Yii.CModel} object the data object being validated
  2950. * @param {String} attribute the name of the attribute to be validated.
  2951. * @returns {String} the client-side validation script. Null if the validator does not support client-side validation.
  2952. * @see CActiveForm::enableClientValidation
  2953. * @since 1.1.7
  2954. */
  2955. Yii.CValidator.prototype.clientValidateAttribute = function (object, attribute) {
  2956. };
  2957. /**
  2958. * Returns a value indicating whether the validator applies to the specified scenario.
  2959. * A validator applies to a scenario as long as any of the following conditions is met:
  2960. * <ul>
  2961. * <li>the validator's "on" property is empty</li>
  2962. * <li>the validator's "on" property contains the specified scenario</li>
  2963. * </ul>
  2964. * @param {String} scenario scenario name
  2965. * @returns {Boolean} whether the validator applies to the specified scenario.
  2966. * @since 1.0.2
  2967. */
  2968. Yii.CValidator.prototype.applyTo = function (scenario) {
  2969. return php.empty(this.on) || this.on[scenario] !== undefined;
  2970. };
  2971. /**
  2972. * Adds an error about the specified attribute to the active record.
  2973. * This is a helper method that performs message selection and internationalization.
  2974. * @param {Yii.CModel} object the data object being validated
  2975. * @param {String} attribute the attribute being validated
  2976. * @param {String} message the error message
  2977. * @param {Array} params values for the placeholders in the error message
  2978. */
  2979. Yii.CValidator.prototype.addError = function (object, attribute, message, params) {
  2980. if (params === undefined) {
  2981. params = [];
  2982. }
  2983. params['{attribute}']=object.getAttributeLabel(attribute);
  2984. object.addError(attribute,php.strtr(message,params));
  2985. };
  2986. /**
  2987. * Checks if the given value is empty.
  2988. * A value is considered empty if it is null, an empty array, or the trimmed result is an empty string.
  2989. * Note that this method is different from PHP empty(). It will return false when the value is 0.
  2990. * @param {Mixed} value the value to be checked
  2991. * @param {Boolean} trim whether to perform trimming before checking if the string is empty. Defaults to false.
  2992. * @returns {Boolean} whether the value is empty
  2993. * @since 1.0.9
  2994. */
  2995. Yii.CValidator.prototype.isEmpty = function (value, trim) {
  2996. if (trim === undefined) {
  2997. trim = false;
  2998. }
  2999. return value===null || value===[] || value==='' || trim && (/boolean|number|string/).test(typeof value) && php.trim(value)==='';
  3000. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3001. /**
  3002. * CMessageSource is the base class for message translation repository classes.
  3003. *
  3004. * A message source is an application component that provides message internationalization (i18n).
  3005. * It stores messages translated in different languages and provides
  3006. * these translated versions when requested.
  3007. *
  3008. * A concrete class must implement {@link loadMessages} or override {@link translateMessage}.
  3009. *
  3010. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3011. * @version $Id: CMessageSource.php 2798 2011-01-01 19:29:03Z qiang.xue $
  3012. * @package system.i18n
  3013. * @since 1.0
  3014. * @author Charles Pick
  3015. * @class
  3016. * @extends Yii.CApplicationComponent
  3017. */
  3018. Yii.CMessageSource = function CMessageSource () {
  3019. };
  3020. Yii.CMessageSource.prototype = new Yii.CApplicationComponent();
  3021. Yii.CMessageSource.prototype.constructor = Yii.CMessageSource;
  3022. /**
  3023. * @var {Boolean} whether to force message translation when the source and target languages are the same.
  3024. * Defaults to false, meaning translation is only performed when source and target languages are different.
  3025. * @since 1.1.4
  3026. */
  3027. Yii.CMessageSource.prototype.forceTranslation = false;
  3028. Yii.CMessageSource.prototype._language = null;
  3029. Yii.CMessageSource.prototype._messages = {};
  3030. /**
  3031. * Loads the message translation for the specified language and category.
  3032. * @param {String} category the message category
  3033. * @param {String} language the target language
  3034. * @returns {Object} the loaded messages
  3035. */
  3036. Yii.CMessageSource.prototype.loadMessages = function (category, language) {
  3037. };
  3038. /**
  3039. * @returns {String} the language that the source messages are written in.
  3040. * Defaults to {@link CApplication::language application language}.
  3041. */
  3042. Yii.CMessageSource.prototype.getLanguage = function () {
  3043. return this._language===null ? Yii.app().sourceLanguage : this._language;
  3044. };
  3045. /**
  3046. * @param {String} language the language that the source messages are written in.
  3047. */
  3048. Yii.CMessageSource.prototype.setLanguage = function (language) {
  3049. this._language=Yii.CLocale.prototype.getCanonicalID(language);
  3050. };
  3051. /**
  3052. * Translates a message to the specified language.
  3053. *
  3054. * Note, if the specified language is the same as
  3055. * the {@link getLanguage source message language}, messages will NOT be translated.
  3056. *
  3057. * If the message is not found in the translations, an {@link onMissingTranslation}
  3058. * event will be raised. Handlers can mark this message or do some
  3059. * default handling. The {@link CMissingTranslationEvent::message}
  3060. * property of the event parameter will be returned.
  3061. *
  3062. * @param {String} category the message category
  3063. * @param {String} message the message to be translated
  3064. * @param {String} language the target language. If null (default), the {@link CApplication::getLanguage application language} will be used.
  3065. * This parameter has been available since version 1.0.3.
  3066. * @returns {String} the translated message (or the original message if translation is not needed)
  3067. */
  3068. Yii.CMessageSource.prototype.translate = function (category, message, language) {
  3069. if (language === undefined) {
  3070. language = null;
  3071. }
  3072. if(language===null) {
  3073. language=Yii.app().getLanguage();
  3074. }
  3075. if(this.forceTranslation || language!==this.getLanguage()) {
  3076. return this.translateMessage(category,message,language);
  3077. }
  3078. else {
  3079. return message;
  3080. }
  3081. };
  3082. /**
  3083. * Translates the specified message.
  3084. * If the message is not found, an {@link onMissingTranslation}
  3085. * event will be raised.
  3086. * @param {String} category the category that the message belongs to
  3087. * @param {String} message the message to be translated
  3088. * @param {String} language the target language
  3089. * @returns {String} the translated message
  3090. */
  3091. Yii.CMessageSource.prototype.translateMessage = function (category, message, language) {
  3092. var key, event;
  3093. key=language+'.'+category;
  3094. if(this._messages[key] === undefined) {
  3095. this._messages[key]=this.loadMessages(category,language);
  3096. }
  3097. if(this._messages[key][message] !== undefined && this._messages[key][message]!=='') {
  3098. return this._messages[key][message];
  3099. }
  3100. else if(this.hasEventHandler('onMissingTranslation'))
  3101. {
  3102. event=new Yii.CMissingTranslationEvent(this,category,message,language);
  3103. this.onMissingTranslation(event);
  3104. return event.message;
  3105. }
  3106. else {
  3107. return message;
  3108. }
  3109. };
  3110. /**
  3111. * Raised when a message cannot be translated.
  3112. * Handlers may log this message or do some default handling.
  3113. * The {@link CMissingTranslationEvent::message} property
  3114. * will be returned by {@link translateMessage}.
  3115. * @param {Yii.CMissingTranslationEvent} event the event parameter
  3116. */
  3117. Yii.CMessageSource.prototype.onMissingTranslation = function (event) {
  3118. this.raiseEvent('onMissingTranslation',event);
  3119. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3120. /**
  3121. * CFilter is the base class for all filters.
  3122. *
  3123. * A filter can be applied before and after an action is executed.
  3124. * It can modify the context that the action is to run or decorate the result that the
  3125. * action generates.
  3126. *
  3127. * Override {@link preFilter()} to specify the filtering logic that should be applied
  3128. * before the action, and {@link postFilter()} for filtering logic after the action.
  3129. *
  3130. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3131. * @version $Id: CFilter.php 2799 2011-01-01 19:31:13Z qiang.xue $
  3132. * @package system.web.filters
  3133. * @since 1.0
  3134. * @author Charles Pick
  3135. * @class
  3136. * @extends Yii.CComponent
  3137. */
  3138. Yii.CFilter = function CFilter () {
  3139. };
  3140. Yii.CFilter.prototype = new Yii.CComponent();
  3141. Yii.CFilter.prototype.constructor = Yii.CFilter;
  3142. /**
  3143. * Performs the filtering.
  3144. * The default implementation is to invoke {@link preFilter}
  3145. * and {@link postFilter} which are meant to be overridden
  3146. * child classes. If a child class needs to override this method,
  3147. * make sure it calls <code>$filterChain->run()</code>
  3148. * if the action should be executed.
  3149. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  3150. */
  3151. Yii.CFilter.prototype.filter = function (filterChain) {
  3152. if(this.preFilter(filterChain))
  3153. {
  3154. filterChain.run();
  3155. this.postFilter(filterChain);
  3156. }
  3157. };
  3158. /**
  3159. * Initializes the filter.
  3160. * This method is invoked after the filter properties are initialized
  3161. * and before {@link preFilter} is called.
  3162. * You may override this method to include some initialization logic.
  3163. * @since 1.1.4
  3164. */
  3165. Yii.CFilter.prototype.init = function () {
  3166. };
  3167. /**
  3168. * Performs the pre-action filtering.
  3169. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  3170. * @returns {Boolean} whether the filtering process should continue and the action
  3171. * should be executed.
  3172. */
  3173. Yii.CFilter.prototype.preFilter = function (filterChain) {
  3174. return true;
  3175. };
  3176. /**
  3177. * Performs the post-action filtering.
  3178. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  3179. */
  3180. Yii.CFilter.prototype.postFilter = function (filterChain) {
  3181. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3182. /**
  3183. * CViewRenderer is the base class for view renderer classes.
  3184. *
  3185. * A view renderer is an application component that renders views written
  3186. * in a customized syntax.
  3187. *
  3188. * Once installing a view renderer as a 'viewRenderer' application component,
  3189. * the normal view rendering process will be intercepted by the renderer.
  3190. * The renderer will first parse the source view file and then render the
  3191. * the resulting view file.
  3192. *
  3193. * Parsing results are saved as temporary files that may be stored
  3194. * under the application runtime directory or together with the source view file.
  3195. *
  3196. * @originalAuthor Steve Heyns http://customgothic.com/
  3197. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3198. * @version $Id: CViewRenderer.php 2799 2011-01-01 19:31:13Z qiang.xue $
  3199. * @package system.web.renderers
  3200. * @since 1.0
  3201. * @author Charles Pick
  3202. * @class
  3203. * @extends Yii.CApplicationComponent
  3204. */
  3205. Yii.CViewRenderer = function CViewRenderer () {
  3206. };
  3207. Yii.CViewRenderer.prototype = new Yii.CApplicationComponent();
  3208. Yii.CViewRenderer.prototype.constructor = Yii.CViewRenderer;
  3209. /**
  3210. * @var {String} the extension name of the view file. Defaults to '.html'.
  3211. * @since 1.0.9
  3212. */
  3213. Yii.CViewRenderer.prototype.fileExtension = '.html';
  3214. /**
  3215. * Renders a view file.
  3216. * @param {Yii.CBaseController} context the controller or widget who is rendering the view file.
  3217. * @param {String} sourceFile the view file path
  3218. * @param {Mixed} data the data to be passed to the view
  3219. * @param {Boolean} returnVar whether the rendering result should be returned
  3220. * @returns {Mixed} the rendering result, or null if the rendering result is not needed.
  3221. */
  3222. Yii.CViewRenderer.prototype.renderFile = function (context, sourceFile, data, returnVar) {
  3223. var file, viewFile;
  3224. viewFile=this.getViewFile(sourceFile);
  3225. return context.renderInternal(viewFile,data,returnVar);
  3226. };
  3227. /**
  3228. * Generates the resulting view file path.
  3229. * @param {String} file source view file path
  3230. * @returns {String} resulting view file path
  3231. */
  3232. Yii.CViewRenderer.prototype.getViewFile = function (file) {
  3233. return file;
  3234. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3235. /**
  3236. * CFormElement is the base class for presenting all kinds of form element.
  3237. *
  3238. * CFormElement implements the way to get and set arbitrary attributes.
  3239. *
  3240. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3241. * @version $Id: CFormElement.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  3242. * @package system.web.form
  3243. * @since 1.1
  3244. * @author Charles Pick
  3245. * @class
  3246. * @extends Yii.CComponent
  3247. */
  3248. Yii.CFormElement = function CFormElement (config, parent) {
  3249. if (config !== false) {
  3250. this.construct(config, parent);
  3251. }
  3252. };
  3253. Yii.CFormElement.prototype = new Yii.CComponent();
  3254. Yii.CFormElement.prototype.constructor = Yii.CFormElement;
  3255. /**
  3256. * @var {Array} list of attributes (name=>value) for the HTML element represented by this object.
  3257. */
  3258. Yii.CFormElement.prototype.attributes = {};
  3259. Yii.CFormElement.prototype._parent = null;
  3260. Yii.CFormElement.prototype._visible = null;
  3261. /**
  3262. * Renders this element.
  3263. * @returns {String} the rendering result
  3264. */
  3265. Yii.CFormElement.prototype.render = function () {
  3266. };
  3267. /**
  3268. * Constructor.
  3269. * @param {Mixed} config the configuration for this element.
  3270. * @param {Mixed} parent the direct parent of this element.
  3271. * @see configure
  3272. */
  3273. Yii.CFormElement.prototype.construct = function (config, parent) {
  3274. this.configure(config);
  3275. this._parent=parent;
  3276. };
  3277. /**
  3278. * Converts the object to a string.
  3279. * This is a PHP magic method.
  3280. * The default implementation simply calls {@link render} and return
  3281. * the rendering result.
  3282. * @returns {String} the string representation of this object.
  3283. */
  3284. Yii.CFormElement.prototype.toString = function () {
  3285. return this.render();
  3286. };
  3287. /**
  3288. * Returns a property value or an attribute value.
  3289. * Do not call this method. This is a PHP magic method that we override
  3290. * to allow using the following syntax to read a property or attribute:
  3291. * <pre>
  3292. * value=element.propertyName;
  3293. * value=element.attributeName;
  3294. * </pre>
  3295. * @param {String} name the property or attribute name
  3296. * @returns {Mixed} the property or attribute value
  3297. * @throws {Yii.CException} if the property or attribute is not defined
  3298. * @see __set
  3299. */
  3300. Yii.CFormElement.prototype.get = function (name) {
  3301. var getter;
  3302. getter='get'+php.ucfirst(name);
  3303. if(php.method_exists(this,getter)) {
  3304. return this[getter]();
  3305. }
  3306. else if(this.attributes[name] !== undefined) {
  3307. return this.attributes[name];
  3308. }
  3309. else {
  3310. throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is not defined.',
  3311. {'{class}':this.getClassName(), '{property}':name}));
  3312. }
  3313. };
  3314. /**
  3315. * Sets value of a property or attribute.
  3316. * Do not call this method. This is a PHP magic method that we override
  3317. * to allow using the following syntax to set a property or attribute.
  3318. * <pre>
  3319. * this.propertyName=value;
  3320. * this.attributeName=value;
  3321. * </pre>
  3322. * @param {String} name the property or attribute name
  3323. * @param {Mixed} value the property or attribute value
  3324. * @see __get
  3325. */
  3326. Yii.CFormElement.prototype.set = function (name, value) {
  3327. var setter;
  3328. setter='set'+php.ucfirst(name);
  3329. if(php.method_exists(this,setter)) {
  3330. this[setter](value);
  3331. }
  3332. else if (this[name] !== undefined) {
  3333. this[name] = value;
  3334. }
  3335. else {
  3336. this.attributes[name]=value;
  3337. }
  3338. };
  3339. /**
  3340. * Configures this object with property initial values.
  3341. * @param {Mixed} config the configuration for this object. This can be an array
  3342. * representing the property names and their initial values.
  3343. * It can also be a string representing the file name of the PHP script
  3344. * that returns a configuration array.
  3345. */
  3346. Yii.CFormElement.prototype.configure = function (config) {
  3347. var name, value;
  3348. for (name in config) {
  3349. if (config.hasOwnProperty(name)) {
  3350. value = config[name];
  3351. this.set(name,value);
  3352. }
  3353. }
  3354. };
  3355. /**
  3356. * Returns a value indicating whether this element is visible and should be rendered.
  3357. * This method will call {@link evaluateVisible} to determine the visibility of this element.
  3358. * @returns {Boolean} whether this element is visible and should be rendered.
  3359. */
  3360. Yii.CFormElement.prototype.getVisible = function () {
  3361. if(this._visible===null) {
  3362. this._visible=this.evaluateVisible();
  3363. }
  3364. return this._visible;
  3365. };
  3366. /**
  3367. * @param {Boolean} value whether this element is visible and should be rendered.
  3368. */
  3369. Yii.CFormElement.prototype.setVisible = function (value) {
  3370. this._visible=value;
  3371. };
  3372. /**
  3373. * @returns {Mixed} the direct parent of this element. This could be either a {@link CForm} object or a {@link CBaseController} object
  3374. * (a controller or a widget).
  3375. */
  3376. Yii.CFormElement.prototype.getParent = function () {
  3377. return this._parent;
  3378. };
  3379. /**
  3380. * Evaluates the visibility of this element.
  3381. * Child classes should override this method to implement the actual algorithm
  3382. * for determining the visibility.
  3383. * @returns {Boolean} whether this element is visible. Defaults to true.
  3384. */
  3385. Yii.CFormElement.prototype.evaluateVisible = function () {
  3386. return true;
  3387. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3388. /**
  3389. * CBaseController is the base class for {@link CController} and {@link CWidget}.
  3390. *
  3391. * It provides the common functionalities shared by controllers who need to render views.
  3392. *
  3393. * CBaseController also implements the support for the following features:
  3394. * <ul>
  3395. * <li>{@link CClipWidget Clips} : a clip is a piece of captured output that can be inserted elsewhere.</li>
  3396. * <li>{@link CWidget Widgets} : a widget is a self-contained sub-controller with its own view and model.</li>
  3397. * <li>{@link COutputCache Fragment cache} : fragment cache selectively caches a portion of the output.</li>
  3398. * </ul>
  3399. *
  3400. * To use a widget in a view, use the following in the view:
  3401. * <pre>
  3402. * this.widget('path.to.widgetClass',{'property1':'value1',+++});
  3403. * </pre>
  3404. * or
  3405. * <pre>
  3406. * this.beginWidget('path.to.widgetClass',{'property1':'value1',+++});
  3407. * // ... display other contents here
  3408. * this.endWidget();
  3409. * </pre>
  3410. *
  3411. * To create a clip, use the following:
  3412. * <pre>
  3413. * this.beginClip('clipID');
  3414. * // ... display the clip contents
  3415. * this.endClip();
  3416. * </pre>
  3417. * Then, in a different view or place, the captured clip can be inserted as:
  3418. * <pre>
  3419. * document.write(this.clips['clipID']);
  3420. * </pre>
  3421. *
  3422. * To use fragment cache, do as follows,
  3423. * <pre>
  3424. * if(this.beginCache('cacheID',{'property1':'value1',+++})
  3425. * {
  3426. * // ... display the content to be cached here
  3427. * this.endCache();
  3428. * }
  3429. * </pre>
  3430. *
  3431. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3432. * @version $Id: CBaseController.php 2799 2011-01-01 19:31:13Z qiang.xue $
  3433. * @package system.web
  3434. * @since 1.0
  3435. * @author Charles Pick
  3436. * @class
  3437. * @extends Yii.CComponent
  3438. */
  3439. Yii.CBaseController = function CBaseController() {
  3440. };
  3441. Yii.CBaseController.prototype = new Yii.CComponent();
  3442. Yii.CBaseController.prototype.constructor = Yii.CBaseController;
  3443. Yii.CBaseController.prototype._widgetStack = [];
  3444. /**
  3445. * Returns the view script file according to the specified view name.
  3446. * This method must be implemented by child classes.
  3447. * @param {String} viewName view name
  3448. * @returns {String} the file path for the named view. False if the view cannot be found.
  3449. */
  3450. Yii.CBaseController.prototype.getViewFile = function (viewName) {
  3451. };
  3452. /**
  3453. * Renders a view file.
  3454. *
  3455. * @param {String} viewFile view file path
  3456. * @param {Array} data data to be extracted and made available to the view
  3457. * @param {Function} callback The callback to execute
  3458. * @throws {Yii.CException} if the view file does not exist
  3459. */
  3460. Yii.CBaseController.prototype.renderFile = function (viewFile, data, callback) {
  3461. var renderer;
  3462. if (data === undefined) {
  3463. data = null;
  3464. }
  3465. if((renderer=Yii.app().getViewRenderer())!==undefined && renderer.fileExtension==='.'+(viewFile.split(".").pop())) {
  3466. return renderer.renderFile(this,viewFile,data,callback);
  3467. }
  3468. else {
  3469. return this.renderInternal(viewFile,data,callback);
  3470. }
  3471. };
  3472. /**
  3473. * Renders a view file.
  3474. * This method includes the view file as a JavaScript script
  3475. * and captures the display result if required.
  3476. * @param {String} viewFile view file
  3477. * @param {Array} data data to be extracted and made available to the view file
  3478. * @param {Function} callback The callback to execute with the rendering result
  3479. * @returns {String} the rendering result. Null if the rendering result is not required.
  3480. */
  3481. Yii.CBaseController.prototype.renderInternal = function (_viewFile_, _data_, _callback_) {
  3482. var data;
  3483. if (_data_ === undefined) {
  3484. _data_ = null;
  3485. }
  3486. return Yii.include(_viewFile_,true, _callback_);
  3487. };
  3488. /**
  3489. * Creates a widget and initializes it.
  3490. * This method first creates the specified widget instance.
  3491. * It then configures the widget's properties with the given initial values.
  3492. * At the end it calls {@link CWidget::init} to initialize the widget.
  3493. * Starting from version 1.1, if a {@link CWidgetFactory widget factory} is enabled,
  3494. * this method will use the factory to create the widget, instead.
  3495. * @param {String} className class name (can be in path alias format)
  3496. * @param {Array} properties initial property values
  3497. * @returns {Yii.CWidget} the fully initialized widget instance.
  3498. */
  3499. Yii.CBaseController.prototype.createWidget = function (className, properties) {
  3500. var widget;
  3501. if (properties === undefined) {
  3502. properties = [];
  3503. }
  3504. widget=Yii.app().getWidgetFactory().createWidget(this,className,properties);
  3505. widget.init();
  3506. return widget;
  3507. };
  3508. /**
  3509. * Creates a widget and executes it.
  3510. * @param {String} className the widget class name or class in dot syntax (e.g. application.widgets.MyWidget)
  3511. * @param {Array} properties list of initial property values for the widget (Property Name => Property Value)
  3512. * @param {Boolean} captureOutput whether to capture the output of the widget. If true, the method will capture
  3513. * and return the output generated by the widget. If false, the output will be directly sent for display
  3514. * and the widget object will be returned. This parameter is available since version 1.1.2.
  3515. * @returns {Mixed} the widget instance when $captureOutput is false, or the widget output when $captureOutput is true.
  3516. */
  3517. Yii.CBaseController.prototype.widget = function (className, properties, captureOutput) {
  3518. var widget;
  3519. if (properties === undefined) {
  3520. properties = [];
  3521. }
  3522. widget=this.createWidget(className,properties);
  3523. return(widget.run());
  3524. };
  3525. /**
  3526. * Creates a widget and executes it.
  3527. * This method is similar to {@link widget()} except that it is expecting
  3528. * a {@link endWidget()} call to end the execution.
  3529. * @param {String} className the widget class name or class in dot syntax (e.g. application.widgets.MyWidget)
  3530. * @param {Array} properties list of initial property values for the widget (Property Name => Property Value)
  3531. * @returns {Yii.CWidget} the widget created to run
  3532. * @see endWidget
  3533. */
  3534. Yii.CBaseController.prototype.beginWidget = function (className, properties) {
  3535. var widget;
  3536. if (properties === undefined) {
  3537. properties = [];
  3538. }
  3539. widget=this.createWidget(className,properties);
  3540. this._widgetStack.push(widget);
  3541. return widget;
  3542. };
  3543. /**
  3544. * Ends the execution of the named widget.
  3545. * This method is used together with {@link beginWidget()}.
  3546. * @param {String} id optional tag identifying the method call for debugging purpose.
  3547. * @returns {Yii.CWidget} the widget just ended running
  3548. * @throws {Yii.CException} if an extra endWidget call is made
  3549. * @see beginWidget
  3550. */
  3551. Yii.CBaseController.prototype.endWidget = function (id) {
  3552. var widget;
  3553. if (id === undefined) {
  3554. id = '';
  3555. }
  3556. if((widget=php.array_pop(this._widgetStack))!==null)
  3557. {
  3558. widget.run();
  3559. return widget;
  3560. }
  3561. else {
  3562. throw new Yii.CException(Yii.t('yii','{controller} has an extra endWidget({id}) call in its view.',
  3563. {'{controller}':php.get_class(this),'{id}':id}));
  3564. }
  3565. };
  3566. /**
  3567. * Begins recording a clip.
  3568. * This method is a shortcut to beginning {@link CClipWidget}.
  3569. * @param {String} id the clip ID.
  3570. * @param {Array} properties initial property values for {@link CClipWidget}.
  3571. */
  3572. Yii.CBaseController.prototype.beginClip = function (id, properties) {
  3573. if (properties === undefined) {
  3574. properties = [];
  3575. }
  3576. properties.id=id;
  3577. this.beginWidget('CClipWidget',properties);
  3578. };
  3579. /**
  3580. * Ends recording a clip.
  3581. * This method is an alias to {@link endWidget}.
  3582. */
  3583. Yii.CBaseController.prototype.endClip = function () {
  3584. this.endWidget('CClipWidget');
  3585. };
  3586. /**
  3587. * Begins fragment caching.
  3588. * This method will display cached content if it is availabe.
  3589. * If not, it will start caching and would expect a {@link endCache()}
  3590. * call to end the cache and save the content into cache.
  3591. * A typical usage of fragment caching is as follows,
  3592. * <pre>
  3593. * if(this.beginCache(id))
  3594. * {
  3595. * // ...generate content here
  3596. * this.endCache();
  3597. * }
  3598. * </pre>
  3599. * @param {String} id a unique ID identifying the fragment to be cached.
  3600. * @param {Array} properties initial property values for {@link COutputCache}.
  3601. * @returns {Boolean} whether we need to generate content for caching. False if cached version is available.
  3602. * @see endCache
  3603. */
  3604. Yii.CBaseController.prototype.beginCache = function (id, properties) {
  3605. var cache;
  3606. if (properties === undefined) {
  3607. properties = [];
  3608. }
  3609. properties.id=id;
  3610. cache=this.beginWidget('COutputCache',properties);
  3611. if(cache.getIsContentCached())
  3612. {
  3613. this.endCache();
  3614. return false;
  3615. }
  3616. else {
  3617. return true;
  3618. }
  3619. };
  3620. /**
  3621. * Ends fragment caching.
  3622. * This is an alias to {@link endWidget}.
  3623. * @see beginCache
  3624. */
  3625. Yii.CBaseController.prototype.endCache = function () {
  3626. this.endWidget('COutputCache');
  3627. };
  3628. /**
  3629. * Begins the rendering of content that is to be decorated by the specified view.
  3630. * @param {Mixed} view the name of the view that will be used to decorate the content. The actual view script
  3631. * is resolved via {@link getViewFile}. If this parameter is null (default),
  3632. * the default layout will be used as the decorative view.
  3633. * Note that if the current controller does not belong to
  3634. * any module, the default layout refers to the application's {@link CWebApplication::layout default layout};
  3635. * If the controller belongs to a module, the default layout refers to the module's
  3636. * {@link CWebModule::layout default layout}.
  3637. * @param {Object} data the variables (name=>value) to be extracted and made available in the decorative view.
  3638. * This parameter has been available since version 1.0.4
  3639. * @see beginContent
  3640. * @see CContentDecorator
  3641. */
  3642. Yii.CBaseController.prototype.beginContent = function (view, data) {
  3643. if (view === undefined) {
  3644. view = null;
  3645. }
  3646. if (data === undefined) {
  3647. data = {};
  3648. }
  3649. this.beginWidget('CContentDecorator',{'view':view, 'data':data});
  3650. };
  3651. /**
  3652. * Ends the rendering of content.
  3653. * @see beginContent
  3654. */
  3655. Yii.CBaseController.prototype.endContent = function () {
  3656. this.endWidget('CContentDecorator');
  3657. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3658. /**
  3659. * CWidget is the base class for widgets.
  3660. *
  3661. * A widget is a self-contained component that may generate presentation
  3662. * based on model data. It can be viewed as a micro-controller that embeds
  3663. * into the controller-managed views.
  3664. *
  3665. * Compared with {@link CController controller}, a widget has neither actions nor filters.
  3666. *
  3667. * Usage is described at {@link CBaseController} and {@link CBaseController::widget}.
  3668. *
  3669. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3670. * @version $Id: CWidget.php 3097 2011-03-17 20:01:03Z qiang.xue $
  3671. * @package system.web.widgets
  3672. * @since 1.0
  3673. * @author Charles Pick
  3674. * @class
  3675. * @extends Yii.CBaseController
  3676. */
  3677. Yii.CWidget = function CWidget() {
  3678. };
  3679. Yii.CWidget.prototype = new Yii.CBaseController();
  3680. Yii.CWidget.prototype.constructor = Yii.CWidget;
  3681. /**
  3682. * @var {String} the prefix to the IDs of the {@link actions}.
  3683. * When a widget is declared an action provider in {@link CController::actions},
  3684. * a prefix can be specified to differentiate its action IDs from others.
  3685. * The same prefix should then also be used to configure this property
  3686. * when the widget is used in a view of the controller.
  3687. * @since 1.0.1
  3688. */
  3689. Yii.CWidget.prototype.actionPrefix = null;
  3690. /**
  3691. * @var {Mixed} the name of the skin to be used by this widget. Defaults to 'default'.
  3692. * If this is set as false, no skin will be applied to this widget.
  3693. * @see CWidgetFactory
  3694. * @since 1.1
  3695. */
  3696. Yii.CWidget.prototype.skin = 'default';
  3697. /**
  3698. * @var {Object} view paths for different types of widgets
  3699. */
  3700. Yii.CWidget.prototype._viewPaths = {};
  3701. /**
  3702. * @var {Integer} the counter for generating implicit IDs.
  3703. */
  3704. Yii.CWidget.prototype._counter = 0;
  3705. /**
  3706. * @var {String} id of the widget.
  3707. */
  3708. Yii.CWidget.prototype._id = null;
  3709. /**
  3710. * @var {Yii.CBaseController} owner/creator of this widget. It could be either a widget or a controller.
  3711. */
  3712. Yii.CWidget.prototype._owner = null;
  3713. /**
  3714. * Returns a list of actions that are used by this widget.
  3715. * The structure of this method's return value is similar to
  3716. * that returned by {@link CController::actions}.
  3717. *
  3718. * When a widget uses several actions, you can declare these actions using
  3719. * this method. The widget will then become an action provider, and the actions
  3720. * can be easily imported into a controller.
  3721. *
  3722. * Note, when creating URLs referring to the actions listed in this method,
  3723. * make sure the action IDs are prefixed with {@link actionPrefix}.
  3724. *
  3725. * @see actionPrefix
  3726. * @see CController::actions
  3727. * @since 1.0.1
  3728. */
  3729. Yii.CWidget.prototype.actions = function () {
  3730. return [];
  3731. };
  3732. /**
  3733. * Constructor.
  3734. * @param {Yii.CBaseController} owner owner/creator of this widget. It could be either a widget or a controller.
  3735. */
  3736. Yii.CWidget.prototype.construct = function (owner) {
  3737. if (owner === undefined) {
  3738. owner = null;
  3739. }
  3740. this._owner=owner===null?Yii.app().getController():owner;
  3741. };
  3742. /**
  3743. * Returns the owner/creator of this widget.
  3744. * @returns {Yii.CBaseController} owner/creator of this widget. It could be either a widget or a controller.
  3745. */
  3746. Yii.CWidget.prototype.getOwner = function () {
  3747. return this._owner;
  3748. };
  3749. /**
  3750. * Returns the ID of the widget or generates a new one if requested.
  3751. * @param {Boolean} autoGenerate whether to generate an ID if it is not set previously
  3752. * @returns {String} id of the widget.
  3753. */
  3754. Yii.CWidget.prototype.getId = function (autoGenerate) {
  3755. var _counter;
  3756. if (autoGenerate === undefined) {
  3757. autoGenerate = true;
  3758. }
  3759. if(this._id!==null) {
  3760. return this._id;
  3761. }
  3762. else if(autoGenerate) {
  3763. return (this._id='yw'+Yii.CWidget.prototype._counter++);
  3764. }
  3765. };
  3766. /**
  3767. * Sets the ID of the widget.
  3768. * @param {String} value id of the widget.
  3769. */
  3770. Yii.CWidget.prototype.setId = function (value) {
  3771. this._id=value;
  3772. };
  3773. /**
  3774. * Returns the controller that this widget belongs to.
  3775. * @returns {Yii.CController} the controller that this widget belongs to.
  3776. */
  3777. Yii.CWidget.prototype.getController = function () {
  3778. if(this._owner instanceof Yii.CController) {
  3779. return this._owner;
  3780. }
  3781. else {
  3782. return Yii.app().getController();
  3783. }
  3784. };
  3785. /**
  3786. * Initializes the widget.
  3787. * This method is called by {@link CBaseController::createWidget}
  3788. * and {@link CBaseController::beginWidget} after the widget's
  3789. * properties have been initialized.
  3790. */
  3791. Yii.CWidget.prototype.init = function () {
  3792. };
  3793. /**
  3794. * Executes the widget.
  3795. * This method is called by {@link CBaseController::endWidget}.
  3796. */
  3797. Yii.CWidget.prototype.run = function () {
  3798. };
  3799. /**
  3800. * Returns the directory containing the view files for this widget.
  3801. * The default implementation returns the 'views' subdirectory of the directory containing the widget class file.
  3802. * If $checkTheme is set true, the directory "ThemeID/views/ClassName" will be returned when it exists.
  3803. * @param {Boolean} checkTheme whether to check if the theme contains a view path for the widget.
  3804. * @returns {String} the directory containing the view files for this widget.
  3805. */
  3806. Yii.CWidget.prototype.getViewPath = function (checkTheme) {
  3807. var className, _viewPaths, theme, path, viewFolder, pathParts;
  3808. if (checkTheme === undefined) {
  3809. checkTheme = false;
  3810. }
  3811. className=php.get_class(this);
  3812. if(Yii.CWidget.prototype._viewPaths[className] !== undefined) {
  3813. return Yii.CWidget.prototype._viewPaths[className];
  3814. }
  3815. else
  3816. {
  3817. if(checkTheme && (theme=Yii.app().getTheme())!==null) {
  3818. path=theme.getViewPath()+"/";
  3819. path+=className;
  3820. return (Yii.CWidget.prototype._viewPaths[className]=path);
  3821. }
  3822. viewFolder = php.rtrim(Yii.app().getBasePath(),"/") + '/views/widgets/';
  3823. return (Yii.CWidget.prototype._viewPaths[className]=viewFolder + className);
  3824. }
  3825. };
  3826. /**
  3827. * Looks for the view script file according to the view name.
  3828. * This method will look for the view under the widget's {@link getViewPath viewPath}.
  3829. * The view script file is named as "ViewName.php". A localized view file
  3830. * may be returned if internationalization is needed. See {@link CApplication::findLocalizedFile}
  3831. * for more details.
  3832. * Since version 1.0.2, the view name can also refer to a path alias
  3833. * if it contains dot characters.
  3834. * @param {String} viewName name of the view (without file extension)
  3835. * @returns {String} the view file path. False if the view file does not exist
  3836. * @see CApplication::findLocalizedFile
  3837. */
  3838. Yii.CWidget.prototype.getViewFile = function (viewName) {
  3839. var renderer, extension, viewFile;
  3840. if((renderer=Yii.app().getViewRenderer())!==undefined) {
  3841. extension=renderer.fileExtension;
  3842. }
  3843. else {
  3844. extension='.js';
  3845. }
  3846. if(php.strpos(viewName,'.')) { // a path alias
  3847. viewFile=Yii.getPathOfAlias(viewName);
  3848. }
  3849. else {
  3850. viewFile=this.getViewPath(true)+'/'+viewName;
  3851. return Yii.app().findLocalizedFile(viewFile+extension);
  3852. }
  3853. if(is_file(viewFile+extension)) {
  3854. return Yii.app().findLocalizedFile(viewFile+extension);
  3855. }
  3856. else if(extension!=='.js' && is_file(viewFile+'.js')) {
  3857. return Yii.app().findLocalizedFile(viewFile+'.js');
  3858. }
  3859. else {
  3860. return false;
  3861. }
  3862. };
  3863. /**
  3864. * Renders a view.
  3865. *
  3866. * The named view refers to a PHP script (resolved via {@link getViewFile})
  3867. * that is included by this method. If $data is an associative array,
  3868. * it will be extracted as PHP variables and made available to the script.
  3869. *
  3870. * @param {String} view name of the view to be rendered. See {@link getViewFile} for details
  3871. * about how the view script is resolved.
  3872. * @param {Array} data data to be extracted into PHP variables and made available to the view script
  3873. * @param {Boolean} returnVar whether the rendering result should be returned instead of being displayed to end users
  3874. * @returns {String} the rendering result. Null if the rendering result is not required.
  3875. * @throws {Yii.CException} if the view does not exist
  3876. * @see getViewFile
  3877. */
  3878. Yii.CWidget.prototype.render = function (view, data, returnVar) {
  3879. var viewFile;
  3880. if (data === undefined) {
  3881. data = null;
  3882. }
  3883. if (returnVar === undefined) {
  3884. returnVar = false;
  3885. }
  3886. if((viewFile=this.getViewFile(view))!==false) {
  3887. return this.renderFile(viewFile,data,returnVar);
  3888. }
  3889. else {
  3890. throw new Yii.CException(Yii.t('yii','{widget} cannot find the view "{view}".',
  3891. {'{widget}':php.get_class(this), '{view}':view}));
  3892. }
  3893. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3894. /**
  3895. * CLogRoute is the base class for all log route classes.
  3896. *
  3897. * A log route object retrieves log messages from a logger and sends it
  3898. * somewhere, such as files, emails.
  3899. * The messages being retrieved may be filtered first before being sent
  3900. * to the destination. The filters include log level filter and log category filter.
  3901. *
  3902. * To specify level filter, set {@link levels} property,
  3903. * which takes a string of comma-separated desired level names (e.g. 'Error, Debug').
  3904. * To specify category filter, set {@link categories} property,
  3905. * which takes a string of comma-separated desired category names (e.g. 'System.Web, System.IO').
  3906. *
  3907. * Level filter and category filter are combinational, i.e., only messages
  3908. * satisfying both filter conditions will they be returned.
  3909. *
  3910. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  3911. * @version $Id: CLogRoute.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  3912. * @package system.logging
  3913. * @since 1.0
  3914. * @author Charles Pick
  3915. * @class
  3916. * @extends Yii.CComponent
  3917. */
  3918. Yii.CLogRoute = function CLogRoute () {
  3919. };
  3920. Yii.CLogRoute.prototype = new Yii.CComponent();
  3921. Yii.CLogRoute.prototype.constructor = Yii.CLogRoute;
  3922. /**
  3923. * @var {Boolean} whether to enable this log route. Defaults to true.
  3924. * @since 1.0.7
  3925. */
  3926. Yii.CLogRoute.prototype.enabled = true;
  3927. /**
  3928. * @var {String} list of levels separated by comma or space. Defaults to empty, meaning all levels.
  3929. */
  3930. Yii.CLogRoute.prototype.levels = '';
  3931. /**
  3932. * @var {String} list of categories separated by comma or space. Defaults to empty, meaning all categories.
  3933. */
  3934. Yii.CLogRoute.prototype.categories = '';
  3935. /**
  3936. * @var {Mixed} the additional filter (eg {@link CLogFilter}) that can be applied to the log messages.
  3937. * The value of this property will be passed to {@link Yii::createComponent} to create
  3938. * a log filter object. As a result, this can be either a string representing the
  3939. * filter class name or an array representing the filter configuration.
  3940. * In general, the log filter class should be {@link CLogFilter} or a child class of it.
  3941. * Defaults to null, meaning no filter will be used.
  3942. * @since 1.0.6
  3943. */
  3944. Yii.CLogRoute.prototype.filter = null;
  3945. /**
  3946. * @var {Array} the logs that are collected so far by this log route.
  3947. * @since 1.1.0
  3948. */
  3949. Yii.CLogRoute.prototype.logs = null;
  3950. /**
  3951. * Initializes the route.
  3952. * This method is invoked after the route is created by the route manager.
  3953. */
  3954. Yii.CLogRoute.prototype.init = function () {
  3955. };
  3956. /**
  3957. * Formats a log message given different fields.
  3958. * @param {String} message message content
  3959. * @param {Integer} level message level
  3960. * @param {String} category message category
  3961. * @param {Integer} time timestamp
  3962. * @returns {String} formatted message
  3963. */
  3964. Yii.CLogRoute.prototype.formatLogMessage = function (message, level, category, time) {
  3965. return php.date('Y/m/d H:i:s',time)+" [" + level + "] [" + category + "] " + message + "\n";
  3966. };
  3967. /**
  3968. * Retrieves filtered log messages from logger for further processing.
  3969. * @param {Yii.CLogger} logger logger instance
  3970. * @param {Boolean} processLogs whether to process the logs after they are collected from the logger
  3971. */
  3972. Yii.CLogRoute.prototype.collectLogs = function (logger, processLogs) {
  3973. var logs;
  3974. if (processLogs === undefined) {
  3975. processLogs = false;
  3976. }
  3977. logs=logger.getLogs(this.levels,this.categories);
  3978. this.logs=php.empty(this.logs) ? logs : php.array_merge(this.logs,logs);
  3979. if(processLogs && !php.empty(this.logs)) {
  3980. if(this.filter!==null) {
  3981. Yii.createComponent(this.filter).filter(this.logs);
  3982. }
  3983. this.processLogs(this.logs);
  3984. }
  3985. };
  3986. /**
  3987. * Processes log messages and sends them to specific destination.
  3988. * Derived child classes must implement this method.
  3989. * @param {Array} logs list of messages. Each array elements represents one message
  3990. * with the following structure:
  3991. * array(
  3992. * [0] => message (string)
  3993. * [1] => level (string)
  3994. * [2] => category (string)
  3995. * [3] => timestamp (float, obtained by microtime(true));
  3996. */
  3997. Yii.CLogRoute.prototype.processLogs = function (logs) {
  3998. };/*global Yii, php, $, jQuery, console, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  3999. /**
  4000. * CWebLogRoute shows the log content in Web page.
  4001. *
  4002. * The log content can appear either at the end of the current Web page
  4003. * or in FireBug console window (if {@link showInFireBug} is set true).
  4004. *
  4005. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  4006. * @version $Id: CWebLogRoute.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  4007. * @package system.logging
  4008. * @since 1.0
  4009. * @author Charles Pick
  4010. * @class
  4011. * @extends Yii.CLogRoute
  4012. */
  4013. Yii.CWebLogRoute = function CWebLogRoute () {
  4014. };
  4015. Yii.CWebLogRoute.prototype = new Yii.CLogRoute();
  4016. Yii.CWebLogRoute.prototype.constructor = Yii.CWebLogRoute;
  4017. /**
  4018. * @var {Boolean} whether the log should be displayed in FireBug instead of browser window. Defaults to false.
  4019. */
  4020. Yii.CWebLogRoute.prototype.showInFireBug = false;
  4021. /**
  4022. * @var {Boolean} whether the log should be ignored in FireBug for ajax calls. Defaults to true.
  4023. * This option should be used carefully, because an ajax call returns all output as a result data.
  4024. * For example if the ajax call expects a json type result any output from the logger will cause ajax call to fail.
  4025. */
  4026. Yii.CWebLogRoute.prototype.ignoreAjaxInFireBug = true;
  4027. /**
  4028. * Displays the log messages.
  4029. * @param {Array} logs list of log messages
  4030. */
  4031. Yii.CWebLogRoute.prototype.processLogs = function (logs) {
  4032. var logView = [], i, limit, log;
  4033. limit = logs.length;
  4034. for (i = 0; i < limit; i++) {
  4035. log = logs[i];
  4036. logView.push({
  4037. 'time': php.date('H:i:s.',log[3]) + php.sprintf('%06d',Number((log[3]-Number(log[3]))*1000000)),
  4038. 'level': log[1],
  4039. 'category': log[2],
  4040. 'message': log[0]
  4041. });
  4042. }
  4043. if (this.showInFireBug) {
  4044. if (console.group !== undefined) {
  4045. console.group("Application Log");
  4046. }
  4047. Yii.forEach(logView, function (index, log) {
  4048. var func;
  4049. if (log[1] === Yii.CLogger.prototype.LEVEL_WARNING) {
  4050. func = "warn";
  4051. }
  4052. else if (log[2] === Yii.CLogger.prototype.LEVEL_ERROR) {
  4053. func = "error";
  4054. }
  4055. else {
  4056. func = "log";
  4057. }
  4058. if (console[func] === undefined) {
  4059. func = "log";
  4060. }
  4061. console[func]("[" + log.time + "] [" + log.level + "] [" + log.category + "] " + log.message);
  4062. });
  4063. if (console.group !== undefined) {
  4064. console.groupEnd();
  4065. }
  4066. }
  4067. else {
  4068. this.render('log',logView);
  4069. }
  4070. };
  4071. /**
  4072. * Renders the view.
  4073. * @param {String} view the view name (file name without extension). The file is assumed to be located under framework/data/views.
  4074. * @param {Array} data data to be passed to the view
  4075. */
  4076. Yii.CWebLogRoute.prototype.render = function (view, data) {
  4077. var app, isAjax, viewFile;
  4078. app=Yii.app();
  4079. isAjax=app.getRequest().getIsAjaxRequest();
  4080. if(this.showInFireBug) {
  4081. if(isAjax && this.ignoreAjaxInFireBug) {
  4082. return;
  4083. }
  4084. view+='-firebug';
  4085. }
  4086. else if(!(app instanceof Yii.CWebApplication) || isAjax) {
  4087. return;
  4088. }
  4089. viewFile='system.views.'+view;
  4090. jQuery("body").append(Yii.CController.prototype.renderPartial(viewFile, {data: data},true));
  4091. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  4092. /**
  4093. * CView is a base class for views
  4094. *
  4095. * @package system.web
  4096. * @since 1.0
  4097. * @author Charles Pick
  4098. * @class
  4099. * @extends Yii.CComponent
  4100. */
  4101. Yii.CView = function CView (config) {
  4102. if (config !== false) {
  4103. this.template = null;
  4104. this.construct(config);
  4105. }
  4106. };
  4107. Yii.CView.prototype = new Yii.CComponent();
  4108. Yii.CView.prototype.constructor = Yii.CView;
  4109. /**
  4110. * Holds a list of registered views
  4111. */
  4112. Yii.CView.prototype._views = {};
  4113. /**
  4114. * Holds a list of cached templates
  4115. * @var Object
  4116. */
  4117. Yii.CView.prototype._templates = {};
  4118. /**
  4119. * The content of the template that should be used to render this view
  4120. * @var String
  4121. */
  4122. Yii.CView.prototype.template = null;
  4123. /**
  4124. * The URL of the template to use for this view.
  4125. * @var String
  4126. */
  4127. Yii.CView.prototype.templateURL = null;
  4128. /**
  4129. * The layout view to use when rendering, if none specified
  4130. * the default layout will be used.
  4131. * @var Yii.CView
  4132. */
  4133. Yii.CView.prototype.layout = null;
  4134. /**
  4135. * jQuery events to delegate for this view.
  4136. * Array should be of the following format:
  4137. * <pre>
  4138. * [
  4139. * ['#selector a.someLink', 'click', function (e) { alert("clicked!")}],
  4140. * ['#selector form', 'submit', function (e) { alert('Submitted!'); e.preventDefault(); }]
  4141. * ]
  4142. * </pre>
  4143. * These events will be bound to their selectors when the view is rendered
  4144. * @var Array
  4145. */
  4146. Yii.CView.prototype.delegates = [];
  4147. /**
  4148. * Registers a view that can be rendered later
  4149. * @param {String} alias The alias for this view so it can be retrieved later
  4150. * @param {Object} config An object that will be used as a configuration for a new CView
  4151. */
  4152. Yii.CView.prototype.registerView = function (alias, config) {
  4153. var url;
  4154. if (alias.indexOf("/") === -1) {
  4155. url = Yii.getPathOfAlias(alias) + ".js";
  4156. }
  4157. else {
  4158. url = alias;
  4159. }
  4160. Yii.CView.prototype._views[url] = config;
  4161. };
  4162. /**
  4163. * Loads a particular view and executes the callback
  4164. * @param {String} alias The alias of the view to load
  4165. * @param {Function} callback The callback to execute, it will receive the loaded view as first parameter
  4166. */
  4167. Yii.CView.prototype.load = function (alias, callback) {
  4168. var config, view, className, url;
  4169. if (alias.indexOf("/") === -1) {
  4170. url = Yii.getPathOfAlias(alias) + ".js";
  4171. }
  4172. else {
  4173. url = alias;
  4174. }
  4175. config = Yii.CView.prototype._views[url];
  4176. if (config === undefined) {
  4177. // load the view
  4178. Yii.include(url, true, function() {
  4179. config = Yii.CView.prototype._views[url];
  4180. if (config === undefined) {
  4181. throw new Yii.CHttpException(404, "No such view: " + url);
  4182. }
  4183. if (config['class'] === undefined) {
  4184. className = "CView";
  4185. }
  4186. else {
  4187. className = config['class'];
  4188. delete config['class'];
  4189. }
  4190. return callback(new Yii[className](config));
  4191. });
  4192. }
  4193. else {
  4194. if (config['class'] === undefined) {
  4195. className = "CView";
  4196. }
  4197. else {
  4198. className = config['class'];
  4199. delete config['class'];
  4200. }
  4201. return callback(new Yii[className](config));
  4202. }
  4203. }
  4204. /**
  4205. * Constructs the view and applies the given configuration
  4206. */
  4207. Yii.CView.prototype.construct = function (config) {
  4208. var self = this;
  4209. if (config === undefined) {
  4210. return;
  4211. }
  4212. Yii.forEach(config, function (key, value) {
  4213. self[key] = value;
  4214. });
  4215. }
  4216. /**
  4217. * Renders the view wrapped in the layout
  4218. * @param {Function} callback The function to execute after the view has been rendered
  4219. */
  4220. Yii.CView.prototype.render = function (callback) {
  4221. var func, self = this;
  4222. if (this.layout === null) {
  4223. this.renderPartial(callback);
  4224. }
  4225. else {
  4226. this.load(this.layout, function(layout) {
  4227. func = function(html) {
  4228. layout.content = html;
  4229. layout.render(callback);
  4230. }
  4231. self.renderPartial(func);
  4232. });
  4233. }
  4234. };
  4235. /**
  4236. * Renders the view
  4237. * @param {Function} callback The function to execute after the view has been rendered
  4238. */
  4239. Yii.CView.prototype.renderPartial = function (callback) {
  4240. var elements = {}, dependencies = [], stack = [], self = this, output = "", func;
  4241. Yii.forEach(this, function(name, value) {
  4242. if (name.slice(0,1) !== "_") {
  4243. elements[name] = value;
  4244. if (value instanceof Yii.CView) {
  4245. dependencies.push(name);
  4246. }
  4247. }
  4248. });
  4249. Yii.forEach(this.delegates, function(i, item) {
  4250. jQuery("body").undelegate(item[0], item[1]).delegate(item[0], item[1], item[2]);
  4251. });
  4252. func = function() {
  4253. self.getTemplate(function(template) {
  4254. callback(Mustache.to_html(template, self), self);
  4255. });
  4256. }
  4257. if (dependencies.length > 0) {
  4258. // can only call this callback when the others have completed.
  4259. stack.push(func);
  4260. Yii.forEach(dependencies, function(i, name) {
  4261. stack.push(function() {
  4262. self[name].renderPartial(function(output, parent) {
  4263. self[name] = output;
  4264. stack.pop()();
  4265. });
  4266. });
  4267. });
  4268. return stack.pop()();
  4269. }
  4270. else {
  4271. func();
  4272. }
  4273. };
  4274. /**
  4275. * Gets the contents of the template
  4276. * @param {Function} callback The function to execute after retrieving the template contents
  4277. * @returns {String} the template contents
  4278. */
  4279. Yii.CView.prototype.getTemplate = function (callback) {
  4280. var self = this, url;
  4281. if (this.template === null) {
  4282. url = this.templateURL;
  4283. if (url.indexOf("/") === -1 && url.indexOf(".") !== -1) {
  4284. url = Yii.getPathOfAlias(url) + ".tpl";
  4285. }
  4286. if (this._templates[url] !== undefined) {
  4287. this.template = this._templates[url];
  4288. callback(this.template, this);
  4289. }
  4290. else {
  4291. jQuery.ajax(url, {
  4292. success: function(data) {
  4293. self._templates[url] = data;
  4294. self.template = data;
  4295. callback(self.template, self);
  4296. },
  4297. error: function (xhr) {
  4298. self._template = "ERROR: " + xhr.responseText;
  4299. callback(self.template, self);
  4300. }
  4301. });
  4302. }
  4303. }
  4304. else {
  4305. callback(this.template, this);
  4306. }
  4307. return this.template;
  4308. };
  4309. /**
  4310. * Sets the contents of the template
  4311. * @param {String} value The template contents
  4312. */
  4313. Yii.CView.prototype.setTemplate = function (value) {
  4314. this.template = value;
  4315. }
  4316. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  4317. /**
  4318. * CApplication is the base class for all application classes.
  4319. *
  4320. * An application serves as the global context that the user request
  4321. * is being processed. It manages a set of application components that
  4322. * provide specific functionalities to the whole application.
  4323. *
  4324. * The core application components provided by CApplication are the following:
  4325. * <ul>
  4326. * <li>{@link getErrorHandler errorHandler}: handles JavaScript errors and
  4327. * uncaught exceptions. This application component is dynamically loaded when needed.</li>
  4328. * <li>{@link getSecurityManager securityManager}: provides security-related
  4329. * services, such as hashing, encryption. This application component is dynamically
  4330. * loaded when needed.</li>
  4331. * <li>{@link getStatePersister statePersister}: provides global state
  4332. * persistence method. This application component is dynamically loaded when needed.</li>
  4333. * <li>{@link getCache cache}: provides caching feature. This application component is
  4334. * disabled by default.</li>
  4335. * <li>{@link getMessages messages}: provides the message source for translating
  4336. * application messages. This application component is dynamically loaded when needed.</li>
  4337. * <li>{@link getCoreMessages coreMessages}: provides the message source for translating
  4338. * Yii framework messages. This application component is dynamically loaded when needed.</li>
  4339. * </ul>
  4340. *
  4341. * CApplication will undergo the following lifecycles when processing a user request:
  4342. * <ol>
  4343. * <li>load application configuration;</li>
  4344. * <li>set up class autoloader and error handling;</li>
  4345. * <li>load static application components;</li>
  4346. * <li>{@link onBeginRequest}: preprocess the user request;</li>
  4347. * <li>{@link processRequest}: process the user request;</li>
  4348. * <li>{@link onEndRequest}: postprocess the user request;</li>
  4349. * </ol>
  4350. *
  4351. * Starting from lifecycle 3, if a JavaScript error or an uncaught exception occurs,
  4352. * the application will switch to its error handling logic and jump to step 6 afterwards.
  4353. *
  4354. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  4355. * @version $Id: CApplication.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  4356. * @package system.base
  4357. * @since 1.0
  4358. *
  4359. * @property string $basePath Returns the root path of the application.
  4360. * @property CCache $cache Returns the cache component.
  4361. * @property CPhpMessageSource $coreMessages Returns the core message translations.
  4362. * @property CDateFormatter $dateFormatter Returns the locale-dependent date formatter.
  4363. * @property CDbConnection $db Returns the database connection component.
  4364. * @property CErrorHandler $errorHandler Returns the error handler component.
  4365. * @property string $extensionPath Returns the root directory that holds all third-party extensions.
  4366. * @property string $id Returns the unique identifier for the application.
  4367. * @property string $language Returns the language that the user is using and the application should be targeted to.
  4368. * @property CLocale $locale Returns the locale instance.
  4369. * @property string $localeDataPath Returns the directory that contains the locale data.
  4370. * @property CMessageSource $messages Returns the application message translations component.
  4371. * @property CNumberFormatter $numberFormatter The locale-dependent number formatter.
  4372. * @property CHttpRequest $request Returns the request component.
  4373. * @property string $runtimePath Returns the directory that stores runtime files.
  4374. * @property CSecurityManager $securityManager Returns the security manager component.
  4375. * @property CStatePersister $statePersister Returns the state persister component.
  4376. * @property string $timeZone Returns the time zone used by this application.
  4377. * @property CUrlManager $urlManager Returns the URL manager component.
  4378. * @author Charles Pick
  4379. * @class
  4380. * @extends Yii.CModule
  4381. */
  4382. Yii.CApplication = function CApplication (config) {
  4383. if (config !== false) {
  4384. this.construct(config);
  4385. }
  4386. };
  4387. Yii.CApplication.prototype = new Yii.CModule(false);
  4388. Yii.CApplication.prototype.constructor = Yii.CApplication;
  4389. /**
  4390. * @var {String} the application name. Defaults to 'My Application'.
  4391. */
  4392. Yii.CApplication.prototype.name = 'My Application';
  4393. /**
  4394. * @var {String} the charset currently used for the application. Defaults to 'UTF-8'.
  4395. */
  4396. Yii.CApplication.prototype.charset = 'UTF-8';
  4397. /**
  4398. * @var {String} the language that the application is written in. This mainly refers to
  4399. * the language that the messages and view files are in. Defaults to 'en_us' (US English).
  4400. */
  4401. Yii.CApplication.prototype.sourceLanguage = 'en_us';
  4402. Yii.CApplication.prototype._id = null;
  4403. Yii.CApplication.prototype._basePath = null;
  4404. Yii.CApplication.prototype._runtimePath = null;
  4405. Yii.CApplication.prototype._extensionPath = null;
  4406. Yii.CApplication.prototype._globalState = null;
  4407. Yii.CApplication.prototype._stateChanged = null;
  4408. Yii.CApplication.prototype._ended = false;
  4409. Yii.CApplication.prototype._language = null;
  4410. Yii.CApplication.prototype._timezone = null;
  4411. /**
  4412. * Processes the request.
  4413. * This is the place where the actual request processing work is done.
  4414. * Derived classes should override this method.
  4415. */
  4416. Yii.CApplication.prototype.processRequest = function () {
  4417. };
  4418. /**
  4419. * Constructor.
  4420. * @param {Mixed} config application configuration.
  4421. * If a string, it is treated as the path of the file that contains the configuration;
  4422. * If an array, it is the actual configuration information.
  4423. * Please make sure you specify the {@link getBasePath basePath} property in the configuration,
  4424. * which should point to the directory containing all application logic, template and data.
  4425. * If not, the directory will be defaulted to 'protected'.
  4426. */
  4427. Yii.CApplication.prototype.construct = function (config) {
  4428. if (config === undefined) {
  4429. config = {};
  4430. }
  4431. Yii.setApplication(this);
  4432. // set basePath at early as possible to avoid trouble
  4433. if(config.basePath !== undefined) {
  4434. this.setBasePath(config.basePath);
  4435. delete config.basePath;
  4436. }
  4437. else {
  4438. this.setBasePath('protected');
  4439. }
  4440. Yii.setPathOfAlias('application',this.getBasePath());
  4441. Yii.setPathOfAlias('webroot',location.protocol + "//" + location.hostname + "/");
  4442. Yii.setPathOfAlias('ext',this.getBasePath()+'/'+'extensions');
  4443. this.preinit();
  4444. this.initSystemHandlers();
  4445. this.registerCoreComponents();
  4446. this.configure(config);
  4447. this.attachBehaviors(this.behaviors);
  4448. this.preloadComponents();
  4449. this.init();
  4450. };
  4451. /**
  4452. * Runs the application.
  4453. * This method loads static application components. Derived classes usually overrides this
  4454. * method to do more application-specific tasks.
  4455. * Remember to call the parent implementation so that static application components are loaded.
  4456. */
  4457. Yii.CApplication.prototype.run = function () {
  4458. try {
  4459. if(this.hasEventHandler('onBeginRequest')) {
  4460. this.onBeginRequest(new Yii.CEvent(this));
  4461. }
  4462. Yii.beginProfile("Request");
  4463. this.processRequest();
  4464. Yii.endProfile("Request");
  4465. if(this.hasEventHandler('onEndRequest')) {
  4466. this.onEndRequest(new Yii.CEvent(this));
  4467. }
  4468. }
  4469. catch (e) {
  4470. if (e instanceof TypeError) {
  4471. this.displayError("TypeError",e);
  4472. }
  4473. else if (e instanceof Yii.CException) {
  4474. this.displayException(e);
  4475. }
  4476. else {
  4477. this.displayError("Error",e);
  4478. }
  4479. }
  4480. };
  4481. /**
  4482. * Terminates the application.
  4483. * This method replaces JavaScript's exit() function by calling
  4484. * {@link onEndRequest} before exiting.
  4485. * @param {Integer} status exit status (value 0 means normal exit while other values mean abnormal exit).
  4486. * @param {Boolean} exit whether to exit the current request. This parameter has been available since version 1.1.5.
  4487. * It defaults to true, meaning the JavaScript's exit() function will be called at the end of this method.
  4488. */
  4489. Yii.CApplication.prototype.end = function (status, exit) {
  4490. if (status === undefined) {
  4491. status = 0;
  4492. }
  4493. if (exit === undefined) {
  4494. exit = true;
  4495. }
  4496. if(this.hasEventHandler('onEndRequest')) {
  4497. this.onEndRequest(new Yii.CEvent(this));
  4498. }
  4499. if(exit) {
  4500. exit(status);
  4501. }
  4502. };
  4503. /**
  4504. * Raised right BEFORE the application processes the request.
  4505. * @param {Yii.CEvent} event the event parameter
  4506. */
  4507. Yii.CApplication.prototype.onBeginRequest = function (event) {
  4508. this.raiseEvent('onBeginRequest',event);
  4509. };
  4510. /**
  4511. * Raised right AFTER the application processes the request.
  4512. * @param {Yii.CEvent} event the event parameter
  4513. */
  4514. Yii.CApplication.prototype.onEndRequest = function (event) {
  4515. if(!this._ended) {
  4516. this._ended=true;
  4517. this.raiseEvent('onEndRequest',event);
  4518. }
  4519. };
  4520. /**
  4521. * Returns the unique identifier for the application.
  4522. * @returns {String} the unique identifier for the application.
  4523. */
  4524. Yii.CApplication.prototype.getId = function () {
  4525. if(this._id!==null) {
  4526. return this._id;
  4527. }
  4528. else {
  4529. return (this._id=php.sprintf('%x',php.crc32(this.getBasePath()+this.name)));
  4530. }
  4531. };
  4532. /**
  4533. * Sets the unique identifier for the application.
  4534. * @param {String} id the unique identifier for the application.
  4535. */
  4536. Yii.CApplication.prototype.setId = function (id) {
  4537. this._id=id;
  4538. };
  4539. /**
  4540. * Returns the root path of the application.
  4541. * @returns {String} the root directory of the application. Defaults to 'protected'.
  4542. */
  4543. Yii.CApplication.prototype.getBasePath = function () {
  4544. return this._basePath;
  4545. };
  4546. /**
  4547. * Sets the root directory of the application.
  4548. * This method can only be invoked at the begin of the constructor.
  4549. * @param {String} path the root directory of the application.
  4550. */
  4551. Yii.CApplication.prototype.setBasePath = function (path) {
  4552. this._basePath = path;
  4553. };
  4554. /**
  4555. * Returns the directory that stores runtime files.
  4556. * @returns {String} the directory that stores runtime files. Defaults to 'protected/runtime'.
  4557. */
  4558. Yii.CApplication.prototype.getRuntimePath = function () {
  4559. if(this._runtimePath!==null) {
  4560. return this._runtimePath;
  4561. }
  4562. else
  4563. {
  4564. this.setRuntimePath(this.getBasePath()+"/runtime");
  4565. return this._runtimePath;
  4566. }
  4567. };
  4568. /**
  4569. * Sets the directory that stores runtime files.
  4570. * @param {String} path the directory that stores runtime files.
  4571. */
  4572. Yii.CApplication.prototype.setRuntimePath = function (path) {
  4573. this._runtimePath= path;
  4574. };
  4575. /**
  4576. * Returns the root directory that holds all third-party extensions.
  4577. * @returns {String} the directory that contains all extensions. Defaults to the 'extensions' directory under 'protected'.
  4578. */
  4579. Yii.CApplication.prototype.getExtensionPath = function () {
  4580. return Yii.getPathOfAlias('ext');
  4581. };
  4582. /**
  4583. * Sets the root directory that holds all third-party extensions.
  4584. * @param {String} path the directory that contains all third-party extensions.
  4585. */
  4586. Yii.CApplication.prototype.setExtensionPath = function (path) {
  4587. Yii.setPathOfAlias('ext',path);
  4588. };
  4589. /**
  4590. * Returns the language that the user is using and the application should be targeted to.
  4591. * @returns {String} the language that the user is using and the application should be targeted to.
  4592. * Defaults to the {@link sourceLanguage source language}.
  4593. */
  4594. Yii.CApplication.prototype.getLanguage = function () {
  4595. return this._language===null ? this.sourceLanguage : this._language;
  4596. };
  4597. /**
  4598. * Specifies which language the application is targeted to.
  4599. *
  4600. * This is the language that the application displays to end users.
  4601. * If set null, it uses the {@link sourceLanguage source language}.
  4602. *
  4603. * Unless your application needs to support multiple languages, you should always
  4604. * set this language to null to maximize the application's performance.
  4605. * @param {String} language the user language (e.g. 'en_US', 'zh_CN').
  4606. * If it is null, the {@link sourceLanguage} will be used.
  4607. */
  4608. Yii.CApplication.prototype.setLanguage = function (language) {
  4609. this._language=language;
  4610. };
  4611. /**
  4612. * Returns the time zone used by this application.
  4613. * @returns {String} the time zone used by this application.
  4614. * @see http://php.net/manual/en/function.date-default-timezone-get.php
  4615. * @since 1.0.9
  4616. */
  4617. Yii.CApplication.prototype.getTimeZone = function () {
  4618. if (this._timezone === null) {
  4619. this._timezone = jzTimezoneDetector.determine_timezone().timezone.olson_tz;
  4620. }
  4621. return this._timezone;
  4622. };
  4623. /**
  4624. * Sets the time zone used by this application.
  4625. * This is a simple wrapper of JavaScript function date_default_timezone_set().
  4626. * @param {String} value the time zone used by this application.
  4627. * @see http://php.net/manual/en/function.date-default-timezone-set.php
  4628. * @since 1.0.9
  4629. */
  4630. Yii.CApplication.prototype.setTimeZone = function (value) {
  4631. this._timezone = value;
  4632. };
  4633. /**
  4634. * Returns the localized version of a specified file.
  4635. *
  4636. * The searching is based on the specified language code. In particular,
  4637. * a file with the same name will be looked for under the subdirectory
  4638. * named as the locale ID. For example, given the file "path/to/view.php"
  4639. * and locale ID "zh_cn", the localized file will be looked for as
  4640. * "path/to/zh_cn/view.php". If the file is not found, the original file
  4641. * will be returned.
  4642. *
  4643. * For consistency, it is recommended that the locale ID is given
  4644. * in lower case and in the format of LanguageID_RegionID (e.g. "en_us").
  4645. *
  4646. * @param {String} srcFile the original file
  4647. * @param {String} srcLanguage the language that the original file is in. If null, the application {@link sourceLanguage source language} is used.
  4648. * @param {String} language the desired language that the file should be localized to. If null, the {@link getLanguage application language} will be used.
  4649. * @returns {String} the matching localized file. The original file is returned if no localized version is found
  4650. * or if source language is the same as the desired language.
  4651. */
  4652. Yii.CApplication.prototype.findLocalizedFile = function (srcFile, srcLanguage, language) {
  4653. var desiredFile;
  4654. if (srcLanguage === undefined) {
  4655. srcLanguage = null;
  4656. }
  4657. if (language === undefined) {
  4658. language = null;
  4659. }
  4660. if(srcLanguage===null) {
  4661. srcLanguage=this.sourceLanguage;
  4662. }
  4663. if(language===null) {
  4664. language=this.getLanguage();
  4665. }
  4666. if(language===srcLanguage) {
  4667. return srcFile;
  4668. }
  4669. // TODO: fix this and determine how to deal with localized files
  4670. return srcFile;
  4671. //desiredFile=php.dirname(srcFile)+DIRECTORY_SEPARATOR+language+DIRECTORY_SEPARATOR+php.basename(srcFile);
  4672. //return is_file(desiredFile) ? desiredFile : srcFile;
  4673. };
  4674. /**
  4675. * Returns the locale instance.
  4676. * @param {String} localeID the locale ID (e.g. en_US). If null, the {@link getLanguage application language ID} will be used.
  4677. * @returns {Yii.CLocale} the locale instance
  4678. */
  4679. Yii.CApplication.prototype.getLocale = function (localeID) {
  4680. if (localeID === undefined) {
  4681. localeID = null;
  4682. }
  4683. return Yii.CLocale.getInstance(localeID===null?this.getLanguage():localeID);
  4684. };
  4685. /**
  4686. * Returns the directory that contains the locale data.
  4687. * @returns {String} the directory that contains the locale data. It defaults to 'framework/i18n/data'.
  4688. * @since 1.1.0
  4689. */
  4690. Yii.CApplication.prototype.getLocaleDataPath = function () {
  4691. var dataPath;
  4692. return Yii.CLocale.dataPath===null ? Yii.getPathOfAlias('system.i18n.data') : Yii.CLocale.dataPath;
  4693. };
  4694. /**
  4695. * Sets the directory that contains the locale data.
  4696. * @param {String} value the directory that contains the locale data.
  4697. * @since 1.1.0
  4698. */
  4699. Yii.CApplication.prototype.setLocaleDataPath = function (value) {
  4700. var dataPath;
  4701. Yii.CLocale.dataPath=value;
  4702. };
  4703. /**
  4704. * @returns {Yii.CNumberFormatter} the locale-dependent number formatter.
  4705. * The current {@link getLocale application locale} will be used.
  4706. */
  4707. Yii.CApplication.prototype.getNumberFormatter = function () {
  4708. return this.getLocale().getNumberFormatter();
  4709. };
  4710. /**
  4711. * Returns the locale-dependent date formatter.
  4712. * @returns {Yii.CDateFormatter} the locale-dependent date formatter.
  4713. * The current {@link getLocale application locale} will be used.
  4714. */
  4715. Yii.CApplication.prototype.getDateFormatter = function () {
  4716. return this.getLocale().getDateFormatter();
  4717. };
  4718. /**
  4719. * Returns the database connection component.
  4720. * @returns {Yii.CDbConnection} the database connection
  4721. */
  4722. Yii.CApplication.prototype.getDb = function () {
  4723. return this.getComponent('db');
  4724. };
  4725. /**
  4726. * Returns the error handler component.
  4727. * @returns {Yii.CErrorHandler} the error handler application component.
  4728. */
  4729. Yii.CApplication.prototype.getErrorHandler = function () {
  4730. return this.getComponent('errorHandler');
  4731. };
  4732. /**
  4733. * Returns the security manager component.
  4734. * @returns {Yii.CSecurityManager} the security manager application component.
  4735. */
  4736. Yii.CApplication.prototype.getSecurityManager = function () {
  4737. return this.getComponent('securityManager');
  4738. };
  4739. /**
  4740. * Returns the state persister component.
  4741. * @returns {Yii.CStatePersister} the state persister application component.
  4742. */
  4743. Yii.CApplication.prototype.getStatePersister = function () {
  4744. return this.getComponent('statePersister');
  4745. };
  4746. /**
  4747. * Returns the cache component.
  4748. * @returns {Yii.CCache} the cache application component. Null if the component is not enabled.
  4749. */
  4750. Yii.CApplication.prototype.getCache = function () {
  4751. return this.getComponent('cache');
  4752. };
  4753. /**
  4754. * Returns the core message translations component.
  4755. * @returns {Yii.CPhpMessageSource} the core message translations
  4756. */
  4757. Yii.CApplication.prototype.getCoreMessages = function () {
  4758. return this.getComponent('coreMessages');
  4759. };
  4760. /**
  4761. * Returns the application message translations component.
  4762. * @returns {Yii.CMessageSource} the application message translations
  4763. */
  4764. Yii.CApplication.prototype.getMessages = function () {
  4765. return this.getComponent('messages');
  4766. };
  4767. /**
  4768. * Returns the request component.
  4769. * @returns {Yii.CHttpRequest} the request component
  4770. */
  4771. Yii.CApplication.prototype.getRequest = function () {
  4772. return this.getComponent('request');
  4773. };
  4774. /**
  4775. * Returns the URL manager component.
  4776. * @returns {Yii.CUrlManager} the URL manager component
  4777. */
  4778. Yii.CApplication.prototype.getUrlManager = function () {
  4779. return this.getComponent('urlManager');
  4780. };
  4781. /**
  4782. * Returns a global value.
  4783. *
  4784. * A global value is one that is persistent across users sessions and requests.
  4785. * @param {String} key the name of the value to be returned
  4786. * @param {Mixed} defaultValue the default value. If the named global value is not found, this will be returned instead.
  4787. * @returns {Mixed} the named global value
  4788. * @see setGlobalState
  4789. */
  4790. Yii.CApplication.prototype.getGlobalState = function (key, defaultValue) {
  4791. if (defaultValue === undefined) {
  4792. defaultValue = null;
  4793. }
  4794. if(this._globalState===null) {
  4795. this.loadGlobalState();
  4796. }
  4797. if(this._globalState[key] !== undefined) {
  4798. return this._globalState[key];
  4799. }
  4800. else {
  4801. return defaultValue;
  4802. }
  4803. };
  4804. /**
  4805. * Sets a global value.
  4806. *
  4807. * A global value is one that is persistent across users sessions and requests.
  4808. * Make sure that the value is serializable and unserializable.
  4809. * @param {String} key the name of the value to be saved
  4810. * @param {Mixed} value the global value to be saved. It must be serializable.
  4811. * @param {Mixed} defaultValue the default value. If the named global value is the same as this value, it will be cleared from the current storage.
  4812. * @see getGlobalState
  4813. */
  4814. Yii.CApplication.prototype.setGlobalState = function (key, value, defaultValue) {
  4815. var changed;
  4816. if (defaultValue === undefined) {
  4817. defaultValue = null;
  4818. }
  4819. if(this._globalState===null) {
  4820. this.loadGlobalState();
  4821. }
  4822. changed=this._stateChanged;
  4823. if(value===defaultValue) {
  4824. if(this._globalState[key] !== undefined) {
  4825. delete this._globalState[key];
  4826. this._stateChanged=true;
  4827. }
  4828. }
  4829. else if(this._globalState[key] === undefined || this._globalState[key]!==value) {
  4830. this._globalState[key]=value;
  4831. this._stateChanged=true;
  4832. }
  4833. if(this._stateChanged!==changed) {
  4834. this.saveGlobalState();
  4835. }
  4836. };
  4837. /**
  4838. * Clears a global value.
  4839. *
  4840. * The value cleared will no longer be available in this request and the following requests.
  4841. * @param {String} key the name of the value to be cleared
  4842. */
  4843. Yii.CApplication.prototype.clearGlobalState = function (key) {
  4844. this.setGlobalState(key,true,true);
  4845. };
  4846. /**
  4847. * Loads the global state data from persistent storage.
  4848. * @see getStatePersister
  4849. * @throws {Yii.CException} if the state persister is not available
  4850. */
  4851. Yii.CApplication.prototype.loadGlobalState = function () {
  4852. var persister;
  4853. persister=this.getStatePersister();
  4854. if((this._globalState=persister.load())===null) {
  4855. this._globalState={};
  4856. }
  4857. this._stateChanged=false;
  4858. };
  4859. /**
  4860. * Saves the global state data into persistent storage.
  4861. * @see getStatePersister
  4862. * @throws {Yii.CException} if the state persister is not available
  4863. */
  4864. Yii.CApplication.prototype.saveGlobalState = function () {
  4865. if(this._stateChanged) {
  4866. this._stateChanged=false;
  4867. this.getStatePersister().save(this._globalState);
  4868. }
  4869. };
  4870. /**
  4871. * Handles uncaught JavaScript exceptions.
  4872. *
  4873. * This method is implemented as a JavaScript exception handler. It requires
  4874. * that constant YII_ENABLE_EXCEPTION_HANDLER be defined true.
  4875. *
  4876. * This method will first raise an {@link onException} event.
  4877. * If the exception is not handled by any event handler, it will call
  4878. * {@link getErrorHandler errorHandler} to process the exception.
  4879. *
  4880. * The application will be terminated by this method.
  4881. *
  4882. * @param {Exception} exception exception that is not caught
  4883. */
  4884. Yii.CApplication.prototype.handleException = function (exception) {
  4885. var category, message, event, handler, msg;
  4886. // disable error capturing to avoid recursive errors
  4887. category='exception.'+php.get_class(exception);
  4888. if(exception instanceof Yii.CHttpException) {
  4889. category+='.'+exception.statusCode;
  4890. }
  4891. message=exception.message;
  4892. Yii.log(message,Yii.CLogger.LEVEL_ERROR,category);
  4893. try
  4894. {
  4895. event=new Yii.CExceptionEvent(this,exception);
  4896. this.onException(event);
  4897. if(!event.handled) {
  4898. // try an error handler
  4899. if((handler=this.getErrorHandler())!==null) {
  4900. handler.handle(event);
  4901. }
  4902. else {
  4903. this.displayException(exception);
  4904. }
  4905. }
  4906. }
  4907. catch(e) {
  4908. this.displayException(e);
  4909. }
  4910. try
  4911. {
  4912. this.end(1);
  4913. return;
  4914. }
  4915. catch(e) {
  4916. // use the most primitive way to log error
  4917. msg = php.get_class(e)+': '+e.message+"\n";
  4918. msg += e.getTraceAsString()+"\n";
  4919. msg += "Previous exception:\n";
  4920. msg += php.get_class(exception)+': '+exception.message+"\n";
  4921. msg += exception.getTraceAsString()+"\n";
  4922. console.log(msg);
  4923. return;
  4924. }
  4925. };
  4926. /**
  4927. * Handles JavaScript execution errors such as warnings, notices.
  4928. *
  4929. * This method is implemented as a JavaScript error handler. It requires
  4930. * that constant YII_ENABLE_ERROR_HANDLER be defined true.
  4931. *
  4932. * This method will first raise an {@link onError} event.
  4933. * If the error is not handled by any event handler, it will call
  4934. * {@link getErrorHandler errorHandler} to process the error.
  4935. *
  4936. * The application will be terminated by this method.
  4937. *
  4938. * @param {Integer} code the level of the error raised
  4939. * @param {String} message the error message
  4940. * @param {String} file the filename that the error was raised in
  4941. * @param {Integer} line the line number the error was raised at
  4942. */
  4943. Yii.CApplication.prototype.handleError = function (code, message, file, line) {
  4944. var log = "", trace, t, i, event, handler, msg;
  4945. if(code) {
  4946. log="message (" + file + ":" + line + ")\nStack trace:\n";
  4947. trace=Yii.CException.prototype.stacktrace();
  4948. // skip the first 3 stacks as they do not tell the error position
  4949. if(php.count(trace)>3) {
  4950. trace=php.array_slice(trace,3);
  4951. }
  4952. for (i in trace) {
  4953. if (trace.hasOwnProperty(i)) {
  4954. t = trace[i];
  4955. if(t.file === undefined) {
  4956. t.file='unknown';
  4957. }
  4958. if(t.line === undefined) {
  4959. t.line=0;
  4960. }
  4961. if(t['function'] === undefined) {
  4962. t['function']='unknown';
  4963. }
  4964. log+="#i " + t.file + "(" + t.line + "): ";
  4965. if(t.object !== undefined && (!t.object instanceof Array && t.object !== null && typeof(t.object) === 'object')) {
  4966. log+=php.get_class(t.object)+'.';
  4967. }
  4968. log+= t['function'] + "()\n";
  4969. }
  4970. }
  4971. Yii.log(log, Yii.CLogger.prototype.LEVEL_ERROR, "js");
  4972. try {
  4973. event = new Yii.CErrorEvent(this, code, message, file, line);
  4974. this.onError(event);
  4975. if (!event.handled) {
  4976. // try an error handler
  4977. handler = this.getErrorHandler();
  4978. if (handler !== null) {
  4979. handler.handle(event);
  4980. }
  4981. else {
  4982. this.displayError(code, message, file, line);
  4983. }
  4984. }
  4985. }
  4986. catch (e) {
  4987. this.displayException(e);
  4988. }
  4989. try {
  4990. this.end(1);
  4991. }
  4992. catch(e) {
  4993. // use the most primitive way to log error
  4994. msg = php.get_class(e)+': '+e.message+"\n";
  4995. msg += e.getTraceAsString()+"\n";
  4996. msg += "Previous error:\n";
  4997. msg += log + "\n";
  4998. console.log(msg);
  4999. return;
  5000. }
  5001. }
  5002. };
  5003. /**
  5004. * Raised when an uncaught JavaScript exception occurs.
  5005. *
  5006. * An event handler can set the {@link CExceptionEvent::handled handled}
  5007. * property of the event parameter to be true to indicate no further error
  5008. * handling is needed. Otherwise, the {@link getErrorHandler errorHandler}
  5009. * application component will continue processing the error.
  5010. *
  5011. * @param {Yii.CExceptionEvent} event event parameter
  5012. */
  5013. Yii.CApplication.prototype.onException = function (event) {
  5014. this.raiseEvent('onException',event);
  5015. };
  5016. /**
  5017. * Raised when a JavaScript execution error occurs.
  5018. *
  5019. * An event handler can set the {@link CErrorEvent::handled handled}
  5020. * property of the event parameter to be true to indicate no further error
  5021. * handling is needed. Otherwise, the {@link getErrorHandler errorHandler}
  5022. * application component will continue processing the error.
  5023. *
  5024. * @param {Yii.CErrorEvent} event event parameter
  5025. */
  5026. Yii.CApplication.prototype.onError = function (event) {
  5027. this.raiseEvent('onError',event);
  5028. };
  5029. /**
  5030. * Displays the captured JavaScript error.
  5031. * This method displays the error in HTML when there is
  5032. * no active error handler.
  5033. * @param {Integer} code error code
  5034. * @param {String} message error message
  5035. * @param {String} file error file
  5036. * @param {String} line error line
  5037. */
  5038. Yii.CApplication.prototype.displayError = function (code, message, file, line) {
  5039. var trace, t, i;
  5040. if(YII_DEBUG) {
  5041. document.write("<h1>JavaScript Error [" + code + "]</h1>\n");
  5042. document.write("<p>" + message + "(" + file + ":" + line + ")</p>\n");
  5043. document.write('<table class="yiiLog" width="100%" cellpadding="2" style="border-spacing:1px;font:11px Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;color:#666666;">');
  5044. document.write('<tr style="background-color:#ccc;">');
  5045. document.write("<th style='width:120px'>Timestamp</th>");
  5046. document.write("<th>Level</th>");
  5047. document.write("<th>Category</th>");
  5048. document.write("<th>Message</th>");
  5049. document.write("</tr>");
  5050. Yii.forEach(Yii._logger.getLogs(), function (i, log) {
  5051. document.write("<tr><td>" + php.date('H:i:s.',log[3]) + php.sprintf('%06d',Number((log[3]-Number(log[3]))*1000000)) + "</td><td>" + log[1] + "</td><td>" + log[2] + "</td><td>" + log[0] + "</td></tr>");
  5052. });
  5053. document.write("</table>");
  5054. document.write("<h2>Stack Trace</h2>");
  5055. document.write('<pre>');
  5056. trace=Yii.CException.prototype.stacktrace();
  5057. // skip the first 3 stacks as they do not tell the error position
  5058. if(php.count(trace)>3) {
  5059. trace=php.array_slice(trace,3);
  5060. }
  5061. for (i in trace) {
  5062. if (trace.hasOwnProperty(i)) {
  5063. document.write(trace[i] + "\n");
  5064. }
  5065. }
  5066. document.write("</pre>");
  5067. }
  5068. else {
  5069. document.write("<h1>JavaScript Error [" + code + "]</h1>\n");
  5070. document.write("<p>" + message + "</p>\n");
  5071. }
  5072. };
  5073. /**
  5074. * Displays the uncaught JavaScript exception.
  5075. * This method displays the exception in HTML when there is
  5076. * no active error handler.
  5077. * @param {Exception} exception the uncaught exception
  5078. */
  5079. Yii.CApplication.prototype.displayException = function (exception) {
  5080. if(YII_DEBUG) {
  5081. document.write('<h1>'+php.get_class(exception)+"</h1>\n");
  5082. document.write('<p>'+exception.getMessage()+'</p>');
  5083. document.write('<pre>'+exception.getTraceAsString()+'</pre>');
  5084. }
  5085. else
  5086. {
  5087. document.write('<h1>'+php.get_class(exception)+"</h1>\n");
  5088. document.write('<p>'+exception.getMessage()+'</p>');
  5089. }
  5090. };
  5091. /**
  5092. * Initializes the class autoloader and error handlers.
  5093. */
  5094. Yii.CApplication.prototype.initSystemHandlers = function () {
  5095. return;
  5096. window.onerror = function (err, loc) {
  5097. Yii.app().displayError("",err);
  5098. return false;
  5099. };
  5100. };
  5101. /**
  5102. * Registers the core application components.
  5103. * @see setComponents
  5104. */
  5105. Yii.CApplication.prototype.registerCoreComponents = function () {
  5106. var components;
  5107. components={
  5108. 'coreMessages':{
  5109. 'class':'CJavaScriptMessageSource',
  5110. 'language':'en_us',
  5111. 'basePath':YII_PATH + '/messages'
  5112. },
  5113. 'db':{
  5114. 'class':'CDbConnection'
  5115. },
  5116. 'messages':{
  5117. 'class':'CJavaScriptMessageSource'
  5118. },
  5119. 'errorHandler':{
  5120. 'class':'CErrorHandler'
  5121. },
  5122. 'securityManager':{
  5123. 'class':'CSecurityManager'
  5124. },
  5125. 'statePersister':{
  5126. 'class':'CStatePersister'
  5127. },
  5128. 'urlManager':{
  5129. 'class':'CUrlManager'
  5130. },
  5131. 'request':{
  5132. 'class':'CHttpRequest'
  5133. },
  5134. 'format':{
  5135. 'class':'CFormatter'
  5136. }
  5137. };
  5138. this.setComponents(components);
  5139. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  5140. /**
  5141. * CBehavior is a convenient base class for behavior classes.
  5142. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  5143. * @version $Id: CBehavior.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  5144. * @package system.base
  5145. * @since 1.0.2
  5146. * @author Charles Pick
  5147. * @class
  5148. * @extends Yii.CComponent
  5149. */
  5150. Yii.CBehavior = function CBehavior() {
  5151. };
  5152. Yii.CBehavior.prototype = new Yii.CComponent();
  5153. Yii.CBehavior.prototype.constructor = Yii.CBehavior;
  5154. Yii.CBehavior.prototype._enabled = null;
  5155. Yii.CBehavior.prototype._owner = null;
  5156. /**
  5157. * Declares events and the corresponding event handler methods.
  5158. * The events are defined by the {@link owner} component, while the handler
  5159. * methods by the behavior class. The handlers will be attached to the corresponding
  5160. * events when the behavior is attached to the {@link owner} component; and they
  5161. * will be detached from the events when the behavior is detached from the component.
  5162. * @returns {Object} events (keys) and the corresponding event handler methods (values).
  5163. */
  5164. Yii.CBehavior.prototype.events = function () {
  5165. return {};
  5166. };
  5167. /**
  5168. * Attaches the behavior object to the component.
  5169. * The default implementation will set the {@link owner} property
  5170. * and attach event handlers as declared in {@link events}.
  5171. * Make sure you call the parent implementation if you override this method.
  5172. * @param {Yii.CComponent} owner the component that this behavior is to be attached to.
  5173. */
  5174. Yii.CBehavior.prototype.attach = function (owner) {
  5175. var eventHandler, event, handler;
  5176. this._owner=owner;
  5177. eventHandler = this.events();
  5178. for (event in eventHandler) {
  5179. if (eventHandler.hasOwnProperty(event)) {
  5180. handler = eventHandler[event];
  5181. owner.attachEventHandler(event,[this,handler]);
  5182. }
  5183. }
  5184. };
  5185. /**
  5186. * Detaches the behavior object from the component.
  5187. * The default implementation will unset the {@link owner} property
  5188. * and detach event handlers declared in {@link events}.
  5189. * Make sure you call the parent implementation if you override this method.
  5190. * @param {Yii.CComponent} owner the component that this behavior is to be detached from.
  5191. */
  5192. Yii.CBehavior.prototype.detach = function (owner) {
  5193. var eventHandler, event, handler;
  5194. eventHandler = this.events();
  5195. for (event in eventHandler) {
  5196. if (eventHandler.hasOwnProperty(event)) {
  5197. handler = eventHandler[event];
  5198. owner.detachEventHandler(event,[this,handler]);
  5199. }
  5200. }
  5201. this._owner=null;
  5202. };
  5203. /**
  5204. * @returns {Yii.CComponent} the owner component that this behavior is attached to.
  5205. */
  5206. Yii.CBehavior.prototype.getOwner = function () {
  5207. return this._owner;
  5208. };
  5209. /**
  5210. * @returns {Boolean} whether this behavior is enabled
  5211. */
  5212. Yii.CBehavior.prototype.getEnabled = function () {
  5213. return this._enabled;
  5214. };
  5215. /**
  5216. * @param {Boolean} value whether this behavior is enabled
  5217. */
  5218. Yii.CBehavior.prototype.setEnabled = function (value) {
  5219. var eventHandler, event, handler, eventHandlerList;
  5220. if(this._enabled!=value && this._owner) {
  5221. if(value) {
  5222. eventHandler = this.events();
  5223. for (event in eventHandler) {
  5224. if (eventHandler.hasOwnProperty(event)) {
  5225. handler = eventHandler[event];
  5226. this._owner.attachEventHandler(event,[this,handler]);
  5227. }
  5228. }
  5229. }
  5230. else {
  5231. eventHandlerList = this.events();
  5232. for (event in eventHandlerList) {
  5233. if (eventHandlerList.hasOwnProperty(event)) {
  5234. handler = eventHandlerList[event];
  5235. this._owner.detachEventHandler(event,[this,handler]);
  5236. }
  5237. }
  5238. }
  5239. }
  5240. this._enabled=value;
  5241. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  5242. /**
  5243. * CErrorEvent represents the parameter for the {@link CApplication::onError onError} event.
  5244. *
  5245. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  5246. * @version $Id: CErrorEvent.php 2799 2011-01-01 19:31:13Z qiang.xue $
  5247. * @package system.base
  5248. * @since 1.0
  5249. * @author Charles Pick
  5250. * @class
  5251. * @extends Yii.CEvent
  5252. */
  5253. Yii.CErrorEvent = function CErrorEvent () {
  5254. };
  5255. Yii.CErrorEvent.prototype = new Yii.CEvent();
  5256. Yii.CErrorEvent.prototype.constructor = Yii.CErrorEvent;
  5257. /**
  5258. * @var {String} error code
  5259. */
  5260. Yii.CErrorEvent.prototype.code = null;
  5261. /**
  5262. * @var {String} error message
  5263. */
  5264. Yii.CErrorEvent.prototype.message = null;
  5265. /**
  5266. * @var {String} error message
  5267. */
  5268. Yii.CErrorEvent.prototype.file = null;
  5269. /**
  5270. * @var {String} error file
  5271. */
  5272. Yii.CErrorEvent.prototype.line = null;
  5273. /**
  5274. * Constructor.
  5275. * @param {Mixed} sender sender of the event
  5276. * @param {String} code error code
  5277. * @param {String} message error message
  5278. * @param {String} file error file
  5279. * @param {Integer} line error line
  5280. */
  5281. Yii.CErrorEvent.prototype.construct = function (sender, code, message, file, line) {
  5282. this.code=code;
  5283. this.message=message;
  5284. this.file=file;
  5285. this.line=line;
  5286. parent.__construct(sender);
  5287. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  5288. /**
  5289. * CExceptionEvent represents the parameter for the {@link CApplication::onException onException} event.
  5290. *
  5291. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  5292. * @version $Id: CExceptionEvent.php 2799 2011-01-01 19:31:13Z qiang.xue $
  5293. * @package system.base
  5294. * @since 1.0
  5295. * @author Charles Pick
  5296. * @class
  5297. * @extends Yii.CEvent
  5298. */
  5299. Yii.CExceptionEvent = function CExceptionEvent (sender, exception) {
  5300. this.construct(sender, exception);
  5301. };
  5302. Yii.CExceptionEvent.prototype = new Yii.CEvent();
  5303. Yii.CExceptionEvent.prototype.constructor = Yii.CExceptionEvent;
  5304. /**
  5305. * @var {Yii.CException} the exception that this event is about.
  5306. */
  5307. Yii.CExceptionEvent.prototype.exception = null;
  5308. /**
  5309. * Constructor.
  5310. * @param {Mixed} sender sender of the event
  5311. * @param {Yii.CException} exception the exception
  5312. */
  5313. Yii.CExceptionEvent.prototype.construct = function (sender, exception) {
  5314. this.exception=exception;
  5315. Yii.CEvent.prototype.construct.call(this, sender);
  5316. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  5317. /**
  5318. * CHttpException represents an exception caused by invalid operations of end-users.
  5319. *
  5320. * The HTTP error code can be obtained via {@link statusCode}.
  5321. * Error handlers may use this status code to decide how to format the error page.
  5322. *
  5323. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  5324. * @version $Id: CHttpException.php 2799 2011-01-01 19:31:13Z qiang.xue $
  5325. * @package system.base
  5326. * @since 1.0
  5327. * @author Charles Pick
  5328. * @class
  5329. * @extends Yii.CException
  5330. */
  5331. Yii.CHttpException = function CHttpException (status, message, code) {
  5332. this.construct(status, message, code);
  5333. };
  5334. Yii.CHttpException.prototype = new Yii.CException(false);
  5335. Yii.CHttpException.prototype.constructor = Yii.CHttpException;
  5336. /**
  5337. * @var {Integer} HTTP status code, such as 403, 404, 500, etc.
  5338. */
  5339. Yii.CHttpException.prototype.statusCode = null;
  5340. /**
  5341. * Constructor.
  5342. * @param {Integer} status HTTP status code, such as 404, 500, etc.
  5343. * @param {String} message error message
  5344. * @param {Integer} code error code
  5345. */
  5346. Yii.CHttpException.prototype.construct = function (status, message, code) {
  5347. if (message === undefined) {
  5348. message = null;
  5349. }
  5350. if (code === undefined) {
  5351. code = 0;
  5352. }
  5353. this.statusCode=status;
  5354. Yii.CException.call(this, message, code);
  5355. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  5356. /**
  5357. * CModel is the base class providing the common features needed by data model objects.
  5358. *
  5359. * CModel defines the basic framework for data models that need to be validated.
  5360. *
  5361. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  5362. * @version $Id: CModel.php 3087 2011-03-15 02:08:53Z qiang.xue $
  5363. * @package system.base
  5364. * @since 1.0
  5365. * @author Charles Pick
  5366. * @class
  5367. * @extends Yii.CComponent
  5368. */
  5369. Yii.CModel = function CModel () {
  5370. };
  5371. Yii.CModel.prototype = new Yii.CComponent();
  5372. Yii.CModel.prototype.constructor = Yii.CModel;
  5373. Yii.CModel.prototype._errors = {};
  5374. Yii.CModel.prototype._validators = null;
  5375. Yii.CModel.prototype._scenario = '';
  5376. /**
  5377. * Returns the list of attribute names of the model.
  5378. * @returns {Array} list of attribute names.
  5379. * @since 1.0.1
  5380. */
  5381. Yii.CModel.prototype.attributeNames = function () {
  5382. };
  5383. /**
  5384. * Returns the validation rules for attributes.
  5385. *
  5386. * This method should be overridden to declare validation rules.
  5387. * Each rule is an object with the following structure:
  5388. * <pre>
  5389. * {
  5390. * attributes: 'attribute list',
  5391. * validator: 'validator name',
  5392. * on: 'scenario name', ...validation parameters...
  5393. * }
  5394. * </pre>
  5395. * where
  5396. * <ul>
  5397. * <li>attributes: specifies the attributes (separated by commas) to be validated;</li>
  5398. * <li>validator: specifies the validator to be used. It can be the name of a model class
  5399. * method, the name of a built-in validator, or a validator class.
  5400. * A validation method must have the following signature:
  5401. * <pre>
  5402. * // params refers to validation parameters given in the rule
  5403. * function validatorName(attribute, params)
  5404. * </pre>
  5405. * A built-in validator refers to one of the validators declared in {@link Yii.CValidator.builtInValidators}.
  5406. * And a validator class is a class extending {@link Yii.CValidator}.</li>
  5407. * <li>on: this specifies the scenarios when the validation rule should be performed.
  5408. * Separate different scenarios with commas. If this option is not set, the rule
  5409. * will be applied in any scenario. Please see {@link Yii.CModel.scenario} for more details about this option.</li>
  5410. * <li>additional parameters are used to initialize the corresponding validator properties.
  5411. * Please refer to individal validator class API for possible properties.</li>
  5412. * </ul>
  5413. *
  5414. * The following are some examples:
  5415. * <pre>
  5416. * [
  5417. * {
  5418. * attributes: 'username',
  5419. * validator: 'required'
  5420. * },
  5421. * {
  5422. * attributes: 'username',
  5423. * validator: 'length',
  5424. * min: 3,
  5425. * max: 12
  5426. * },
  5427. * {
  5428. * attributes: 'password',
  5429. * validator: 'compare',
  5430. * compareAttribute: 'password2',
  5431. * on: 'register'
  5432. * },
  5433. * {
  5434. * attributes: 'password',
  5435. * validator: 'authenticate',
  5436. * on: 'login'
  5437. * }
  5438. * ];
  5439. * </pre>
  5440. *
  5441. * @returns {Array} validation rules to be applied when {@link validate()} is called.
  5442. * @see scenario
  5443. */
  5444. Yii.CModel.prototype.rules = function () {
  5445. return [];
  5446. };
  5447. /**
  5448. * Returns a list of behaviors that this model should behave as.
  5449. * The return value should be an array of behavior configurations indexed by
  5450. * behavior names. Each behavior configuration can be either a string specifying
  5451. * the behavior class or an array of the following structure:
  5452. * <pre>
  5453. * 'behaviorName':{
  5454. * 'class':'path.to.BehaviorClass',
  5455. * 'property1':'value1',
  5456. * 'property2':'value2',
  5457. * }
  5458. * </pre>
  5459. *
  5460. * Note, the behavior classes must implement {@link IBehavior} or extend from
  5461. * {@link CBehavior}. Behaviors declared in this method will be attached
  5462. * to the model when it is instantiated.
  5463. *
  5464. * For more details about behaviors, see {@link CComponent}.
  5465. * @returns {Object} the behavior configurations (behavior name=>behavior configuration)
  5466. * @since 1.0.2
  5467. */
  5468. Yii.CModel.prototype.behaviors = function () {
  5469. return {};
  5470. };
  5471. /**
  5472. * Returns the attribute labels.
  5473. * Attribute labels are mainly used in error messages of validation.
  5474. * By default an attribute label is generated using {@link generateAttributeLabel}.
  5475. * This method allows you to explicitly specify attribute labels.
  5476. *
  5477. * Note, in order to inherit labels defined in the parent class, a child class needs to
  5478. * merge the parent labels with child labels using functions like array_merge().
  5479. *
  5480. * @returns {Object} attribute labels (name=>label)
  5481. * @see generateAttributeLabel
  5482. */
  5483. Yii.CModel.prototype.attributeLabels = function () {
  5484. return {};
  5485. };
  5486. /**
  5487. * Performs the validation.
  5488. *
  5489. * This method executes the validation rules as declared in {@link rules}.
  5490. * Only the rules applicable to the current {@link scenario} will be executed.
  5491. * A rule is considered applicable to a scenario if its 'on' option is not set
  5492. * or contains the scenario.
  5493. *
  5494. * Errors found during the validation can be retrieved via {@link getErrors}.
  5495. *
  5496. * @param {Array} attributes list of attributes that should be validated. Defaults to null,
  5497. * meaning any attribute listed in the applicable validation rules should be
  5498. * validated. If this parameter is given as a list of attributes, only
  5499. * the listed attributes will be validated.
  5500. * @param {Boolean} clearErrors whether to call {@link clearErrors} before performing validation
  5501. * @returns {Boolean} whether the validation is successful without any error.
  5502. * @see beforeValidate
  5503. * @see afterValidate
  5504. */
  5505. Yii.CModel.prototype.validate = function (attributes, clearErrors) {
  5506. var i, limit, validatorList, validator;
  5507. if (attributes === undefined) {
  5508. attributes = null;
  5509. }
  5510. if (clearErrors === undefined) {
  5511. clearErrors = true;
  5512. }
  5513. if (clearErrors) {
  5514. this.clearErrors();
  5515. }
  5516. if(this.beforeValidate()) {
  5517. validatorList = this.getValidators();
  5518. limit = validatorList.length;
  5519. for (i = 0; i < limit; i++) {
  5520. validator = validatorList[i];
  5521. validator.validate(this,attributes);
  5522. }
  5523. this.afterValidate();
  5524. return !this.hasErrors();
  5525. }
  5526. else {
  5527. return false;
  5528. }
  5529. };
  5530. /**
  5531. * This method is invoked after a model instance is created by new operator.
  5532. * The default implementation raises the {@link onAfterConstruct} event.
  5533. * You may override this method to do postprocessing after model creation.
  5534. * Make sure you call the parent implementation so that the event is raised properly.
  5535. */
  5536. Yii.CModel.prototype.afterConstruct = function () {
  5537. if(this.hasEventHandler('onAfterConstruct')) {
  5538. this.onAfterConstruct(new Yii.CEvent(this));
  5539. }
  5540. };
  5541. /**
  5542. * This method is invoked before validation starts.
  5543. * The default implementation calls {@link onBeforeValidate} to raise an event.
  5544. * You may override this method to do preliminary checks before validation.
  5545. * Make sure the parent implementation is invoked so that the event can be raised.
  5546. * @returns {Boolean} whether validation should be executed. Defaults to true.
  5547. * If false is returned, the validation will stop and the model is considered invalid.
  5548. */
  5549. Yii.CModel.prototype.beforeValidate = function () {
  5550. var event;
  5551. event=new Yii.CModelEvent(this);
  5552. this.onBeforeValidate(event);
  5553. return event.isValid;
  5554. };
  5555. /**
  5556. * This method is invoked after validation ends.
  5557. * The default implementation calls {@link onAfterValidate} to raise an event.
  5558. * You may override this method to do postprocessing after validation.
  5559. * Make sure the parent implementation is invoked so that the event can be raised.
  5560. */
  5561. Yii.CModel.prototype.afterValidate = function () {
  5562. this.onAfterValidate(new Yii.CEvent(this));
  5563. };
  5564. /**
  5565. * This event is raised after the model instance is created by new operator.
  5566. * @param {Yii.CEvent} event the event parameter
  5567. * @since 1.0.2
  5568. */
  5569. Yii.CModel.prototype.onAfterConstruct = function (event) {
  5570. this.raiseEvent('onAfterConstruct',event);
  5571. };
  5572. /**
  5573. * This event is raised before the validation is performed.
  5574. * @param {Yii.CModelEvent} event the event parameter
  5575. * @since 1.0.2
  5576. */
  5577. Yii.CModel.prototype.onBeforeValidate = function (event) {
  5578. this.raiseEvent('onBeforeValidate',event);
  5579. };
  5580. /**
  5581. * This event is raised after the validation is performed.
  5582. * @param {Yii.CEvent} event the event parameter
  5583. * @since 1.0.2
  5584. */
  5585. Yii.CModel.prototype.onAfterValidate = function (event) {
  5586. this.raiseEvent('onAfterValidate',event);
  5587. };
  5588. /**
  5589. * Returns all the validators declared in the model.
  5590. * This method differs from {@link getValidators} in that the latter
  5591. * would only return the validators applicable to the current {@link scenario}.
  5592. * Also, since this method return a {@link CList} object, you may
  5593. * manipulate it by inserting or removing validators (useful in behaviors).
  5594. * For example, <code>$model->validatorList->add($newValidator)</code>.
  5595. * The change made to the {@link CList} object will persist and reflect
  5596. * in the result of the next call of {@link getValidators}.
  5597. * @returns {Yii.CList} all the validators declared in the model.
  5598. * @since 1.1.2
  5599. */
  5600. Yii.CModel.prototype.getValidatorList = function () {
  5601. if(this._validators===null) {
  5602. this._validators=this.createValidators();
  5603. }
  5604. return this._validators;
  5605. };
  5606. /**
  5607. * Returns the validators applicable to the current {@link scenario}.
  5608. * @param {String} attribute the name of the attribute whose validators should be returned.
  5609. * If this is null, the validators for ALL attributes in the model will be returned.
  5610. * @returns {Array} the validators applicable to the current {@link scenario}.
  5611. * @since 1.0.1
  5612. */
  5613. Yii.CModel.prototype.getValidators = function (attribute) {
  5614. var validators, scenario, i, limit, validator;
  5615. if (attribute === undefined) {
  5616. attribute = null;
  5617. }
  5618. if(this._validators===null) {
  5619. this._validators=this.createValidators();
  5620. }
  5621. validators=[];
  5622. scenario=this.getScenario();
  5623. limit = this._validators.length;
  5624. for (i = 0; i < limit; i++) {
  5625. validator = this._validators[i];
  5626. if(validator.applyTo(scenario)) {
  5627. if(attribute===null || php.in_array(attribute,validator.attributes,true)) {
  5628. validators.push(validator);
  5629. }
  5630. }
  5631. }
  5632. return validators;
  5633. };
  5634. /**
  5635. * Creates validator objects based on the specification in {@link rules}.
  5636. * This method is mainly used internally.
  5637. * @returns {Yii.CList} validators built based on {@link rules()}.
  5638. */
  5639. Yii.CModel.prototype.createValidators = function () {
  5640. var validators, i, ruleList, rule, validator, validatorName = null, attributes = null;
  5641. validators=[];
  5642. ruleList = this.rules();
  5643. for (i in ruleList) {
  5644. if (ruleList.hasOwnProperty(i)) {
  5645. rule = ruleList[i];
  5646. attributes = rule.attributes;
  5647. delete rule.attributes;
  5648. validatorName = rule.validator;
  5649. delete rule.validator;
  5650. if(attributes !== undefined && validatorName !== undefined) { // attributes, validator name
  5651. validator = new Yii.CValidator();
  5652. validators.push(validator.createValidator(validatorName,this,attributes,rule));
  5653. }
  5654. else {
  5655. throw new Yii.CException(Yii.t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.',
  5656. {'{class}':php.get_class(this)}));
  5657. }
  5658. }
  5659. }
  5660. return validators;
  5661. };
  5662. /**
  5663. * Returns a value indicating whether the attribute is required.
  5664. * This is determined by checking if the attribute is associated with a
  5665. * {@link CRequiredValidator} validation rule in the current {@link scenario}.
  5666. * @param {String} attribute attribute name
  5667. * @returns {Boolean} whether the attribute is required
  5668. * @since 1.0.2
  5669. */
  5670. Yii.CModel.prototype.isAttributeRequired = function (attribute) {
  5671. var i, validatorList, validator;
  5672. validatorList = this.getValidators(attribute);
  5673. for (i in validatorList) {
  5674. if (validatorList.hasOwnProperty(i)) {
  5675. validator = validatorList[i];
  5676. if(validator instanceof Yii.CRequiredValidator) {
  5677. return true;
  5678. }
  5679. }
  5680. }
  5681. return false;
  5682. };
  5683. /**
  5684. * Returns a value indicating whether the attribute is safe for massive assignments.
  5685. * @param {String} attribute attribute name
  5686. * @returns {Boolean} whether the attribute is safe for massive assignments
  5687. * @since 1.1
  5688. */
  5689. Yii.CModel.prototype.isAttributeSafe = function (attribute) {
  5690. var attributes;
  5691. attributes=this.getSafeAttributeNames();
  5692. return php.in_array(attribute,attributes);
  5693. };
  5694. /**
  5695. * Returns the text label for the specified attribute.
  5696. * @param {String} attribute the attribute name
  5697. * @returns {String} the attribute label
  5698. * @see generateAttributeLabel
  5699. * @see attributeLabels
  5700. */
  5701. Yii.CModel.prototype.getAttributeLabel = function (attribute) {
  5702. var labels;
  5703. labels=this.attributeLabels();
  5704. if(labels[attribute] !== undefined) {
  5705. return labels[attribute];
  5706. }
  5707. else {
  5708. return this.generateAttributeLabel(attribute);
  5709. }
  5710. };
  5711. /**
  5712. * Returns a value indicating whether there is any validation error.
  5713. * @param {String} attribute attribute name. Use null to check all attributes.
  5714. * @returns {Boolean} whether there is any error.
  5715. */
  5716. Yii.CModel.prototype.hasErrors = function (attribute) {
  5717. var i;
  5718. if (attribute === undefined) {
  5719. attribute = null;
  5720. }
  5721. if(attribute===null) {
  5722. for (i in this._errors) {
  5723. if (this._errors.hasOwnProperty(i)) {
  5724. return true;
  5725. }
  5726. }
  5727. return false;
  5728. }
  5729. else {
  5730. return this._errors[attribute] !== undefined;
  5731. }
  5732. };
  5733. /**
  5734. * Returns the errors for all attribute or a single attribute.
  5735. * @param {String} attribute attribute name. Use null to retrieve errors for all attributes.
  5736. * @returns {Array} errors for all attributes or the specified attribute. Empty array is returned if no error.
  5737. */
  5738. Yii.CModel.prototype.getErrors = function (attribute) {
  5739. if (attribute === undefined) {
  5740. attribute = null;
  5741. }
  5742. if(attribute===null) {
  5743. return this._errors;
  5744. }
  5745. else {
  5746. return this._errors[attribute] !== undefined ? this._errors[attribute] : [];
  5747. }
  5748. };
  5749. /**
  5750. * Returns the first error of the specified attribute.
  5751. * @param {String} attribute attribute name.
  5752. * @returns {String} the error message. Null is returned if no error.
  5753. * @since 1.0.2
  5754. */
  5755. Yii.CModel.prototype.getError = function (attribute) {
  5756. return this._errors[attribute] !== undefined ? php.reset(this._errors[attribute]) : null;
  5757. };
  5758. /**
  5759. * Adds a new error to the specified attribute.
  5760. * @param {String} attribute attribute name
  5761. * @param {String} error new error message
  5762. */
  5763. Yii.CModel.prototype.addError = function (attribute, error) {
  5764. if (this._errors[attribute] === undefined) {
  5765. this._errors[attribute] = [];
  5766. }
  5767. this._errors[attribute].push(error);
  5768. };
  5769. /**
  5770. * Adds a list of errors.
  5771. * @param {Array} errors a list of errors. The array keys must be attribute names.
  5772. * The array values should be error messages. If an attribute has multiple errors,
  5773. * these errors must be given in terms of an array.
  5774. * You may use the result of {@link getErrors} as the value for this parameter.
  5775. * @since 1.0.5
  5776. */
  5777. Yii.CModel.prototype.addErrors = function (errors) {
  5778. var error, i, attribute, e;
  5779. for (attribute in errors) {
  5780. if (errors.hasOwnProperty(attribute)) {
  5781. error = errors[attribute];
  5782. if(Object.prototype.toString.call(error) === '[object Array]') {
  5783. for (i in error) {
  5784. if (error.hasOwnProperty(i)) {
  5785. e = error[i];
  5786. if (this._errors[attribute] === undefined) {
  5787. this._errors[attribute] = [];
  5788. }
  5789. this._errors[attribute].push(e);
  5790. }
  5791. }
  5792. }
  5793. else {
  5794. if (this._errors[attribute] === undefined) {
  5795. this._errors[attribute] = [];
  5796. }
  5797. this._errors[attribute].push(error);
  5798. }
  5799. }
  5800. }
  5801. };
  5802. /**
  5803. * Removes errors for all attributes or a single attribute.
  5804. * @param {String} attribute attribute name. Use null to remove errors for all attribute.
  5805. */
  5806. Yii.CModel.prototype.clearErrors = function (attribute) {
  5807. if (attribute === undefined) {
  5808. attribute = null;
  5809. }
  5810. if(attribute===null) {
  5811. this._errors={};
  5812. }
  5813. else {
  5814. delete this._errors[attribute];
  5815. }
  5816. };
  5817. /**
  5818. * Generates a user friendly attribute label.
  5819. * This is done by replacing underscores or dashes with blanks and
  5820. * changing the first letter of each word to upper case.
  5821. * For example, 'department_name' or 'DepartmentName' becomes 'Department Name'.
  5822. * @param {String} name the column name
  5823. * @returns {String} the attribute label
  5824. */
  5825. Yii.CModel.prototype.generateAttributeLabel = function (name) {
  5826. return php.trim(name.replace(/([A-Z])/g, ' $1').replace(/_|-|\./g, ' ')).replace(/^./, function (str) {
  5827. return str.toUpperCase();
  5828. }
  5829. );
  5830. };
  5831. /**
  5832. * Returns all attribute values.
  5833. * @param {Array} names list of attributes whose value needs to be returned.
  5834. * Defaults to null, meaning all attributes as listed in {@link attributeNames} will be returned.
  5835. * If it is an array, only the attributes in the array will be returned.
  5836. * @returns {Array} attribute values (name=>value).
  5837. */
  5838. Yii.CModel.prototype.getAttributes = function (names) {
  5839. var values, i, nameList, name, values2, n;
  5840. if (names === undefined) {
  5841. names = null;
  5842. }
  5843. values={};
  5844. nameList = this.attributeNames();
  5845. for (i in nameList) {
  5846. if (nameList.hasOwnProperty(i)) {
  5847. name = nameList[i];
  5848. values[name]=this.name;
  5849. }
  5850. }
  5851. if(Object.prototype.toString.call(names) === '[object Array]') {
  5852. values2=[];
  5853. for (n in names) {
  5854. if (names.hasOwnProperty(n)) {
  5855. name = names[n];
  5856. values2[name] = (values[name] !== undefined ? values[name] : null);
  5857. }
  5858. }
  5859. return values2;
  5860. }
  5861. else {
  5862. return values;
  5863. }
  5864. };
  5865. /**
  5866. * Sets the attribute values in a massive way.
  5867. * @param {Array} values attribute values (name=>value) to be set.
  5868. * @param {Boolean} safeOnly whether the assignments should only be done to the safe attributes.
  5869. * A safe attribute is one that is associated with a validation rule in the current {@link scenario}.
  5870. * @see getSafeAttributeNames
  5871. * @see attributeNames
  5872. */
  5873. Yii.CModel.prototype.setAttributes = function (values, safeOnly) {
  5874. var attributes, name, value;
  5875. if (safeOnly === undefined) {
  5876. safeOnly = true;
  5877. }
  5878. if(!values instanceof Object) {
  5879. return;
  5880. }
  5881. attributes=php.array_flip(safeOnly ? this.getSafeAttributeNames() : this.attributeNames());
  5882. for (name in values) {
  5883. if (values.hasOwnProperty(name)) {
  5884. value = values[name];
  5885. if(attributes[name] !== undefined) {
  5886. this.name=value;
  5887. }
  5888. else if(safeOnly) {
  5889. this.onUnsafeAttribute(name,value);
  5890. }
  5891. }
  5892. }
  5893. };
  5894. /**
  5895. * Unsets the attributes.
  5896. * @param {Array} names list of attributes to be set null. If this parameter is not given,
  5897. * all attributes as specified by {@link attributeNames} will have their values unset.
  5898. * @since 1.1.3
  5899. */
  5900. Yii.CModel.prototype.unsetAttributes = function (names) {
  5901. var i, name;
  5902. if (names === undefined) {
  5903. names = null;
  5904. }
  5905. if(names===null) {
  5906. names=this.attributeNames();
  5907. }
  5908. for (i in names) {
  5909. if (names.hasOwnProperty(i)) {
  5910. name = names[i];
  5911. this.name=null;
  5912. }
  5913. }
  5914. };
  5915. /**
  5916. * This method is invoked when an unsafe attribute is being massively assigned.
  5917. * The default implementation will log a warning message if YII_DEBUG is on.
  5918. * It does nothing otherwise.
  5919. * @param {String} name the unsafe attribute name
  5920. * @param {Mixed} value the attribute value
  5921. * @since 1.1.1
  5922. */
  5923. Yii.CModel.prototype.onUnsafeAttribute = function (name, value) {
  5924. if(YII_DEBUG) {
  5925. Yii.log(Yii.t('yii','Failed to set unsafe attribute "{attribute}".',{'{attribute}':name}),Yii.CLogger.LEVEL_WARNING);
  5926. }
  5927. };
  5928. /**
  5929. * Returns the scenario that this model is used in.
  5930. *
  5931. * Scenario affects how validation is performed and which attributes can
  5932. * be massively assigned.
  5933. *
  5934. * A validation rule will be performed when calling {@link validate()}
  5935. * if its 'on' option is not set or contains the current scenario value.
  5936. *
  5937. * And an attribute can be massively assigned if it is associated with
  5938. * a validation rule for the current scenario. Note that an exception is
  5939. * the {@link CUnsafeValidator unsafe} validator which marks the associated
  5940. * attributes as unsafe and not allowed to be massively assigned.
  5941. *
  5942. * @returns {String} the scenario that this model is in.
  5943. * @since 1.0.4
  5944. */
  5945. Yii.CModel.prototype.getScenario = function () {
  5946. return this._scenario;
  5947. };
  5948. /**
  5949. * Sets the scenario for the model.
  5950. * @param {String} value the scenario that this model is in.
  5951. * @see getScenario
  5952. * @since 1.0.4
  5953. */
  5954. Yii.CModel.prototype.setScenario = function (value) {
  5955. this._scenario=value;
  5956. };
  5957. /**
  5958. * Returns the attribute names that are safe to be massively assigned.
  5959. * A safe attribute is one that is associated with a validation rule in the current {@link scenario}.
  5960. * @returns {Array} safe attribute names
  5961. * @since 1.0.2
  5962. */
  5963. Yii.CModel.prototype.getSafeAttributeNames = function () {
  5964. var attributes, unsafe, i, validatorList, validator, n, name, j, k;
  5965. attributes=[];
  5966. unsafe=[];
  5967. validatorList = this.getValidators();
  5968. for (i in validatorList) {
  5969. if (validatorList.hasOwnProperty(i)) {
  5970. validator = validatorList[i];
  5971. if(!validator.safe) {
  5972. for (n in validator.attributes) {
  5973. if (validator.attributes.hasOwnProperty(n)) {
  5974. name = validator.attributes[n];
  5975. unsafe.push(name);
  5976. }
  5977. }
  5978. }
  5979. else
  5980. {
  5981. for (j in validator.attributes) {
  5982. if (validator.attributes.hasOwnProperty(j)) {
  5983. name = validator.attributes[j];
  5984. attributes[name]=true;
  5985. }
  5986. }
  5987. }
  5988. }
  5989. }
  5990. for (k in unsafe) {
  5991. if (unsafe.hasOwnProperty(k)) {
  5992. name = unsafe[k];
  5993. delete attributes[name];
  5994. }
  5995. }
  5996. return php.array_keys(attributes);
  5997. };
  5998. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  5999. /**
  6000. * CModelBehavior is a base class for behaviors that are attached to a model component.
  6001. * The model should extend from {@link CModel} or its child classes.
  6002. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  6003. * @version $Id: CModelBehavior.php 2799 2011-01-01 19:31:13Z qiang.xue $
  6004. * @package system.base
  6005. * @since 1.0.2
  6006. * @author Charles Pick
  6007. * @class
  6008. * @extends Yii.CBehavior
  6009. */
  6010. Yii.CModelBehavior = function CModelBehavior() {
  6011. };
  6012. Yii.CModelBehavior.prototype = new Yii.CBehavior();
  6013. Yii.CModelBehavior.prototype.constructor = Yii.CModelBehavior;
  6014. /**
  6015. * Declares events and the corresponding event handler methods.
  6016. * The default implementation returns 'onBeforeValidate' and 'onAfterValidate' events and handlers.
  6017. * If you override this method, make sure you merge the parent result to the return value.
  6018. * @returns {Object} events (keys) and the corresponding event handler methods (values).
  6019. * @see CBehavior::events
  6020. */
  6021. Yii.CModelBehavior.prototype.events = function () {
  6022. return {
  6023. 'onAfterConstruct':'afterConstruct',
  6024. 'onBeforeValidate':'beforeValidate',
  6025. 'onAfterValidate':'afterValidate'
  6026. };
  6027. };
  6028. /**
  6029. * Responds to {@link CModel::onAfterConstruct} event.
  6030. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  6031. * @param {Yii.CEvent} event event parameter
  6032. */
  6033. Yii.CModelBehavior.prototype.afterConstruct = function (event) {
  6034. };
  6035. /**
  6036. * Responds to {@link CModel::onBeforeValidate} event.
  6037. * Overrides this method if you want to handle the corresponding event of the {@link owner}.
  6038. * You may set {@link CModelEvent::isValid} to be false to quit the validation process.
  6039. * @param {Yii.CModelEvent} event event parameter
  6040. */
  6041. Yii.CModelBehavior.prototype.beforeValidate = function (event) {
  6042. };
  6043. /**
  6044. * Responds to {@link CModel::onAfterValidate} event.
  6045. * Overrides this method if you want to handle the corresponding event of the {@link owner}.
  6046. * @param {Yii.CEvent} event event parameter
  6047. */
  6048. Yii.CModelBehavior.prototype.afterValidate = function (event) {
  6049. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6050. /**
  6051. * CModelEvent class.
  6052. *
  6053. * CModelEvent represents the event parameters needed by events raised by a model.
  6054. *
  6055. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  6056. * @version $Id: CModelEvent.php 2799 2011-01-01 19:31:13Z qiang.xue $
  6057. * @package system.base
  6058. * @since 1.0
  6059. * @author Charles Pick
  6060. * @class
  6061. * @extends Yii.CEvent
  6062. */
  6063. Yii.CModelEvent = function CModelEvent () {
  6064. };
  6065. Yii.CModelEvent.prototype = new Yii.CEvent();
  6066. Yii.CModelEvent.prototype.constructor = Yii.CModelEvent;
  6067. /**
  6068. * @var {Boolean} whether the model is in valid status and should continue its normal method execution cycles. Defaults to true.
  6069. * For example, when this event is raised in a {@link CFormModel} object that is executing {@link CModel::beforeValidate},
  6070. * if this property is set false by the event handler, the {@link CModel::validate} method will quit after handling this event.
  6071. * If true, the normal execution cycles will continue, including performing the real validations and calling
  6072. * {@link CModel::afterValidate}.
  6073. */
  6074. Yii.CModelEvent.prototype.isValid = true;
  6075. /**
  6076. * @var {Yii.CDbCrireria} the query criteria that is passed as a parameter to a find method of {@link CActiveRecord}.
  6077. * Note that this property is only used by {@link CActiveRecord::onBeforeFind} event.
  6078. * This property could be null.
  6079. * @since 1.1.5
  6080. */
  6081. Yii.CModelEvent.prototype.criteria = null;/*global Yii, php, sjcl, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6082. /**
  6083. * CSecurityManager provides private keys, hashing and encryption functions.
  6084. *
  6085. * CSecurityManager is used by Yii components and applications for security-related purpose.
  6086. * For example, it is used in cookie validation feature to prevent cookie data
  6087. * from being tampered.
  6088. *
  6089. * CSecurityManager is mainly used to protect data from being tampered and viewed.
  6090. * It can generate HMAC and encrypt the data. The private key used to generate HMAC
  6091. * is set by {@link setValidationKey ValidationKey}. The key used to encrypt data is
  6092. * specified by {@link setEncryptionKey EncryptionKey}. If the above keys are not
  6093. * explicitly set, random keys will be generated and used.
  6094. *
  6095. * To protected data with HMAC, call {@link hashData()}; and to check if the data
  6096. * is tampered, call {@link validateData()}, which will return the real data if
  6097. * it is not tampered. The algorithm used to generated HMAC is specified by
  6098. * {@link validation}.
  6099. *
  6100. * To encrypt and decrypt data, call {@link encrypt()} and {@link decrypt()}
  6101. * respectively, which uses 3DES encryption algorithm. Note, the PHP Mcrypt
  6102. * extension must be installed and loaded.
  6103. *
  6104. * CSecurityManager is a core application component that can be accessed via
  6105. * {@link CApplication::getSecurityManager()}.
  6106. *
  6107. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  6108. * @version $Id: CSecurityManager.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  6109. * @package system.base
  6110. * @since 1.0
  6111. * @author Charles Pick
  6112. * @class
  6113. * @extends Yii.CApplicationComponent
  6114. */
  6115. Yii.CSecurityManager = function CSecurityManager() {
  6116. };
  6117. Yii.CSecurityManager.prototype = new Yii.CApplicationComponent();
  6118. Yii.CSecurityManager.prototype.constructor = Yii.CSecurityManager;
  6119. /**
  6120. * @const
  6121. */
  6122. Yii.CSecurityManager.STATE_VALIDATION_KEY = 'Yii.CSecurityManager.validationkey';
  6123. /**
  6124. * @const
  6125. */
  6126. Yii.CSecurityManager.STATE_ENCRYPTION_KEY = 'Yii.CSecurityManager.encryptionkey';
  6127. /**
  6128. * @var {String} the name of the hashing algorithm to be used by {@link computeHMAC}.
  6129. *
  6130. * Defaults to 'sha1', meaning using SHA1 hash algorithm.
  6131. * @since 1.1.3
  6132. */
  6133. Yii.CSecurityManager.prototype.hashAlgorithm = 'sha1';
  6134. Yii.CSecurityManager.prototype._validationKey = null;
  6135. Yii.CSecurityManager.prototype._encryptionKey = null;
  6136. /**
  6137. * @returns {String} a randomly generated private key
  6138. */
  6139. Yii.CSecurityManager.prototype.generateRandomKey = function () {
  6140. return php.sprintf('%08x%08x%08x%08x',php.mt_rand(),php.mt_rand(),php.mt_rand(),php.mt_rand());
  6141. };
  6142. /**
  6143. * @returns {String} the private key used to generate HMAC.
  6144. * If the key is not explicitly set, a random one is generated and returned.
  6145. */
  6146. Yii.CSecurityManager.prototype.getValidationKey = function () {
  6147. var key;
  6148. if(this._validationKey!==null) {
  6149. return this._validationKey;
  6150. }
  6151. else {
  6152. if((key=Yii.app().getGlobalState(this.STATE_VALIDATION_KEY))!==null) {
  6153. this.setValidationKey(key);
  6154. }
  6155. else {
  6156. key=this.generateRandomKey();
  6157. this.setValidationKey(key);
  6158. Yii.app().setGlobalState(this.STATE_VALIDATION_KEY,key);
  6159. }
  6160. return this._validationKey;
  6161. }
  6162. };
  6163. /**
  6164. * @param {String} value the key used to generate HMAC
  6165. * @throws {Yii.CException} if the key is empty
  6166. */
  6167. Yii.CSecurityManager.prototype.setValidationKey = function (value) {
  6168. if(!php.empty(value)) {
  6169. this._validationKey=value;
  6170. }
  6171. else {
  6172. throw new Yii.CException(Yii.t('yii','CSecurityManager.validationKey cannot be empty.'));
  6173. }
  6174. };
  6175. /**
  6176. * @returns {String} the private key used to encrypt/decrypt data.
  6177. * If the key is not explicitly set, a random one is generated and returned.
  6178. */
  6179. Yii.CSecurityManager.prototype.getEncryptionKey = function () {
  6180. var key;
  6181. if(this._encryptionKey!==null) {
  6182. return this._encryptionKey;
  6183. }
  6184. else {
  6185. if((key=Yii.app().getGlobalState(this.STATE_ENCRYPTION_KEY))!==null) {
  6186. this.setEncryptionKey(key);
  6187. }
  6188. else {
  6189. key=this.generateRandomKey();
  6190. this.setEncryptionKey(key);
  6191. Yii.app().setGlobalState(this.STATE_ENCRYPTION_KEY,key);
  6192. }
  6193. return this._encryptionKey;
  6194. }
  6195. };
  6196. /**
  6197. * @param {String} value the key used to encrypt/decrypt data.
  6198. * @throws {Yii.CException} if the key is empty
  6199. */
  6200. Yii.CSecurityManager.prototype.setEncryptionKey = function (value) {
  6201. if(!php.empty(value)) {
  6202. this._encryptionKey=value;
  6203. }
  6204. else {
  6205. throw new Yii.CException(Yii.t('yii','CSecurityManager.encryptionKey cannot be empty.'));
  6206. }
  6207. };
  6208. /**
  6209. * This method has been deprecated since version 1.1.3.
  6210. * Please use {@link hashAlgorithm} instead.
  6211. */
  6212. Yii.CSecurityManager.prototype.getValidation = function () {
  6213. return this.hashAlgorithm;
  6214. };
  6215. /**
  6216. * This method has been deprecated since version 1.1.3.
  6217. * Please use {@link hashAlgorithm} instead.
  6218. * @param {String} value -
  6219. */
  6220. Yii.CSecurityManager.prototype.setValidation = function (value) {
  6221. this.hashAlgorithm=value;
  6222. };
  6223. /**
  6224. * Encrypts data.
  6225. * @param {String} data data to be encrypted.
  6226. * @param {String} key the decryption key. This defaults to null, meaning using {@link getEncryptionKey EncryptionKey}.
  6227. * @returns {String} the encrypted data
  6228. * @throws {Yii.CException} if PHP Mcrypt extension is not loaded
  6229. */
  6230. Yii.CSecurityManager.prototype.encrypt = function (data, key) {
  6231. var module, iv, encrypted;
  6232. if (key === undefined) {
  6233. key = null;
  6234. }
  6235. module=this.openCryptModule();
  6236. key=key===null ? php.md5(this.getEncryptionKey()) : key;
  6237. encrypted = module.encrypt(key, data);
  6238. return encrypted;
  6239. };
  6240. /**
  6241. * Decrypts data
  6242. * @param {String} data data to be decrypted.
  6243. * @param {String} key the decryption key. This defaults to null, meaning using {@link getEncryptionKey EncryptionKey}.
  6244. * @returns {String} the decrypted data
  6245. * @throws {Yii.CException} if PHP Mcrypt extension is not loaded
  6246. */
  6247. Yii.CSecurityManager.prototype.decrypt = function (data, key) {
  6248. var module, ivSize, iv, decrypted;
  6249. if (key === undefined) {
  6250. key = null;
  6251. }
  6252. module=this.openCryptModule();
  6253. key=key===null ? php.md5(this.getEncryptionKey()) : key;
  6254. decrypted = module.decrypt(key, data);
  6255. return decrypted;
  6256. };
  6257. /**
  6258. * Opens the mcrypt module with the configuration specified in {@link cryptAlgorithm}.
  6259. * @returns {Resource} the mycrypt module handle.
  6260. * @since 1.1.3
  6261. */
  6262. Yii.CSecurityManager.prototype.openCryptModule = function () {
  6263. var module;
  6264. if(sjcl !== undefined) {
  6265. return sjcl;
  6266. }
  6267. else {
  6268. throw new Yii.CException(Yii.t('yii','CSecurityManager requires the Stanford Javascript Crypto Library to be loaded in order to use data encryption feature.'));
  6269. }
  6270. };
  6271. /**
  6272. * Prefixes data with an HMAC.
  6273. * @param {String} data data to be hashed.
  6274. * @param {String} key the private key to be used for generating HMAC. Defaults to null, meaning using {@link validationKey}.
  6275. * @returns {String} data prefixed with HMAC
  6276. */
  6277. Yii.CSecurityManager.prototype.hashData = function (data, key) {
  6278. if (key === undefined) {
  6279. key = null;
  6280. }
  6281. return this.computeHMAC(data,key)+data;
  6282. };
  6283. /**
  6284. * Validates if data is tampered.
  6285. * @param {String} data data to be validated. The data must be previously
  6286. * generated using {@link hashData()}.
  6287. * @param {String} key the private key to be used for generating HMAC. Defaults to null, meaning using {@link validationKey}.
  6288. * @returns {String} the real data with HMAC stripped off. False if the data
  6289. * is tampered.
  6290. */
  6291. Yii.CSecurityManager.prototype.validateData = function (data, key) {
  6292. var len, hmac, data2;
  6293. if (key === undefined) {
  6294. key = null;
  6295. }
  6296. len=php.strlen(this.computeHMAC('test'));
  6297. if(php.strlen(data)>=len) {
  6298. hmac=data.slice(0, len);
  6299. data2=data.slice(len);
  6300. return hmac===this.computeHMAC(data2,key)?data2:false;
  6301. }
  6302. else {
  6303. return false;
  6304. }
  6305. };
  6306. /**
  6307. * Computes the HMAC for the data with {@link getValidationKey ValidationKey}.
  6308. * @param {String} data data to be generated HMAC
  6309. * @param {String} key the private key to be used for generating HMAC. Defaults to null, meaning using {@link validationKey}.
  6310. * @returns {String} the HMAC for the data
  6311. */
  6312. Yii.CSecurityManager.prototype.computeHMAC = function (data, key) {
  6313. var pack, func, hmac;
  6314. if (key === undefined) {
  6315. key = null;
  6316. }
  6317. if(key===null) {
  6318. key=this.getValidationKey();
  6319. }
  6320. hmac = new sjcl.misc.hmac(key);
  6321. return php.md5(hmac.encrypt(data).join(""));
  6322. };
  6323. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6324. /**
  6325. * CStatePersister implements a file-based persistent data storage.
  6326. *
  6327. * It can be used to keep data available through multiple requests and sessions.
  6328. *
  6329. * By default, CStatePersister stores data in a file named 'state.bin' that is located
  6330. * under the application {@link CApplication::getRuntimePath runtime path}.
  6331. * You may change the location by setting the {@link stateFile} property.
  6332. *
  6333. * To retrieve the data from CStatePersister, call {@link load()}. To save the data,
  6334. * call {@link save()}.
  6335. *
  6336. * Comparison among state persister, session and cache is as follows:
  6337. * <ul>
  6338. * <li>session: data persisting within a single user session.</li>
  6339. * <li>state persister: data persisting through all requests/sessions (e.g. hit counter).</li>
  6340. * <li>cache: volatile and fast storage. It may be used as storage medium for session or state persister.</li>
  6341. * </ul>
  6342. *
  6343. * Since server resource is often limited, be cautious if you plan to use CStatePersister
  6344. * to store large amount of data. You should also consider using database-based persister
  6345. * to improve the throughput.
  6346. *
  6347. * CStatePersister is a core application component used to store global application state.
  6348. * It may be accessed via {@link CApplication::getStatePersister()}.
  6349. * page state persistent method based on cache.
  6350. *
  6351. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  6352. * @version $Id: CStatePersister.php 3165 2011-04-06 08:27:40Z mdomba $
  6353. * @package system.base
  6354. * @since 1.0
  6355. * @author Charles Pick
  6356. * @class
  6357. * @extends Yii.CApplicationComponent
  6358. */
  6359. Yii.CStatePersister = function CStatePersister() {
  6360. };
  6361. Yii.CStatePersister.prototype = new Yii.CApplicationComponent();
  6362. Yii.CStatePersister.prototype.constructor = Yii.CStatePersister;
  6363. /**
  6364. * Initializes the component.
  6365. * This method overrides the parent implementation by making sure the
  6366. * browser supports localStorage
  6367. */
  6368. Yii.CStatePersister.prototype.init = function () {
  6369. Yii.CApplicationComponent.prototype.init.call(this);
  6370. try {
  6371. return "localStorage" in window && window.localStorage !== null;
  6372. }
  6373. catch (e) {
  6374. throw new Yii.CException(Yii.t('yii','Unable to access local storage, please ensure that you\'re using a modern browser!'));
  6375. }
  6376. };
  6377. /**
  6378. * Loads state data from persistent storage.
  6379. * @returns {Mixed} state data. Null if no state data available.
  6380. */
  6381. Yii.CStatePersister.prototype.load = function () {
  6382. var state = {}, i, value;
  6383. if(window.localStorage.length !== 0) {
  6384. for (i in window.localStorage) {
  6385. if (window.localStorage.hasOwnProperty(i)) {
  6386. try {
  6387. state[i] = Yii.CJSON.decode(window.localStorage[i]);
  6388. }
  6389. catch (e) {
  6390. state[i] = window.localStorage[i];
  6391. }
  6392. }
  6393. }
  6394. return state;
  6395. }
  6396. else {
  6397. return null;
  6398. }
  6399. };
  6400. /**
  6401. * Saves application state in persistent storage.
  6402. * @param {Mixed} state state data (must be serializable).
  6403. */
  6404. Yii.CStatePersister.prototype.save = function (state) {
  6405. var i;
  6406. window.localStorage.clear();
  6407. for(i in state) {
  6408. if (state.hasOwnProperty(i)) {
  6409. window.localStorage[i] = Yii.CJSON.encode(state[i]);
  6410. }
  6411. }
  6412. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6413. /**
  6414. * CCache is the base class for cache classes with different cache storage implementation.
  6415. *
  6416. * A data item can be stored in cache by calling {@link set} and be retrieved back
  6417. * later by {@link get}. In both operations, a key identifying the data item is required.
  6418. * An expiration time and/or a dependency can also be specified when calling {@link set}.
  6419. * If the data item expires or the dependency changes, calling {@link get} will not
  6420. * return back the data item.
  6421. *
  6422. * Note, by definition, cache does not ensure the existence of a value
  6423. * even if it does not expire. Cache is not meant to be a persistent storage.
  6424. *
  6425. * CCache implements the interface {@link ICache} with the following methods:
  6426. * <ul>
  6427. * <li>{@link get} : retrieve the value with a key (if any) from cache</li>
  6428. * <li>{@link set} : store the value with a key into cache</li>
  6429. * <li>{@link add} : store the value only if cache does not have this key</li>
  6430. * <li>{@link delete} : delete the value with the specified key from cache</li>
  6431. * <li>{@link flush} : delete all values from cache</li>
  6432. * </ul>
  6433. *
  6434. * Child classes must implement the following methods:
  6435. * <ul>
  6436. * <li>{@link getValue}</li>
  6437. * <li>{@link setValue}</li>
  6438. * <li>{@link addValue}</li>
  6439. * <li>{@link deleteValue}</li>
  6440. * <li>{@link flush} (optional)</li>
  6441. * </ul>
  6442. *
  6443. * CCache also implements ArrayAccess so that it can be used like an array.
  6444. *
  6445. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  6446. * @version $Id: CCache.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  6447. * @package system.caching
  6448. * @since 1.0
  6449. * @author Charles Pick
  6450. * @class
  6451. * @extends Yii.CApplicationComponent
  6452. */
  6453. Yii.CCache = function CCache () {
  6454. };
  6455. Yii.CCache.prototype = new Yii.CApplicationComponent();
  6456. Yii.CCache.prototype.constructor = Yii.CCache;
  6457. /**
  6458. * @var {String} a string prefixed to every cache key so that it is unique. Defaults to {@link CApplication::getId() application ID}.
  6459. */
  6460. Yii.CCache.prototype.keyPrefix = null;
  6461. /**
  6462. * Initializes the application component.
  6463. * This method overrides the parent implementation by setting default cache key prefix.
  6464. */
  6465. Yii.CCache.prototype.init = function () {
  6466. Yii.CApplicationComponent.prototype.init.call(this);
  6467. if(this.keyPrefix===null) {
  6468. this.keyPrefix=Yii.app().getId();
  6469. }
  6470. };
  6471. /**
  6472. * @param {String} key a key identifying a value to be cached
  6473. * @returns {Sring} a key generated from the provided key which ensures the uniqueness across applications
  6474. */
  6475. Yii.CCache.prototype.generateUniqueKey = function (key) {
  6476. return php.md5(this.keyPrefix+key);
  6477. };
  6478. /**
  6479. * Retrieves a value from cache with a specified key.
  6480. * @param {String} id a key identifying the cached value
  6481. * @returns {Mixed} the value stored in cache, false if the value is not in the cache, expired or the dependency has changed.
  6482. */
  6483. Yii.CCache.prototype.get = function (id) {
  6484. var value, data;
  6485. if((value=this.getValue(this.generateUniqueKey(id)))!==false) {
  6486. data = value;
  6487. if (!data) {
  6488. return false;
  6489. }
  6490. if(Object.prototype.toString.call(data) !== '[object Array]') {
  6491. if (data.length > 0) {
  6492. try {
  6493. data = Yii.CJSON.decode(data);
  6494. }
  6495. catch (e) {
  6496. return false;
  6497. }
  6498. }
  6499. else {
  6500. return false;
  6501. }
  6502. }
  6503. if (false && data[1] !== undefined && data[1] !== {}) {
  6504. data[1] = Yii.createComponent(data[1]);
  6505. }
  6506. if(data[1] === null || !(data[1] instanceof Yii.CCacheDependency) || !data[1].getHasChanged()) {
  6507. Yii.trace('Serving "'+id+'" from cache','system.caching.'+this.getClassName());
  6508. return data[0];
  6509. }
  6510. }
  6511. return false;
  6512. };
  6513. /**
  6514. * Retrieves multiple values from cache with the specified keys.
  6515. * Some caches (such as memcache, apc) allow retrieving multiple cached values at one time,
  6516. * which may improve the performance since it reduces the communication cost.
  6517. * In case a cache doesn't support this feature natively, it will be simulated by this method.
  6518. * @param {Array} ids list of keys identifying the cached values
  6519. * @returns {Array} list of cached values corresponding to the specified keys. The array
  6520. * is returned in terms of (key,value) pairs.
  6521. * If a value is not cached or expired, the corresponding array value will be false.
  6522. * @since 1.0.8
  6523. */
  6524. Yii.CCache.prototype.mget = function (ids) {
  6525. var uniqueIDs, results, i, id, values, uniqueID, data;
  6526. uniqueIDs={};
  6527. results={};
  6528. for (i in ids) {
  6529. if (ids.hasOwnProperty(i)) {
  6530. id = ids[i];
  6531. uniqueIDs[id]=this.generateUniqueKey(id);
  6532. results[id]=false;
  6533. }
  6534. }
  6535. values=this.getValues(uniqueIDs);
  6536. for (id in uniqueIDs) {
  6537. if (uniqueIDs.hasOwnProperty(id)) {
  6538. uniqueID = uniqueIDs[id];
  6539. if(values[uniqueID] === undefined) {
  6540. continue;
  6541. }
  6542. data=Yii.CJSON.decode(values[uniqueID]);
  6543. data = value;
  6544. if(Object.prototype.toString.call(data) !== '[object Array]') {
  6545. if (data.length > 0) {
  6546. try {
  6547. data = Yii.CJSON.decode(data);
  6548. }
  6549. catch (e) {
  6550. return false;
  6551. }
  6552. }
  6553. else {
  6554. return false;
  6555. }
  6556. }
  6557. if (data[1] !== undefined && data[1] !== {}) {
  6558. data[1] = Yii.createComponent(data[1]);
  6559. }
  6560. if(!(data[1] instanceof Yii.CCacheDependency) || !data[1].getHasChanged()) {
  6561. Yii.trace('Serving "'+id+'" from cache','system.caching.'+this.getClassName());
  6562. results[id] = data[0];
  6563. }
  6564. }
  6565. }
  6566. return results;
  6567. };
  6568. /**
  6569. * Stores a value identified by a key into cache.
  6570. * If the cache already contains such a key, the existing value and
  6571. * expiration time will be replaced with the new ones.
  6572. *
  6573. * @param {String} id the key identifying the value to be cached
  6574. * @param {Mixed} value the value to be cached
  6575. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6576. * @param {ICacheDependency} dependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
  6577. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6578. */
  6579. Yii.CCache.prototype.set = function (id, value, expire, dependency) {
  6580. var data;
  6581. if (expire === undefined) {
  6582. expire = 0;
  6583. }
  6584. if (dependency === undefined) {
  6585. dependency = null;
  6586. }
  6587. Yii.trace('Saving "'+id+'" to cache','system.caching.'+this.getClassName());
  6588. if(dependency!==null) {
  6589. dependency.evaluateDependency();
  6590. }
  6591. data=[value,dependency];
  6592. return this.setValue(this.generateUniqueKey(id),Yii.CJSON.encode(data),expire);
  6593. };
  6594. /**
  6595. * Stores a value identified by a key into cache if the cache does not contain this key.
  6596. * Nothing will be done if the cache already contains the key.
  6597. * @param {String} id the key identifying the value to be cached
  6598. * @param {Mixed} value the value to be cached
  6599. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6600. * @param {ICacheDependency} dependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
  6601. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6602. */
  6603. Yii.CCache.prototype.add = function (id, value, expire, dependency) {
  6604. var data;
  6605. if (expire === undefined) {
  6606. expire = 0;
  6607. }
  6608. if (dependency === undefined) {
  6609. dependency = null;
  6610. }
  6611. Yii.trace('Adding "'+id+'" to cache','system.caching.'+this.getClassName());
  6612. if(dependency!==null) {
  6613. dependency.evaluateDependency();
  6614. }
  6615. data=[value,dependency];
  6616. return this.addValue(this.generateUniqueKey(id),Yii.CJSON.encode(data),expire);
  6617. };
  6618. /**
  6619. * Deletes a value with the specified key from cache
  6620. * @param {String} id the key of the value to be deleted
  6621. * @returns {Boolean} if no error happens during deletion
  6622. */
  6623. Yii.CCache.prototype.remove = function (id) {
  6624. Yii.trace('Deleting "'+id+'" from cache','system.caching.'+this.getClassName());
  6625. return this.deleteValue(this.generateUniqueKey(id));
  6626. };
  6627. /**
  6628. * Deletes all values from cache.
  6629. * Be careful of performing this operation if the cache is shared by multiple applications.
  6630. * @returns {Boolean} whether the flush operation was successful.
  6631. */
  6632. Yii.CCache.prototype.flush = function () {
  6633. Yii.trace('Flushing cache','system.caching.'+this.getClassName());
  6634. return this.flushValues();
  6635. };
  6636. /**
  6637. * Retrieves a value from cache with a specified key.
  6638. * This method should be implemented by child classes to retrieve the data
  6639. * from specific cache storage. The uniqueness and dependency are handled
  6640. * in {@link get()} already. So only the implementation of data retrieval
  6641. * is needed.
  6642. * @param {String} key a unique key identifying the cached value
  6643. * @returns {String} the value stored in cache, false if the value is not in the cache or expired.
  6644. * @throws {Yii.CException} if this method is not overridden by child classes
  6645. */
  6646. Yii.CCache.prototype.getValue = function (key) {
  6647. throw new Yii.CException(Yii.t('yii','{className} does not support get() functionality.',
  6648. {'{className}':this.getClassName()}));
  6649. };
  6650. /**
  6651. * Retrieves multiple values from cache with the specified keys.
  6652. * The default implementation simply calls {@link getValue} multiple
  6653. * times to retrieve the cached values one by one.
  6654. * If the underlying cache storage supports multiget, this method should
  6655. * be overridden to exploit that feature.
  6656. * @param {Array} keys a list of keys identifying the cached values
  6657. * @returns {Object} a list of cached values indexed by the keys
  6658. * @since 1.0.8
  6659. */
  6660. Yii.CCache.prototype.getValues = function (keys) {
  6661. var results, i, key;
  6662. results={};
  6663. for (i in keys) {
  6664. if (keys.hasOwnProperty(i)) {
  6665. key = keys[i];
  6666. results[key]=this.getValue(key);
  6667. }
  6668. }
  6669. return results;
  6670. };
  6671. /**
  6672. * Stores a value identified by a key in cache.
  6673. * This method should be implemented by child classes to store the data
  6674. * in specific cache storage. The uniqueness and dependency are handled
  6675. * in {@link set()} already. So only the implementation of data storage
  6676. * is needed.
  6677. *
  6678. * @param {String} key the key identifying the value to be cached
  6679. * @param {String} value the value to be cached
  6680. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6681. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6682. * @throws {Yii.CException} if this method is not overridden by child classes
  6683. */
  6684. Yii.CCache.prototype.setValue = function (key, value, expire) {
  6685. throw new Yii.CException(Yii.t('yii','{className} does not support set() functionality.',
  6686. {'{className}':this.getClassName()}));
  6687. };
  6688. /**
  6689. * Stores a value identified by a key into cache if the cache does not contain this key.
  6690. * This method should be implemented by child classes to store the data
  6691. * in specific cache storage. The uniqueness and dependency are handled
  6692. * in {@link add()} already. So only the implementation of data storage
  6693. * is needed.
  6694. *
  6695. * @param {String} key the key identifying the value to be cached
  6696. * @param {String} value the value to be cached
  6697. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6698. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6699. * @throws {Yii.CException} if this method is not overridden by child classes
  6700. */
  6701. Yii.CCache.prototype.addValue = function (key, value, expire) {
  6702. throw new Yii.CException(Yii.t('yii','{className} does not support add() functionality.',
  6703. {'{className}':this.getClassName()}));
  6704. };
  6705. /**
  6706. * Deletes a value with the specified key from cache
  6707. * This method should be implemented by child classes to delete the data from actual cache storage.
  6708. * @param {String} key the key of the value to be deleted
  6709. * @returns {Boolean} if no error happens during deletion
  6710. * @throws {Yii.CException} if this method is not overridden by child classes
  6711. */
  6712. Yii.CCache.prototype.deleteValue = function (key) {
  6713. throw new Yii.CException(Yii.t('yii','{className} does not support delete() functionality.',
  6714. {'{className}':this.getClassName()}));
  6715. };
  6716. /**
  6717. * Deletes all values from cache.
  6718. * Child classes may implement this method to realize the flush operation.
  6719. * @returns {Boolean} whether the flush operation was successful.
  6720. * @throws {Yii.CException} if this method is not overridden by child classes
  6721. * @since 1.1.5
  6722. */
  6723. Yii.CCache.prototype.flushValues = function () {
  6724. throw new Yii.CException(Yii.t('yii','{className} does not support flushValues() functionality.',
  6725. {'{className}':this.getClassName()}));
  6726. };
  6727. /**
  6728. * Returns whether there is a cache entry with a specified key.
  6729. * This method is required by the interface ArrayAccess.
  6730. * @param {String} id a key identifying the cached value
  6731. * @returns {Boolean}
  6732. */
  6733. Yii.CCache.prototype.offsetExists = function (id) {
  6734. return this.get(id)!==false;
  6735. };
  6736. /**
  6737. * Retrieves the value from cache with a specified key.
  6738. * This method is required by the interface ArrayAccess.
  6739. * @param {String} id a key identifying the cached value
  6740. * @returns {Mixed} the value stored in cache, false if the value is not in the cache or expired.
  6741. */
  6742. Yii.CCache.prototype.offsetGet = function (id) {
  6743. return this.get(id);
  6744. };
  6745. /**
  6746. * Stores the value identified by a key into cache.
  6747. * If the cache already contains such a key, the existing value will be
  6748. * replaced with the new ones. To add expiration and dependencies, use the set() method.
  6749. * This method is required by the interface ArrayAccess.
  6750. * @param {String} id the key identifying the value to be cached
  6751. * @param {Mixed} value the value to be cached
  6752. */
  6753. Yii.CCache.prototype.offsetSet = function (id, value) {
  6754. this.set(id, value);
  6755. };
  6756. /**
  6757. * Deletes the value with the specified key from cache
  6758. * This method is required by the interface ArrayAccess.
  6759. * @param {String} id the key of the value to be deleted
  6760. * @returns {Boolean} if no error happens during deletion
  6761. */
  6762. Yii.CCache.prototype.offsetUnset = function (id) {
  6763. this.remove(id);
  6764. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6765. /**
  6766. * CLocalCache implements a cache application component based on localStorage
  6767. * @package system.caching
  6768. * @since 1.0
  6769. * @author Charles Pick
  6770. * @class
  6771. * @extends Yii.CCache
  6772. */
  6773. Yii.CLocalCache = function CLocalCache () {
  6774. };
  6775. Yii.CLocalCache.prototype = new Yii.CCache();
  6776. Yii.CLocalCache.prototype.constructor = Yii.CLocalCache;
  6777. /**
  6778. * Retrieves a value from cache with a specified key.
  6779. * This is the implementation of the method declared in the parent class.
  6780. * @param {String} key a unique key identifying the cached value
  6781. * @returns {String} the value stored in cache, false if the value is not in the cache or expired.
  6782. */
  6783. Yii.CLocalCache.prototype.getValue = function (key) {
  6784. var raw, item, expiry, now;
  6785. raw = localStorage.getItem(key);
  6786. if (raw === null) {
  6787. return false;
  6788. }
  6789. try {
  6790. item = Yii.CJSON.decode(raw);
  6791. now = php.time();
  6792. expiry = item.shift();
  6793. if (expiry !== 0 && expiry < now) {
  6794. localStorage.removeItem(key);
  6795. return false;
  6796. }
  6797. return item.shift();
  6798. }
  6799. catch (e) {
  6800. return raw;
  6801. }
  6802. };
  6803. /**
  6804. * Stores a value identified by a key in cache.
  6805. * This is the implementation of the method declared in the parent class.
  6806. *
  6807. * @param {String} key the key identifying the value to be cached
  6808. * @param {String} value the value to be cached
  6809. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6810. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6811. */
  6812. Yii.CLocalCache.prototype.setValue = function (key, value, expire) {
  6813. if(expire>0) {
  6814. expire+=php.time();
  6815. }
  6816. else {
  6817. expire=0;
  6818. }
  6819. return localStorage.setItem(key, Yii.CJSON.encode([expire,value]));
  6820. };
  6821. /**
  6822. * Stores a value identified by a key into cache if the cache does not contain this key.
  6823. * This is the implementation of the method declared in the parent class.
  6824. *
  6825. * @param {String} key the key identifying the value to be cached
  6826. * @param {String} value the value to be cached
  6827. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6828. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6829. */
  6830. Yii.CLocalCache.prototype.addValue = function (key, value, expire) {
  6831. if(expire>0) {
  6832. expire+=php.time();
  6833. }
  6834. else {
  6835. expire=0;
  6836. }
  6837. // TODO: expiry!
  6838. return localStorage.setItem(key, value);
  6839. };
  6840. /**
  6841. * Deletes a value with the specified key from cache
  6842. * This is the implementation of the method declared in the parent class.
  6843. * @param {String} key the key of the value to be deleted
  6844. * @returns {Boolean} if no error happens during deletion
  6845. */
  6846. Yii.CLocalCache.prototype.remove = function (key) {
  6847. return localStorage.removeItem(key);
  6848. };
  6849. /**
  6850. * Deletes all values from cache.
  6851. * This is the implementation of the method declared in the parent class.
  6852. * @returns {Boolean} whether the flush operation was successful.
  6853. * @since 1.1.5
  6854. */
  6855. Yii.CLocalCache.prototype.flushValues = function () {
  6856. return localStorage.clear();
  6857. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6858. /**
  6859. * CSessionCache implements a cache application component based on sessionStorage
  6860. * @package system.caching
  6861. * @since 1.0
  6862. * @author Charles Pick
  6863. * @class
  6864. * @extends Yii.CCache
  6865. */
  6866. Yii.CSessionCache = function CSessionCache () {
  6867. };
  6868. Yii.CSessionCache.prototype = new Yii.CCache();
  6869. Yii.CSessionCache.prototype.constructor = Yii.CSessionCache;
  6870. /**
  6871. * Retrieves a value from cache with a specified key.
  6872. * This is the implementation of the method declared in the parent class.
  6873. * @param {String} key a unique key identifying the cached value
  6874. * @returns {String} the value stored in cache, false if the value is not in the cache or expired.
  6875. */
  6876. Yii.CSessionCache.prototype.getValue = function (key) {
  6877. var raw, item, expiry, now;
  6878. raw = sessionStorage.getItem(key);
  6879. if (raw === null) {
  6880. return false;
  6881. }
  6882. try {
  6883. item = Yii.CJSON.decode(raw);
  6884. now = php.time();
  6885. expiry = item.shift();
  6886. if (expiry !== 0 && expiry < now) {
  6887. sessionStorage.removeItem(key);
  6888. return false;
  6889. }
  6890. return item.shift();
  6891. }
  6892. catch (e) {
  6893. return raw;
  6894. }
  6895. };
  6896. /**
  6897. * Stores a value identified by a key in cache.
  6898. * This is the implementation of the method declared in the parent class.
  6899. *
  6900. * @param {String} key the key identifying the value to be cached
  6901. * @param {String} value the value to be cached
  6902. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6903. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6904. */
  6905. Yii.CSessionCache.prototype.setValue = function (key, value, expire) {
  6906. if(expire>0) {
  6907. expire+=php.time();
  6908. }
  6909. else {
  6910. expire=0;
  6911. }
  6912. return sessionStorage.setItem(key, Yii.CJSON.encode([expire,value]));
  6913. };
  6914. /**
  6915. * Stores a value identified by a key into cache if the cache does not contain this key.
  6916. * This is the implementation of the method declared in the parent class.
  6917. *
  6918. * @param {String} key the key identifying the value to be cached
  6919. * @param {String} value the value to be cached
  6920. * @param {Integer} expire the number of seconds in which the cached value will expire. 0 means never expire.
  6921. * @returns {Boolean} true if the value is successfully stored into cache, false otherwise
  6922. */
  6923. Yii.CSessionCache.prototype.addValue = function (key, value, expire) {
  6924. if(expire>0) {
  6925. expire+=php.time();
  6926. }
  6927. else {
  6928. expire=0;
  6929. }
  6930. // TODO: expiry!
  6931. return sessionStorage.setItem(key, value);
  6932. };
  6933. /**
  6934. * Deletes a value with the specified key from cache
  6935. * This is the implementation of the method declared in the parent class.
  6936. * @param {String} key the key of the value to be deleted
  6937. * @returns {Boolean} if no error happens during deletion
  6938. */
  6939. Yii.CSessionCache.prototype.remove = function (key) {
  6940. return sessionStorage.removeItem(key);
  6941. };
  6942. /**
  6943. * Deletes all values from cache.
  6944. * This is the implementation of the method declared in the parent class.
  6945. * @returns {Boolean} whether the flush operation was successful.
  6946. * @since 1.1.5
  6947. */
  6948. Yii.CSessionCache.prototype.flushValues = function () {
  6949. return sessionStorage.clear();
  6950. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  6951. /**
  6952. * CAttributeCollection implements a collection for storing attribute names and values.
  6953. *
  6954. * Besides all functionalities provided by {@link CMap}, CAttributeCollection
  6955. * allows you to get and set attribute values like getting and setting
  6956. * properties. For example, the following usages are all valid for a
  6957. * CAttributeCollection object:
  6958. * <pre>
  6959. * collection.text='text'; // same as: $collection->add('text','text');
  6960. * document.write(collection.text); // same as: echo $collection->itemAt('text');
  6961. * </pre>
  6962. *
  6963. * The case sensitivity of attribute names can be toggled by setting the
  6964. * {@link caseSensitive} property of the collection.
  6965. *
  6966. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  6967. * @version $Id: CAttributeCollection.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  6968. * @package system.collections
  6969. * @since 1.0
  6970. * @author Charles Pick
  6971. * @class
  6972. * @extends Yii.CMap
  6973. */
  6974. Yii.CAttributeCollection = function CAttributeCollection(data, readOnly) {
  6975. this.construct(data, readOnly);
  6976. };
  6977. Yii.CAttributeCollection.prototype = new Yii.CMap();
  6978. Yii.CAttributeCollection.prototype.constructor = Yii.CAttributeCollection;
  6979. /**
  6980. * @var {Boolean} whether the keys are case-sensitive. Defaults to false.
  6981. */
  6982. Yii.CAttributeCollection.prototype.caseSensitive = false;
  6983. /**
  6984. * Returns a property value or an event handler list by property or event name.
  6985. * This method overrides the parent implementation by returning
  6986. * a key value if the key exists in the collection.
  6987. * @param {String} name the property name or the event name
  6988. * @returns {Mixed} the property value or the event handler list
  6989. * @throws {Yii.CException} if the property/event is not defined.
  6990. */
  6991. Yii.CAttributeCollection.prototype.get = function (name) {
  6992. if(this.contains(name)) {
  6993. return this.itemAt(name);
  6994. }
  6995. else {
  6996. return Yii.CMap.prototype.get.call(this, name);
  6997. }
  6998. };
  6999. /**
  7000. * Sets value of a component property.
  7001. * This method overrides the parent implementation by adding a new key value
  7002. * to the collection.
  7003. * @param {String} name the property name or event name
  7004. * @param {Mixed} value the property value or event handler
  7005. * @throws {Yii.CException} If the property is not defined or read-only.
  7006. */
  7007. Yii.CAttributeCollection.prototype.set = function (name, value) {
  7008. this.add(name,value);
  7009. };
  7010. /**
  7011. * Checks if a property value is null.
  7012. * This method overrides the parent implementation by checking
  7013. * if the key exists in the collection and contains a non-null value.
  7014. * @param {String} name the property name or the event name
  7015. * @returns {Boolean} whether the property value is null
  7016. * @since 1.0.1
  7017. */
  7018. Yii.CAttributeCollection.prototype.isset = function (name) {
  7019. if(this.contains(name)) {
  7020. return this.itemAt(name)!==null;
  7021. }
  7022. else {
  7023. return Yii.CMap.prototype.isset.call(this, name);
  7024. }
  7025. };
  7026. /**
  7027. * Sets a component property to be null.
  7028. * This method overrides the parent implementation by clearing
  7029. * the specified key value.
  7030. * @param {String} name the property name or the event name
  7031. * @since 1.0.1
  7032. */
  7033. Yii.CAttributeCollection.prototype.unset = function (name) {
  7034. this.remove(name);
  7035. };
  7036. /**
  7037. * Returns the item with the specified key.
  7038. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  7039. * @param {Mixed} key the key
  7040. * @returns {Mixed} the element at the offset, null if no element is found at the offset
  7041. */
  7042. Yii.CAttributeCollection.prototype.itemAt = function (key) {
  7043. if(this.caseSensitive) {
  7044. return Yii.CMap.prototype.itemAt.call(this,key);
  7045. }
  7046. else {
  7047. return Yii.CMap.prototype.itemAt.call(this,key.toLowerCase());
  7048. }
  7049. };
  7050. /**
  7051. * Adds an item into the map.
  7052. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  7053. * @param {Mixed} key key
  7054. * @param {Mixed} value value
  7055. */
  7056. Yii.CAttributeCollection.prototype.add = function (key, value) {
  7057. if(this.caseSensitive) {
  7058. Yii.CMap.prototype.add.call(this, key,value);
  7059. }
  7060. else {
  7061. Yii.CMap.prototype.add.call(this, key.toLowerCase(),value);
  7062. }
  7063. };
  7064. /**
  7065. * Removes an item from the map by its key.
  7066. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  7067. * @param {Mixed} key the key of the item to be removed
  7068. * @returns {Mixed} the removed value, null if no such key exists.
  7069. */
  7070. Yii.CAttributeCollection.prototype.remove = function (key) {
  7071. if(this.caseSensitive) {
  7072. return Yii.CMap.prototype.remove.call(this, key);
  7073. }
  7074. else {
  7075. return Yii.CMap.prototype.remove.call(this, key.toLowerCase());
  7076. }
  7077. };
  7078. /**
  7079. * Returns whether the specified is in the map.
  7080. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  7081. * @param {Mixed} key the key
  7082. * @returns {Boolean} whether the map contains an item with the specified key
  7083. */
  7084. Yii.CAttributeCollection.prototype.contains = function (key) {
  7085. if(this.caseSensitive) {
  7086. return Yii.CMap.prototype.contains.call(this, key);
  7087. }
  7088. else {
  7089. return Yii.CMap.prototype.contains.call(this, key.toLowerCase());
  7090. }
  7091. };
  7092. /**
  7093. * Determines whether a property is defined.
  7094. * This method overrides parent implementation by returning true
  7095. * if the collection contains the named key.
  7096. * @param {String} name the property name
  7097. * @returns {Boolean} whether the property is defined
  7098. */
  7099. Yii.CAttributeCollection.prototype.hasProperty = function (name) {
  7100. return this.contains(name) || Yii.CMap.prototype.hasProperty.call(this, name);
  7101. };
  7102. /**
  7103. * Determines whether a property can be read.
  7104. * This method overrides parent implementation by returning true
  7105. * if the collection contains the named key.
  7106. * @param {String} name the property name
  7107. * @returns {Boolean} whether the property can be read
  7108. */
  7109. Yii.CAttributeCollection.prototype.canGetProperty = function (name) {
  7110. return this.contains(name) || Yii.CMap.prototype.canGetProperty.call(this, name);
  7111. };
  7112. /**
  7113. * Determines whether a property can be set.
  7114. * This method overrides parent implementation by always returning true
  7115. * because you can always add a new value to the collection.
  7116. * @param {String} name the property name
  7117. * @returns {Boolean} true
  7118. */
  7119. Yii.CAttributeCollection.prototype.canSetProperty = function (name) {
  7120. return true;
  7121. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7122. /**
  7123. * CConfiguration represents an array-based configuration.
  7124. *
  7125. * It can be used to initialize an object's properties.
  7126. *
  7127. * The configuration data may be obtained from a PHP script. For example,
  7128. * <pre>
  7129. * return {
  7130. * 'name':'My Application',
  7131. * 'defaultController':'index',
  7132. * };
  7133. * </pre>
  7134. * Use the following code to load the above configuration data:
  7135. * <pre>
  7136. * config=new Yii.CConfiguration('path/to/config.php');
  7137. * </pre>
  7138. *
  7139. * To apply the configuration to an object, call {@link applyTo()}.
  7140. * Each (key,value) pair in the configuration data is applied
  7141. * to the object like: $object->$key=$value.
  7142. *
  7143. * Since CConfiguration extends from {@link CMap}, it can be
  7144. * used like an associative array. See {@link CMap} for more details.
  7145. *
  7146. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  7147. * @version $Id: CConfiguration.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  7148. * @package system.collections
  7149. * @since 1.0
  7150. * @author Charles Pick
  7151. * @class
  7152. * @extends Yii.CMap
  7153. */
  7154. Yii.CConfiguration = function CConfiguration (data, readOnly) {
  7155. this.construct(data, readOnly);
  7156. };
  7157. Yii.CConfiguration.prototype = new Yii.CMap();
  7158. Yii.CConfiguration.prototype.constructor = Yii.CConfiguration;
  7159. /**
  7160. * Saves the configuration into a JSON string.
  7161. * The string is a valid JSON expression representing the configuration data as an object.
  7162. * @returns {String} the JSON representation of the configuration
  7163. */
  7164. Yii.CConfiguration.prototype.saveAsString = function () {
  7165. return Yii.CJSON.encode(this.toObject());
  7166. };
  7167. /**
  7168. * Applies the configuration to an object.
  7169. * Each (key,value) pair in the configuration data is applied
  7170. * to the object like: $object->$key=$value.
  7171. * @param {Object} object object to be applied with this configuration
  7172. */
  7173. Yii.CConfiguration.prototype.applyTo = function (object) {
  7174. var keyValue, key, value;
  7175. keyValue = this.toObject();
  7176. for (key in keyValue) {
  7177. if (keyValue.hasOwnProperty(key)) {
  7178. value = keyValue[key];
  7179. object[key] = value;
  7180. }
  7181. }
  7182. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7183. /**
  7184. * CQueue implements a queue.
  7185. *
  7186. * The typical queue operations are implemented, which include
  7187. * {@link enqueue()}, {@link dequeue()} and {@link peek()}. In addition,
  7188. * {@link contains()} can be used to check if an item is contained
  7189. * in the queue. To obtain the number of the items in the queue,
  7190. * check the {@link getCount Count} property.
  7191. *
  7192. * Items in the queue may be traversed using foreach as follows,
  7193. * <pre>
  7194. * for (i in queue) +++
  7195. * </pre>
  7196. *
  7197. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  7198. * @version $Id: CQueue.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  7199. * @package system.collections
  7200. * @since 1.0
  7201. * @author Charles Pick
  7202. * @class
  7203. * @extends Yii.CComponent
  7204. */
  7205. Yii.CQueue = function CQueue(data) {
  7206. this.readOnly = false;
  7207. this.construct(data);
  7208. };
  7209. Yii.CQueue.prototype = new Yii.CList();
  7210. Yii.CQueue.prototype.constructor = Yii.CQueue;
  7211. /**
  7212. * Constructor.
  7213. * Initializes the queue with an array or an iterable object.
  7214. * @param {Array} data the intial data. Default is null, meaning no initialization.
  7215. * @throws {Yii.CException} If data is not null and neither an array nor an iterator.
  7216. */
  7217. Yii.CQueue.prototype.construct = function (data) {
  7218. if (data === undefined) {
  7219. data = null;
  7220. }
  7221. if(data!==null) {
  7222. this.copyFrom(data);
  7223. }
  7224. };
  7225. /**
  7226. * @param {Mixed} item the item
  7227. * @returns {Boolean} whether the queue contains the item
  7228. */
  7229. Yii.CQueue.prototype.contains = function (item) {
  7230. var i, limit = this.length;
  7231. for (i = 0; i < limit; i++) {
  7232. if (item === this[i]) {
  7233. return true;
  7234. }
  7235. }
  7236. return false;
  7237. };
  7238. /**
  7239. * Returns the item at the top of the queue.
  7240. * @returns {Mixed} item at the top of the queue
  7241. * @throws {Yii.CException} if the queue is empty
  7242. */
  7243. Yii.CQueue.prototype.peek = function () {
  7244. if(this.length===0) {
  7245. throw new Yii.CException(Yii.t('yii','The queue is empty.'));
  7246. }
  7247. else {
  7248. return this[0];
  7249. }
  7250. };
  7251. /**
  7252. * Removes and returns the object at the beginning of the queue.
  7253. * @returns {Mixed} the item at the beginning of the queue
  7254. * @throws {Yii.CException} if the queue is empty
  7255. */
  7256. Yii.CQueue.prototype.dequeue = function () {
  7257. if(this.length===0) {
  7258. throw new Yii.CException(Yii.t('yii','The queue is empty.'));
  7259. }
  7260. else {
  7261. return this.shift();
  7262. }
  7263. };
  7264. /**
  7265. * Adds an object to the end of the queue.
  7266. * @param {Mixed} item the item to be appended into the queue
  7267. */
  7268. Yii.CQueue.prototype.enqueue = function (item) {
  7269. this.push(item);
  7270. };
  7271. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7272. /**
  7273. * CStack implements a stack.
  7274. *
  7275. * The typical stack operations are implemented, which include
  7276. * {@link push()}, {@link pop()} and {@link peek()}. In addition,
  7277. * {@link contains()} can be used to check if an item is contained
  7278. * in the stack. To obtain the number of the items in the stack,
  7279. * check the {@link getCount Count} property.
  7280. *
  7281. * Items in the stack may be traversed using foreach as follows,
  7282. * <pre>
  7283. * for (i in stack) +++
  7284. * </pre>
  7285. *
  7286. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  7287. * @version $Id: CStack.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  7288. * @package system.collections
  7289. * @since 1.0
  7290. * @author Charles Pick
  7291. * @class
  7292. * @extends Yii.CComponent
  7293. */
  7294. Yii.CStack = function CStack (data) {
  7295. this.construct(data);
  7296. };
  7297. Yii.CStack.prototype = new Array();
  7298. Yii.CStack.prototype.constructor = Yii.CStack;
  7299. Yii.augment(Yii.CStack, Yii.CComponent);
  7300. /**
  7301. * Constructor.
  7302. * Initializes the stack with an array or an iterable object.
  7303. * @param {Array} data the initial data. Default is null, meaning no initialization.
  7304. * @throws {Yii.CException} If data is not null and neither an array nor an iterator.
  7305. */
  7306. Yii.CStack.prototype.construct = function (data) {
  7307. if (data === undefined) {
  7308. data = null;
  7309. }
  7310. if(data!==null) {
  7311. this.copyFrom(data);
  7312. }
  7313. };
  7314. /**
  7315. * @returns {Array} the list of items in stack
  7316. */
  7317. Yii.CStack.prototype.toArray = function () {
  7318. var ret = [], i, limit;
  7319. limit = this.length;
  7320. for (i = 0; i < limit; i++) {
  7321. ret.push(this[i]);
  7322. }
  7323. return ret;
  7324. };
  7325. /**
  7326. * Copies iterable data into the stack.
  7327. * Note, existing data in the list will be cleared first.
  7328. * @param {Mixed} data the data to be copied from, must be an array or object implementing Traversable
  7329. * @throws {Yii.CException} If data is neither an array nor a Traversable.
  7330. */
  7331. Yii.CStack.prototype.copyFrom = function (data) {
  7332. var i, item;
  7333. if(Object.prototype.toString.call(data) === '[object Array]' || (data instanceof Array))
  7334. {
  7335. this.clear();
  7336. for (i in data)
  7337. {
  7338. if (data.hasOwnProperty(i)) {
  7339. item = data[i];
  7340. this.push(item);
  7341. }
  7342. }
  7343. }
  7344. else if(data!==null) {
  7345. throw new Yii.CException(Yii.t('yii','Stack data must be an array or an object implementing Traversable.'));
  7346. }
  7347. };
  7348. /**
  7349. * Removes all items in the stack.
  7350. */
  7351. Yii.CStack.prototype.clear = function () {
  7352. var i, limit;
  7353. limit = this.length;
  7354. for(i = 0; i < limit; i++) {
  7355. delete this[i];
  7356. }
  7357. };
  7358. /**
  7359. * @param {Mixed} item the item
  7360. * @returns {Boolean} whether the stack contains the item
  7361. */
  7362. Yii.CStack.prototype.contains = function (item) {
  7363. var i, limit = this.length;
  7364. for (i = 0; i < limit; i++) {
  7365. if (item === this[i]) {
  7366. return true;
  7367. }
  7368. }
  7369. return false;
  7370. };
  7371. /**
  7372. * Returns the item at the top of the stack.
  7373. * Unlike {@link pop()}, this method does not remove the item from the stack.
  7374. * @returns {Mixed} item at the top of the stack
  7375. * @throws {Yii.CException} if the stack is empty
  7376. */
  7377. Yii.CStack.prototype.peek = function () {
  7378. if(this.length) {
  7379. return this[this.length - 1];
  7380. }
  7381. else {
  7382. throw new Yii.CException(Yii.t('yii','The stack is empty.'));
  7383. }
  7384. };
  7385. /**
  7386. * Pops up the item at the top of the stack.
  7387. * @returns {Mixed} the item at the top of the stack
  7388. * @throws {Yii.CException} if the stack is empty
  7389. */
  7390. Yii.CStack.prototype.pop = function () {
  7391. if(this.length) {
  7392. return Array.prototype.pop.call(this);
  7393. }
  7394. else {
  7395. throw new Yii.CException(Yii.t('yii','The stack is empty.'));
  7396. }
  7397. };
  7398. /**
  7399. * Returns the number of items in the stack.
  7400. * @returns {Integer} the number of items in the stack
  7401. */
  7402. Yii.CStack.prototype.getCount = function () {
  7403. return this.length;
  7404. };
  7405. /**
  7406. * Returns the number of items in the stack.
  7407. * This method is required by Countable interface.
  7408. * @returns {Integer} number of items in the stack.
  7409. */
  7410. Yii.CStack.prototype.count = function () {
  7411. return this.length;
  7412. };
  7413. /**
  7414. * Provides convenient access to Yii.forEach()
  7415. * @param {Function} callback The callback function, this will receive 2 parameters, key and value
  7416. * @returns {Yii.CStack} the stack
  7417. */
  7418. Yii.CStack.prototype.forEach = function(callback) {
  7419. return Yii.forEach(this,callback);
  7420. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7421. /**
  7422. * CTypedList represents a list whose items are of the certain type.
  7423. *
  7424. * CTypedList extends {@link CList} by making sure that the elements to be
  7425. * added to the list is of certain class type.
  7426. *
  7427. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  7428. * @version $Id: CTypedList.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  7429. * @package system.collections
  7430. * @since 1.0
  7431. * @author Charles Pick
  7432. * @class
  7433. * @extends Yii.CList
  7434. */
  7435. Yii.CTypedList = function CTypedList (type) {
  7436. this.construct(type);
  7437. };
  7438. Yii.CTypedList.prototype = new Yii.CList();
  7439. Yii.CTypedList.prototype.constructor = Yii.CTypedList;
  7440. Yii.CTypedList.prototype._type = null;
  7441. /**
  7442. * Constructor.
  7443. * @param {String} type class type
  7444. */
  7445. Yii.CTypedList.prototype.construct = function (type) {
  7446. this._type=type;
  7447. };
  7448. /**
  7449. * Inserts an item at the specified position.
  7450. * This method overrides the parent implementation by
  7451. * checking the item to be inserted is of certain type.
  7452. * @param {Integer} index the specified position.
  7453. * @param {Mixed} item new item
  7454. * @throws {Yii.CException} If the index specified exceeds the bound,
  7455. * the list is read-only or the element is not of the expected type.
  7456. */
  7457. Yii.CTypedList.prototype.insertAt = function (index, item) {
  7458. if(item instanceof this._type) {
  7459. Yii.CList.prototype.insertAt.call(this,index,item);
  7460. }
  7461. else {
  7462. throw new Yii.CException(Yii.t('yii','CTypedList<{type}> can only hold objects of {type} class.',
  7463. {'{type}':this._type}));
  7464. }
  7465. };
  7466. /**
  7467. * Pushes an item on to the end of the list
  7468. * @param {Mixed} the item to add
  7469. * @returns {Integer} the number of items in the list
  7470. */
  7471. Yii.CTypedList.prototype.push = function (item) {
  7472. if(item instanceof this._type) {
  7473. return Yii.CList.prototype.push.call(this,item);
  7474. }
  7475. else {
  7476. throw new Yii.CException(Yii.t('yii','CTypedList<{type}> can only hold objects of {type} class.',
  7477. {'{type}':this._type}));
  7478. }
  7479. };
  7480. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7481. /**
  7482. * CTypedMap represents a map whose items are of the certain type.
  7483. *
  7484. * CTypedMap extends {@link CMap} by making sure that the elements to be
  7485. * added to the list is of certain class type.
  7486. *
  7487. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  7488. * @version $Id: CTypedMap.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  7489. * @package system.collections
  7490. * @since 1.0
  7491. * @author Charles Pick
  7492. * @class
  7493. * @extends Yii.CMap
  7494. */
  7495. Yii.CTypedMap = function CTypedMap (type) {
  7496. this.construct(type);
  7497. };
  7498. Yii.CTypedMap.prototype = new Yii.CMap();
  7499. Yii.CTypedMap.prototype.constructor = Yii.CTypedMap;
  7500. Yii.CTypedMap.prototype._type = null;
  7501. /**
  7502. * Constructor.
  7503. * @param {String} type class type
  7504. */
  7505. Yii.CTypedMap.prototype.construct = function (type) {
  7506. this._type=type;
  7507. };
  7508. /**
  7509. * Adds an item into the map.
  7510. * This method overrides the parent implementation by
  7511. * checking the item to be inserted is of certain type.
  7512. * @param {Integer} index the specified position.
  7513. * @param {Mixed} item new item
  7514. * @throws {Yii.CException} If the index specified exceeds the bound,
  7515. * the map is read-only or the element is not of the expected type.
  7516. */
  7517. Yii.CTypedMap.prototype.add = function (index, item) {
  7518. if(item instanceof this._type) {
  7519. Yii.CMap.prototype.add.call(this, index,item);
  7520. }
  7521. else {
  7522. throw new Yii.CException(Yii.t('yii','CTypedMap<{type}> can only hold objects of {type} class.',
  7523. {'{type}':this._type}));
  7524. }
  7525. };var YII_PATH = "/js/test/";
  7526. var appConfig = {
  7527. 'basePath': "/js/app",
  7528. 'name': "EbayStore",
  7529. 'preload': ["log"],
  7530. 'params': {
  7531. 'version': 0.1
  7532. },
  7533. 'components': {
  7534. 'db': {
  7535. 'connectionString': 'sqlite:host=localhost;dbname=ebaystore',
  7536. 'enableParamLogging': true,
  7537. 'enableProfiling': true,
  7538. 'initSQLs': [
  7539. ]
  7540. },
  7541. 'viewRenderer' : {
  7542. 'class': 'CMustacheViewRenderer'
  7543. },
  7544. 'request': {
  7545. 'enableCsrfValidation': true,
  7546. 'enableCookieValidation': true
  7547. },
  7548. 'log': {
  7549. 'class': 'CLogRouter',
  7550. 'routes': [
  7551. {
  7552. 'class': 'CProfileLogRoute',
  7553. 'showInFireBug': false
  7554. },
  7555. {
  7556. 'class': 'CWebLogRoute',
  7557. 'showInFireBug': false
  7558. }
  7559. ]
  7560. },
  7561. 'cache': {
  7562. 'class': 'CSessionCache'
  7563. },
  7564. 'urlManager': {
  7565. 'urlFormat': 'path',
  7566. 'showScriptName': false,
  7567. 'urlSuffix': '.html',
  7568. 'useStrictParsing': false,
  7569. 'rules': [
  7570. {
  7571. 'pattern': '/',
  7572. 'route': '/site/index',
  7573. 'urlSuffix': ''
  7574. },
  7575. {
  7576. 'pattern': 'contactus',
  7577. 'route': '/site/contact'
  7578. },
  7579. {
  7580. 'pattern': '<controller:\\w+>s',
  7581. 'route': '<controller>/index'
  7582. },
  7583. {
  7584. 'pattern': '<controller:\\w+>s/<id:\\d+>',
  7585. 'route': '<controller>/view'
  7586. },
  7587. {
  7588. 'pattern': '<controller:\\w+>s/<action:\\w+>/<id:\\d+>',
  7589. 'route': '<controller>/<action>'
  7590. },
  7591. {
  7592. 'pattern': '<controller:\\w+>s/<action:\\w+>',
  7593. 'route': '<controller>/<action>'
  7594. }
  7595. ]
  7596. }
  7597. }
  7598. };
  7599. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7600. /**
  7601. * A base class for data sources.
  7602. * @package system.ds
  7603. * @since 1.0
  7604. * @author Charles Pick
  7605. * @class
  7606. * @extends Yii.CComponent
  7607. */
  7608. Yii.CActiveDataSource = function CActiveDataSource () {
  7609. };
  7610. Yii.CActiveDataSource.prototype = new Yii.CComponent();
  7611. Yii.CActiveDataSource.prototype.constructor = Yii.CActiveDataSource;
  7612. /**
  7613. * Gets data from the data source and executes the callback when data arrives.
  7614. * Child classes must override this method!
  7615. * @param {Function} callback The callback function to execute, this will recieve the
  7616. * data as its first parameter and the data source as its second parameter.
  7617. *
  7618. */
  7619. Yii.CActiveDataSource.prototype.getData = function (callback) {
  7620. };
  7621. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  7622. /**
  7623. * CAsyncRecord is the base class for classes representing relational data loaded from a remote data source.
  7624. *
  7625. * It implements the active record design pattern, a popular Object-Relational Mapping (ORM) technique.
  7626. *
  7627. * @package system.ds
  7628. * @since 1.0
  7629. *
  7630. * @property array $attributes
  7631. * @author Charles Pick
  7632. * @class
  7633. * @extends Yii.CModel
  7634. */
  7635. Yii.CAsyncRecord = function CAsyncRecord (scenario, callback) {
  7636. if (scenario !== false) {
  7637. return this.construct(scenario, callback);
  7638. }
  7639. };
  7640. Yii.CAsyncRecord.prototype = new Yii.CModel(false);
  7641. Yii.CAsyncRecord.prototype.constructor = Yii.CAsyncRecord;
  7642. /**
  7643. * @const
  7644. */
  7645. Yii.CAsyncRecord.prototype.BELONGS_TO = 'CBelongsToRelation';
  7646. /**
  7647. * @const
  7648. */
  7649. Yii.CAsyncRecord.prototype.HAS_ONE = 'CHasOneRelation';
  7650. /**
  7651. * @const
  7652. */
  7653. Yii.CAsyncRecord.prototype.HAS_MANY = 'CHasManyRelation';
  7654. /**
  7655. * @const
  7656. */
  7657. Yii.CAsyncRecord.prototype.MANY_MANY = 'CManyManyRelation';
  7658. /**
  7659. * @const
  7660. */
  7661. Yii.CAsyncRecord.prototype.STAT = 'CStatRelation';
  7662. /**
  7663. * @var {Yii.CActiveDataSource} the default data source for all active records
  7664. * @see getDbConnection
  7665. */
  7666. Yii.CAsyncRecord.prototype._ds = null;
  7667. /**
  7668. * Whether or not to wrap the posted data in an object or not.
  7669. * If this is set to true, data will be wrapped in an object with the same name as
  7670. * this model. If set to a string, the string value will be used to wrap. If false
  7671. * no wrapping will be applied.
  7672. * Defaults to false.
  7673. * @var Mixed
  7674. */
  7675. Yii.CAsyncRecord.prototype.wrapData = false;
  7676. Yii.CAsyncRecord.prototype._models = {};
  7677. Yii.CAsyncRecord.prototype._new = false;
  7678. Yii.CAsyncRecord.prototype._attributes = {};
  7679. Yii.CAsyncRecord.prototype._related = {};
  7680. Yii.CAsyncRecord.prototype._c = null;
  7681. Yii.CAsyncRecord.prototype._pk = null;
  7682. Yii.CAsyncRecord.prototype._alias = 't';
  7683. /**
  7684. * Constructor.
  7685. * @param {String} scenario scenario name. See {@link CModel::scenario} for more details about this parameter.
  7686. */
  7687. Yii.CAsyncRecord.prototype.construct = function (scenario) {
  7688. if (scenario === undefined) {
  7689. scenario = 'insert';
  7690. }
  7691. if(scenario===null) { // internally used by populateRecord() and model()
  7692. return;
  7693. }
  7694. this._attributes = {};
  7695. this._ds = this.dataStoreDefaults();
  7696. this.setScenario(scenario);
  7697. this.setIsNewRecord(true);
  7698. this._attributes=this.attributeDefaults();
  7699. this.init();
  7700. this.attachBehaviors(this.behaviors());
  7701. this.afterConstruct();
  7702. };
  7703. /**
  7704. * Initializes this model.
  7705. * This method is invoked when an AR instance is newly created and has
  7706. * its {@link scenario} set.
  7707. * You may override this method to provide code that is needed to initialize the model (e.g. setting
  7708. * initial property values.)
  7709. * @since 1.0.8
  7710. */
  7711. Yii.CAsyncRecord.prototype.init = function () {
  7712. };
  7713. /**
  7714. * Returns a list of attribute names and their default values.
  7715. * Child classes should override this!
  7716. * @returns {Object} attributeName: value
  7717. */
  7718. Yii.CAsyncRecord.prototype.attributeDefaults = function () {
  7719. return {};
  7720. };
  7721. /**
  7722. * Sets the parameters about query caching.
  7723. * This is a shortcut method to {@link CDbConnection::cache()}.
  7724. * It changes the query caching parameter of the {@link dbConnection} instance.
  7725. * @param {Integer} duration the number of seconds that query results may remain valid in cache.
  7726. * If this is 0, the caching will be disabled.
  7727. * @param {Yii.CCacheDependency} dependency the dependency that will be used when saving the query results into cache.
  7728. * @param {Integer} queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1,
  7729. * meaning that the next SQL query will be cached.
  7730. * @returns {Yii.CAsyncRecord} the active record instance itself.
  7731. * @since 1.1.7
  7732. */
  7733. Yii.CAsyncRecord.prototype.cache = function (duration, dependency, queryCount) {
  7734. if (dependency === undefined) {
  7735. dependency = null;
  7736. }
  7737. if (queryCount === undefined) {
  7738. queryCount = 1;
  7739. }
  7740. this.getDataSource().cache(duration, dependency, queryCount);
  7741. return this;
  7742. };
  7743. /**
  7744. * Getter magic method.
  7745. * This method is overridden so that RR attributes can be accessed like properties.
  7746. * @param {String} name property name
  7747. * @returns {Mixed} property value
  7748. * @see getAttribute
  7749. */
  7750. Yii.CAsyncRecord.prototype.get = function (name) {
  7751. var getter, i, object, nameParts = [], limit;
  7752. if (name.indexOf(".") !== -1) {
  7753. nameParts = name.split(".");
  7754. name = nameParts.shift();
  7755. }
  7756. if (this[name] !== undefined) {
  7757. object = this[name];
  7758. }
  7759. else if (this._attributes[name] !== undefined) {
  7760. object = this._attributes[name];
  7761. }
  7762. else if (this._related[name] !== undefined) {
  7763. object = this._related[name];
  7764. }
  7765. if (object !== undefined) {
  7766. if (nameParts.length > 0) {
  7767. if (object instanceof Yii.CComponent) {
  7768. return object.get(nameParts.join("."));
  7769. }
  7770. limit = nameParts.length;
  7771. for (i = 0; i < limit; i++) {
  7772. name = nameParts.shift();
  7773. object = object[name];
  7774. if (nameParts.length === 0) {
  7775. return object;
  7776. }
  7777. if (object instanceof Yii.CComponent) {
  7778. return object.get(nameParts.join("."));
  7779. }
  7780. }
  7781. }
  7782. return object;
  7783. }
  7784. else {
  7785. if (nameParts.length > 0) {
  7786. return Yii.CModel.prototype.get.call(this, php.array_merge([name],nameParts).join("."));
  7787. }
  7788. return Yii.CModel.prototype.get.call(this,name);
  7789. }
  7790. };
  7791. /**
  7792. * Setter magic method.
  7793. * This method is overridden so that RR attributes can be accessed like properties.
  7794. * @param {String} name property name
  7795. * @param {Mixed} value property value
  7796. */
  7797. Yii.CAsyncRecord.prototype.set = function (name, value) {
  7798. var nameParts = [];
  7799. if (name.indexOf(".") !== -1) {
  7800. nameParts = name.split(".");
  7801. name = nameParts.pop();
  7802. nameParts = nameParts.join(".");
  7803. return (this.get(nameParts)[name] = value);
  7804. }
  7805. else if(this.setAttribute(name,value)===false) {
  7806. if(this.relations[name] !== undefined) {
  7807. this._related[name]=value;
  7808. }
  7809. else {
  7810. Yii.CModel.prototype.set.call(this, name,value);
  7811. }
  7812. }
  7813. };
  7814. /**
  7815. * Gets the data source for this model.
  7816. * @returns {Yii.CActiveDataSource} The data source that this model interacts with
  7817. */
  7818. Yii.CAsyncRecord.prototype.getDataSource = function () {
  7819. if (this._ds !== null) {
  7820. if (this._ds instanceof Yii.CActiveDataSource) {
  7821. return this._ds;
  7822. }
  7823. this._ds = Yii.createComponent(this._ds);
  7824. }
  7825. return this._ds;
  7826. };
  7827. /**
  7828. * Sets the data source for this model
  7829. * @param {Yii.CActiveDataSource} value The data source to use with this model
  7830. */
  7831. Yii.CAsyncRecord.prototype.setDataSource = function (value) {
  7832. var className;
  7833. if (!(value instanceof Yii.CActiveDataSource)) {
  7834. if (value['class'] !== undefined) {
  7835. className = value['class'];
  7836. delete value['class'];
  7837. }
  7838. else {
  7839. className = 'CActiveDataSource';
  7840. }
  7841. value = Yii.createComponent(className, value);
  7842. }
  7843. this._ds = value;
  7844. }
  7845. /**
  7846. * Checks whether this AR has the named attribute
  7847. * @param {String} name attribute name
  7848. * @returns {Boolean} whether this AR has the named attribute (table column).
  7849. */
  7850. Yii.CAsyncRecord.prototype.hasAttribute = function (name) {
  7851. return this.get(name) !== undefined;
  7852. };
  7853. /**
  7854. * Returns the named attribute value.
  7855. * If this is a new record and the attribute is not set before,
  7856. * the default column value will be returned.
  7857. * If this record is the result of a query and the attribute is not loaded,
  7858. * null will be returned.
  7859. * You may also use $this->AttributeName to obtain the attribute value.
  7860. * @param {String} name the attribute name
  7861. * @returns {Mixed} the attribute value. Null if the attribute is not set or does not exist.
  7862. * @see hasAttribute
  7863. */
  7864. Yii.CAsyncRecord.prototype.getAttribute = function (name) {
  7865. if(this[name] !== undefined) {
  7866. return this[name];
  7867. }
  7868. else if(this._attributes[name] !== undefined) {
  7869. return this._attributes[name];
  7870. }
  7871. };
  7872. /**
  7873. * Returns all column attribute values.
  7874. * Note, related objects are not returned.
  7875. * @param {Mixed} names names of attributes whose value needs to be returned.
  7876. * If this is true (default), then all attribute values will be returned, including
  7877. * those that are not loaded from DB (null will be returned for those attributes).
  7878. * If this is null, all attributes except those that are not loaded from DB will be returned.
  7879. * @returns {Array} attribute values indexed by attribute names.
  7880. */
  7881. Yii.CAsyncRecord.prototype.getAttributes = function (names) {
  7882. var attributes, nameColumn, name, attrs, i, column;
  7883. if (names === undefined) {
  7884. names = true;
  7885. }
  7886. attributes=this._attributes;
  7887. if(Object.prototype.toString.call(names) === '[object Array]') {
  7888. attrs=[];
  7889. for (i in names) {
  7890. if (names.hasOwnProperty(i)) {
  7891. name = names[i];
  7892. if(this[name] !== undefined) {
  7893. attrs[name]=this.name;
  7894. }
  7895. else {
  7896. attrs[name]=attributes[name] !== undefined?attributes[name]:null;
  7897. }
  7898. }
  7899. }
  7900. return attrs;
  7901. }
  7902. else {
  7903. return attributes;
  7904. }
  7905. };
  7906. /**
  7907. * Sets the named attribute value.
  7908. * You may also use $this->AttributeName to set the attribute value.
  7909. * @param {String} name the attribute name
  7910. * @param {Mixed} value the attribute value.
  7911. * @returns {Boolean} whether the attribute exists and the assignment is conducted successfully
  7912. * @see hasAttribute
  7913. */
  7914. Yii.CAsyncRecord.prototype.setAttribute = function (name, value) {
  7915. if(this[name] !== undefined) {
  7916. this[name]=value;
  7917. }
  7918. else if(this._attributes[name] !== undefined) {
  7919. this._attributes[name]=value;
  7920. }
  7921. else {
  7922. return false;
  7923. }
  7924. return true;
  7925. };
  7926. /**
  7927. * Returns if the current record is new.
  7928. * @returns {Boolean} whether the record is new and should be inserted when calling {@link save}.
  7929. * This property is automatically set in constructor and {@link populateRecord}.
  7930. * Defaults to false, but it will be set to true if the instance is created using
  7931. * the new operator.
  7932. */
  7933. Yii.CAsyncRecord.prototype.getIsNewRecord = function () {
  7934. return this._new;
  7935. };
  7936. /**
  7937. * Sets if the record is new.
  7938. * @param {Boolean} value whether the record is new and should be inserted when calling {@link save}.
  7939. * @see getIsNewRecord
  7940. */
  7941. Yii.CAsyncRecord.prototype.setIsNewRecord = function (value) {
  7942. this._new=value;
  7943. };
  7944. /**
  7945. * This event is raised before the record is saved.
  7946. * By setting {@link CModelEvent::isValid} to be false, the normal {@link save()} process will be stopped.
  7947. * @param {Yii.CModelEvent} event the event parameter
  7948. * @since 1.0.2
  7949. */
  7950. Yii.CAsyncRecord.prototype.onBeforeSave = function (event) {
  7951. this.raiseEvent('onBeforeSave',event);
  7952. };
  7953. /**
  7954. * This event is raised after the record is saved.
  7955. * @param {Yii.CEvent} event the event parameter
  7956. * @since 1.0.2
  7957. */
  7958. Yii.CAsyncRecord.prototype.onAfterSave = function (event) {
  7959. this.raiseEvent('onAfterSave',event);
  7960. };
  7961. /**
  7962. * This event is raised before the record is deleted.
  7963. * By setting {@link CModelEvent::isValid} to be false, the normal {@link delete()} process will be stopped.
  7964. * @param {Yii.CModelEvent} event the event parameter
  7965. * @since 1.0.2
  7966. */
  7967. Yii.CAsyncRecord.prototype.onBeforeDelete = function (event) {
  7968. this.raiseEvent('onBeforeDelete',event);
  7969. };
  7970. /**
  7971. * This event is raised after the record is deleted.
  7972. * @param {Yii.CEvent} event the event parameter
  7973. * @since 1.0.2
  7974. */
  7975. Yii.CAsyncRecord.prototype.onAfterDelete = function (event) {
  7976. this.raiseEvent('onAfterDelete',event);
  7977. };
  7978. /**
  7979. * This event is raised before an AR finder performs a find call.
  7980. * In this event, the {@link CModelEvent::criteria} property contains the query criteria
  7981. * passed as parameters to those find methods. If you want to access
  7982. * the query criteria specified in scopes, please use {@link getDbCriteria()}.
  7983. * You can modify either criteria to customize them based on needs.
  7984. * @param {Yii.CModelEvent} event the event parameter
  7985. * @see beforeFind
  7986. * @since 1.0.9
  7987. */
  7988. Yii.CAsyncRecord.prototype.onBeforeFind = function (event) {
  7989. this.raiseEvent('onBeforeFind',event);
  7990. };
  7991. /**
  7992. * This event is raised after the record is instantiated by a find method.
  7993. * @param {Yii.CEvent} event the event parameter
  7994. * @since 1.0.2
  7995. */
  7996. Yii.CAsyncRecord.prototype.onAfterFind = function (event) {
  7997. this.raiseEvent('onAfterFind',event);
  7998. };
  7999. /**
  8000. * This method is invoked before saving a record (after validation, if any).
  8001. * The default implementation raises the {@link onBeforeSave} event.
  8002. * You may override this method to do any preparation work for record saving.
  8003. * Use {@link isNewRecord} to determine whether the saving is
  8004. * for inserting or updating record.
  8005. * Make sure you call the parent implementation so that the event is raised properly.
  8006. * @returns {Boolean} whether the saving should be executed. Defaults to true.
  8007. */
  8008. Yii.CAsyncRecord.prototype.beforeSave = function () {
  8009. var event;
  8010. if(this.hasEventHandler('onBeforeSave')) {
  8011. event=new Yii.CModelEvent(this);
  8012. this.onBeforeSave(event);
  8013. return event.isValid;
  8014. }
  8015. else {
  8016. return true;
  8017. }
  8018. };
  8019. /**
  8020. * This method is invoked after saving a record successfully.
  8021. * The default implementation raises the {@link onAfterSave} event.
  8022. * You may override this method to do postprocessing after record saving.
  8023. * Make sure you call the parent implementation so that the event is raised properly.
  8024. */
  8025. Yii.CAsyncRecord.prototype.afterSave = function () {
  8026. if(this.hasEventHandler('onAfterSave')) {
  8027. this.onAfterSave(new Yii.CEvent(this));
  8028. }
  8029. };
  8030. /**
  8031. * This method is invoked before deleting a record.
  8032. * The default implementation raises the {@link onBeforeDelete} event.
  8033. * You may override this method to do any preparation work for record deletion.
  8034. * Make sure you call the parent implementation so that the event is raised properly.
  8035. * @returns {Boolean} whether the record should be deleted. Defaults to true.
  8036. */
  8037. Yii.CAsyncRecord.prototype.beforeDelete = function () {
  8038. var event;
  8039. if(this.hasEventHandler('onBeforeDelete')) {
  8040. event=new Yii.CModelEvent(this);
  8041. this.onBeforeDelete(event);
  8042. return event.isValid;
  8043. }
  8044. else {
  8045. return true;
  8046. }
  8047. };
  8048. /**
  8049. * This method is invoked after deleting a record.
  8050. * The default implementation raises the {@link onAfterDelete} event.
  8051. * You may override this method to do postprocessing after the record is deleted.
  8052. * Make sure you call the parent implementation so that the event is raised properly.
  8053. */
  8054. Yii.CAsyncRecord.prototype.afterDelete = function () {
  8055. if(this.hasEventHandler('onAfterDelete')) {
  8056. this.onAfterDelete(new Yii.CEvent(this));
  8057. }
  8058. };
  8059. /**
  8060. * This method is invoked before an AR finder executes a find call.
  8061. * The find calls include {@link find}, {@link findAll}, {@link findByPk},
  8062. * {@link findAllByPk}, {@link findByAttributes} and {@link findAllByAttributes}.
  8063. * The default implementation raises the {@link onBeforeFind} event.
  8064. * If you override this method, make sure you call the parent implementation
  8065. * so that the event is raised properly.
  8066. *
  8067. * Starting from version 1.1.5, this method may be called with a hidden {@link CDbCriteria}
  8068. * parameter which represents the current query criteria as passed to a find method of AR.
  8069. *
  8070. * @since 1.0.9
  8071. */
  8072. Yii.CAsyncRecord.prototype.beforeFind = function () {
  8073. var event;
  8074. if(this.hasEventHandler('onBeforeFind')) {
  8075. event=new Yii.CModelEvent(this);
  8076. // for backward compatibility
  8077. event.criteria=arguments.length>0 ? arguments[0] : null;
  8078. this.onBeforeFind(event);
  8079. }
  8080. };
  8081. /**
  8082. * This method is invoked after each record is instantiated by a find method.
  8083. * The default implementation raises the {@link onAfterFind} event.
  8084. * You may override this method to do postprocessing after each newly found record is instantiated.
  8085. * Make sure you call the parent implementation so that the event is raised properly.
  8086. */
  8087. Yii.CAsyncRecord.prototype.afterFind = function () {
  8088. if(this.hasEventHandler('onAfterFind')) {
  8089. this.onAfterFind(new Yii.CEvent(this));
  8090. }
  8091. };
  8092. /**
  8093. * Calls {@link beforeFind}.
  8094. * This method is internally used.
  8095. * @since 1.0.11
  8096. */
  8097. Yii.CAsyncRecord.prototype.beforeFindInternal = function () {
  8098. this.beforeFind();
  8099. };
  8100. /**
  8101. * Calls {@link afterFind}.
  8102. * This method is internally used.
  8103. * @since 1.0.3
  8104. */
  8105. Yii.CAsyncRecord.prototype.afterFindInternal = function () {
  8106. this.afterFind();
  8107. };
  8108. /**
  8109. * Adds an item to the data source based on this remote record attributes.
  8110. * Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
  8111. * After the record is inserted to data source successfully, its {@link isNewRecord} property will be set false,
  8112. * and its {@link scenario} property will be set to be 'update'.
  8113. * @param {Array} attributes list of attributes that need to be saved. Defaults to null,
  8114. * meaning all attributes that are loaded from DS will be saved.
  8115. * @param {Function} callback The callback that will be executed after the insert succeeds
  8116. * @returns {Mixed} The data source request
  8117. * @throws {Yii.CException} if the record is not new
  8118. */
  8119. Yii.CAsyncRecord.prototype.create = function (attributes, callback) {
  8120. var builder, table, command, primaryKey, i, pk, self = this, func, postData;
  8121. if (attributes === undefined) {
  8122. attributes = null;
  8123. }
  8124. if(!this.getIsNewRecord()) {
  8125. throw new Yii.CDbException(Yii.t('yii','The remote record cannot be created because it is not new.'));
  8126. }
  8127. if(this.beforeSave()) {
  8128. Yii.trace(this.getClassName()+'.create()','system.ds.CAsyncRecord');
  8129. func = function (data, dataSource) {
  8130. var model;
  8131. model = self.populateRecord(data);
  8132. model.afterSave();
  8133. model.setIsNewRecord(false);
  8134. model.setScenario('update');
  8135. callback(model, dataSource);
  8136. };
  8137. if (this.wrapData === true) {
  8138. postData = {};
  8139. postData[this.getClassName()] = this.getAttributes(attributes);
  8140. }
  8141. else if (this.wrapData) {
  8142. postData = {};
  8143. postData[this.wrapData] = this.getAttributes(attributes);
  8144. }
  8145. else {
  8146. postData = this.getAttributes(attributes);
  8147. }
  8148. return this.getDataSource().create(postData, func);
  8149. }
  8150. return false;
  8151. };
  8152. /**
  8153. * Updates the row represented by this remote record.
  8154. * All loaded attributes will be saved to the database.
  8155. * Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
  8156. * @param {Array} attributes list of attributes that need to be saved. Defaults to null,
  8157. * meaning all attributes that are loaded from DB will be saved.
  8158. * @param {Function} callback The callback that will be executed after the update succeeds
  8159. * @returns {Mixed} The data source request
  8160. * @throws {Yii.CException} if the record is new
  8161. */
  8162. Yii.CAsyncRecord.prototype.update = function (attributes, callback) {
  8163. var self = this, func, postData;
  8164. if (attributes === undefined) {
  8165. attributes = null;
  8166. }
  8167. if(this.getIsNewRecord()) {
  8168. throw new Yii.CDbException(Yii.t('yii','The remote record cannot be updated because it is new.'));
  8169. }
  8170. if(this.beforeSave()) {
  8171. Yii.trace(this.getClassName()+'.update()','system.ds.CAsyncRecord');
  8172. func = function (data, dataSource) {
  8173. var model;
  8174. model = self.populateRecord(data);
  8175. model.afterSave();
  8176. model.setIsNewRecord(false);
  8177. model.setScenario('update');
  8178. callback(model, dataSource);
  8179. };
  8180. if (this.wrapData === true) {
  8181. postData = {};
  8182. postData[this.getClassName()] = this.getAttributes(attributes);
  8183. }
  8184. else if (this.wrapData) {
  8185. postData = {};
  8186. postData[this.wrapData] = this.getAttributes(attributes);
  8187. }
  8188. else {
  8189. postData = this.getAttributes(attributes);
  8190. }
  8191. return this.getDataSource().update(postData, func);
  8192. }
  8193. else {
  8194. return false;
  8195. }
  8196. };
  8197. /**
  8198. * Saves a selected list of attributes.
  8199. * Unlike {@link save}, this method only saves the specified attributes
  8200. * of an existing row dataset and does NOT call either {@link beforeSave} or {@link afterSave}.
  8201. * Also note that this method does neither attribute filtering nor validation.
  8202. * So do not use this method with untrusted data (such as user posted data).
  8203. * @param {Array} attributes attributes to be updated. Each element represents an attribute name
  8204. * or an attribute value indexed by its name. If the latter, the record's
  8205. * attribute will be changed accordingly before saving.
  8206. * @param {Function} callback The callback that will be executed after the insert succeeds
  8207. * @returns {Mixed} The data source request
  8208. * @throws {Yii.CException} if the record is new or any database error
  8209. */
  8210. Yii.CAsyncRecord.prototype.saveAttributes = function (attributes, callback) {
  8211. var values, name, value;
  8212. if(!this.getIsNewRecord()) {
  8213. Yii.trace(this.getClassName()+'.saveAttributes()','system.ds.CAsyncRecord');
  8214. values={};
  8215. for (name in attributes) {
  8216. if (attributes.hasOwnProperty(name)) {
  8217. value = attributes[name];
  8218. if((typeof(name) === 'number' && (name % 1 ? false : true))) {
  8219. values[value]=this[value];
  8220. }
  8221. else {
  8222. values[name]=this[name]=value;
  8223. }
  8224. }
  8225. }
  8226. Yii.trace(this.getClassName()+'.update()','system.ds.CAsyncRecord');
  8227. return this.getDataSource().update(values, callback);
  8228. }
  8229. else {
  8230. throw new Yii.CDbException(Yii.t('yii','The active record cannot be updated because it is new.'));
  8231. }
  8232. };
  8233. /**
  8234. * Saves the current record.
  8235. *
  8236. * The record is created if its {@link isNewRecord}
  8237. * property is true (usually the case when the record is created using the 'new'
  8238. * operator). Otherwise, it will be used to update the corresponding item in the data source
  8239. * (usually the case if the record is obtained using one of those 'find' methods.)
  8240. *
  8241. * Validation will be performed before saving the record. If the validation fails,
  8242. * the record will not be saved. You can call {@link getErrors()} to retrieve the
  8243. * validation errors.
  8244. *
  8245. * If the record is saved via insertion, its {@link isNewRecord} property will be
  8246. * set false, and its {@link scenario} property will be set to be 'update'.
  8247. * And if its primary key is auto-incremental and is not set before insertion,
  8248. * the primary key will be populated with the automatically generated key value.
  8249. * @param {Function} callback The callback function that will be executed after the save
  8250. * @param {Boolean} runValidation whether to perform validation before saving the record.
  8251. * If the validation fails, the record will not be saved to database.
  8252. * @param {Array} attributes list of attributes that need to be saved. Defaults to null,
  8253. * meaning all attributes that are loaded from DB will be saved.
  8254. * @returns {Mixed} the response from the data source
  8255. */
  8256. Yii.CAsyncRecord.prototype.save = function (callback, runValidation, attributes) {
  8257. if (runValidation === undefined) {
  8258. runValidation = true;
  8259. }
  8260. if (attributes === undefined) {
  8261. attributes = null;
  8262. }
  8263. if(!runValidation || this.validate(attributes)) {
  8264. return this.getIsNewRecord() ? this.create(attributes, callback) : this.update(attributes, callback);
  8265. }
  8266. else {
  8267. return false;
  8268. }
  8269. };
  8270. /**
  8271. * Creates a remote record with the given attributes.
  8272. * This method is internally used by the find methods.
  8273. * @param {Array} attributes attribute values (column name=>column value)
  8274. * @param {Boolean} callAfterFind whether to call {@link afterFind} after the record is populated.
  8275. * This parameter is added in version 1.0.3.
  8276. * @returns {Yii.CAsyncRecord} the newly created active record. The class of the object is the same as the model class.
  8277. * Null is returned if the input data is false.
  8278. */
  8279. Yii.CAsyncRecord.prototype.populateRecord = function (attributes, callAfterFind) {
  8280. var record, md, name, value;
  8281. if (callAfterFind === undefined) {
  8282. callAfterFind = true;
  8283. }
  8284. if(attributes!==false) {
  8285. record=this.instantiate(attributes);
  8286. record.setIsNewRecord(false);
  8287. record.setScenario('update');
  8288. record.init();
  8289. for (name in attributes) {
  8290. if (attributes.hasOwnProperty(name)) {
  8291. value = attributes[name];
  8292. if(record[name] !== undefined) {
  8293. record[name]=value;
  8294. }
  8295. else if(record._attributes[name] !== undefined) {
  8296. record._attributes[name]=value;
  8297. }
  8298. }
  8299. }
  8300. record._pk=record.getPrimaryKey();
  8301. record.attachBehaviors(record.behaviors());
  8302. if(callAfterFind) {
  8303. record.afterFind();
  8304. }
  8305. return record;
  8306. }
  8307. else {
  8308. return null;
  8309. }
  8310. };
  8311. /**
  8312. * Creates a list of active records based on the input data.
  8313. * This method is internally used by the find methods.
  8314. * @param {Array} data list of attribute values for the active records.
  8315. * @param {Boolean} callAfterFind whether to call {@link afterFind} after each record is populated.
  8316. * This parameter is added in version 1.0.3.
  8317. * @param {String} index the name of the attribute whose value will be used as indexes of the query result array.
  8318. * If null, it means the array will be indexed by zero-based integers.
  8319. * @returns {Array} list of active records.
  8320. */
  8321. Yii.CAsyncRecord.prototype.populateRecords = function (data, callAfterFind, index) {
  8322. var records, i, limit, record, attributes;
  8323. if (callAfterFind === undefined) {
  8324. callAfterFind = true;
  8325. }
  8326. if (index === undefined) {
  8327. index = null;
  8328. }
  8329. records=[];
  8330. limit = data.length;
  8331. for (i = 0; i < limit; i++) {
  8332. attributes = data[i];
  8333. if((record=this.populateRecord(attributes,callAfterFind))!==null) {
  8334. if(index===null) {
  8335. records.push(record);
  8336. }
  8337. else {
  8338. records[record[index]]=record;
  8339. }
  8340. }
  8341. }
  8342. return records;
  8343. };
  8344. /**
  8345. * Creates an active record instance.
  8346. * This method is called by {@link populateRecord} and {@link populateRecords}.
  8347. * You may override this method if the instance being created
  8348. * depends the attributes that are to be populated to the record.
  8349. * For example, by creating a record based on the value of a column,
  8350. * you may implement the so-called single-table inheritance mapping.
  8351. * @param {Object} attributes list of attribute values for the active records.
  8352. * @returns {Yii.CAsyncRecord} the active record
  8353. * @since 1.0.2
  8354. */
  8355. Yii.CAsyncRecord.prototype.instantiate = function (attributes) {
  8356. var classVar, model;
  8357. classVar=this.getClassName();
  8358. model=new Yii[classVar]();
  8359. return model;
  8360. };
  8361. /**
  8362. * Returns the primary key value.
  8363. * @returns {Mixed} the primary key value. An array (column name=>column value) is returned if the primary key is composite.
  8364. * If primary key is not defined, null will be returned.
  8365. */
  8366. Yii.CAsyncRecord.prototype.getPrimaryKey = function () {
  8367. var table, values,name,pk,self = this;
  8368. pk = this.primaryKey();
  8369. if(typeof(pk) === 'string') {
  8370. return this.get(pk);
  8371. }
  8372. else if(Object.prototype.toString.call(pk) === '[object Array]') {
  8373. values={};
  8374. Yii.forEach(pk, function (i, name) {
  8375. values[name] = self.get(name);
  8376. });
  8377. return values;
  8378. }
  8379. else {
  8380. return null;
  8381. }
  8382. };
  8383. /**
  8384. * Sets the primary key value.
  8385. * After calling this method, the old primary key value can be obtained from {@link oldPrimaryKey}.
  8386. * @param {Mixed} value the new primary key value. If the primary key is composite, the new value
  8387. * should be provided as an array (column name=>column value).
  8388. * @since 1.1.0
  8389. */
  8390. Yii.CAsyncRecord.prototype.setPrimaryKey = function (value) {
  8391. var table, values,name,pk,self = this;
  8392. pk = this.primaryKey();
  8393. if(typeof(pk) === 'string') {
  8394. this.set(pk, value);
  8395. }
  8396. else if(Object.prototype.toString.call(pk) === '[object Array]') {
  8397. values={};
  8398. Yii.forEach(pk, function (i, name) {
  8399. self[name] = value[i];
  8400. });
  8401. }
  8402. };
  8403. /**
  8404. * Performs a query, this is mainly used internally by the find / findAll methods
  8405. * @param {Function} callback The callback function to execute when data arrives
  8406. * @param {Object} criteria The criteria that will be sent to the server
  8407. * @param {Boolean} all whether to return all data or not
  8408. */
  8409. Yii.CAsyncRecord.prototype.query = function (callback, criteria, all) {
  8410. var command, finder, func, self = this;
  8411. if (all === undefined) {
  8412. all = false;
  8413. }
  8414. this.beforeFind();
  8415. func = function(data, dataSource) {
  8416. if (all) {
  8417. return callback(self.populateRecords(data, true), dataSource);
  8418. }
  8419. else {
  8420. return callback(self.populateRecord(data.shift(), true), dataSource);
  8421. }
  8422. };
  8423. return this.getDataSource().search(criteria,func);
  8424. };
  8425. /**
  8426. * Finds a single remote record with the specified condition.
  8427. * @param {Function} callback The callback function that will recieve the results
  8428. * @param {Mixed} criteria query criteria.
  8429. * @returns {Yii.CAsyncRecord} the record found. Null if no record is found.
  8430. */
  8431. Yii.CAsyncRecord.prototype.find = function (callback, criteria) {
  8432. Yii.trace(this.getClassName()+'.find()','system.ds.CAsyncRecord');
  8433. return this.query(callback, criteria);
  8434. };
  8435. /**
  8436. * Finds all remote records satisfying the specified condition.
  8437. * See {@link find()} for detailed explanation about $condition and $params.
  8438. * @param {Function} callback The callback function that will recieve the results
  8439. * @param {Mixed} criteria query criteria.
  8440. * @returns {Array} list of active records satisfying the specified condition. An empty array is returned if none is found.
  8441. */
  8442. Yii.CAsyncRecord.prototype.findAll = function (callback, criteria) {
  8443. Yii.trace(this.getClassName()+'.findAll()','system.ds.CAsyncRecord');
  8444. return this.query(callback, criteria,true);
  8445. };
  8446. /**
  8447. * Finds a remote active record with the specified primary key.
  8448. * See {@link find()} for detailed explanation about $condition and $params.
  8449. * @param {Function} callback The callback function that will recieve the results
  8450. * @param {Mixed} pk primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value).
  8451. * @returns {Yii.CAsyncRecord} the record found. Null if none is found.
  8452. */
  8453. Yii.CAsyncRecord.prototype.findByPk = function (callback, pk, criteria) {
  8454. var postData;
  8455. if (criteria === undefined) {
  8456. criteria = {};
  8457. }
  8458. criteria[this.primaryKey()] = pk;
  8459. if (this.wrapData === true) {
  8460. postData = {};
  8461. postData[this.getClassName()] = criteria;
  8462. }
  8463. else if (this.wrapData) {
  8464. postData = {};
  8465. postData[this.wrapData] = criteria;
  8466. }
  8467. else {
  8468. postData = criteria;
  8469. }
  8470. Yii.trace(this.getClassName()+'.findByPk()','system.ds.CAsyncRecord');
  8471. return this.query(callback, postData);
  8472. };
  8473. /**
  8474. * Finds all active records with the specified primary keys.
  8475. * See {@link find()} for detailed explanation about $condition and $params.
  8476. * @param {Function} callback The callback function that will recieve the results
  8477. * @param {Mixed} pk primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value).
  8478. * @param {Mixed} condition query condition or criteria.
  8479. * @param {Object} params parameters to be bound to an SQL statement.
  8480. * @returns {Array} the records found. An empty array is returned if none is found.
  8481. */
  8482. Yii.CAsyncRecord.prototype.findAllByPk = function (callback, pk, criteria) {
  8483. var postData;
  8484. if (criteria === undefined) {
  8485. criteria = {};
  8486. }
  8487. criteria[this.primaryKey()] = pk;
  8488. if (this.wrapData === true) {
  8489. postData = {};
  8490. postData[this.getClassName()] = criteria;
  8491. }
  8492. else if (this.wrapData) {
  8493. postData = {};
  8494. postData[this.wrapData] = criteria;
  8495. }
  8496. else {
  8497. postData = criteria;
  8498. }
  8499. Yii.trace(this.getClassName()+'.findAllByPk()','system.ds.CAsyncRecord');
  8500. return this.query(callback, postData,true);
  8501. };
  8502. /**
  8503. * Finds a single active record that has the specified attribute values.
  8504. * See {@link find()} for detailed explanation about $condition and $params.
  8505. * @param {Function} callback The callback function that will recieve the results
  8506. * @param {Object} attributes list of attribute values (indexed by attribute names) that the active records should match.
  8507. * Since version 1.0.8, an attribute value can be an array which will be used to generate an IN condition.
  8508. * @returns {Yii.CAsyncRecord} the record found. Null if none is found.
  8509. */
  8510. Yii.CAsyncRecord.prototype.findByAttributes = function (callback, attributes) {
  8511. var postData;
  8512. Yii.trace(this.getClassName()+'.findByAttributes()','system.ds.CAsyncRecord');
  8513. if (this.wrapData === true) {
  8514. postData = {};
  8515. postData[this.getClassName()] = attributes;
  8516. }
  8517. else if (this.wrapData) {
  8518. postData = {};
  8519. postData[this.wrapData] = attributes;
  8520. }
  8521. else {
  8522. postData = attributes;
  8523. }
  8524. return this.query(callback, postData);
  8525. };
  8526. /**
  8527. * Finds all active records that have the specified attribute values.
  8528. * See {@link find()} for detailed explanation about $condition and $params.
  8529. * @param {Function} callback The callback function that will recieve the results
  8530. * @param {Array} attributes list of attribute values (indexed by attribute names) that the active records should match.
  8531. * Since version 1.0.8, an attribute value can be an array which will be used to generate an IN condition.
  8532. * @returns {Array} the records found. An empty array is returned if none is found.
  8533. */
  8534. Yii.CAsyncRecord.prototype.findAllByAttributes = function (callback, attributes) {
  8535. var postData;
  8536. Yii.trace(this.getClassName()+'.findAllByAttributes()','system.ds.CAsyncRecord');
  8537. if (this.wrapData === true) {
  8538. postData = {};
  8539. postData[this.getClassName()] = attributes;
  8540. }
  8541. else if (this.wrapData) {
  8542. postData = {};
  8543. postData[this.wrapData] = attributes;
  8544. }
  8545. else {
  8546. postData = attributes;
  8547. }
  8548. return this.query(callback, postData, true);
  8549. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  8550. /**
  8551. * CAsyncRecordBehavior is the base class for behaviors that can be attached to {@link CAsyncRecord}.
  8552. * Compared with {@link CModelBehavior}, CAsyncRecordBehavior attaches to more events
  8553. * that are only defined by {@link CAsyncRecord}.
  8554. *
  8555. * @package system.ds
  8556. * @since 1.0.2
  8557. * @author Charles Pick
  8558. * @class
  8559. * @extends Yii.CModelBehavior
  8560. */
  8561. Yii.CAsyncRecordBehavior = function CAsyncRecordBehavior () {
  8562. };
  8563. Yii.CAsyncRecordBehavior.prototype = new Yii.CModelBehavior();
  8564. Yii.CAsyncRecordBehavior.prototype.constructor = Yii.CAsyncRecordBehavior;
  8565. /**
  8566. * Declares events and the corresponding event handler methods.
  8567. * If you override this method, make sure you merge the parent result to the return value.
  8568. * @returns {Array} events (array keys) and the corresponding event handler methods (array values).
  8569. * @see CBehavior::events
  8570. */
  8571. Yii.CAsyncRecordBehavior.prototype.events = function () {
  8572. return php.array_merge(parent.events(), {
  8573. 'onBeforeSave':'beforeSave',
  8574. 'onAfterSave':'afterSave',
  8575. 'onBeforeDelete':'beforeDelete',
  8576. 'onAfterDelete':'afterDelete',
  8577. 'onBeforeFind':'beforeFind',
  8578. 'onAfterFind':'afterFind'
  8579. });
  8580. };
  8581. /**
  8582. * Responds to {@link CAsyncRecord::onBeforeSave} event.
  8583. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  8584. * You may set {@link CModelEvent::isValid} to be false to quit the saving process.
  8585. * @param {Yii.CModelEvent} event event parameter
  8586. */
  8587. Yii.CAsyncRecordBehavior.prototype.beforeSave = function (event) {
  8588. };
  8589. /**
  8590. * Responds to {@link CAsyncRecord::onAfterSave} event.
  8591. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  8592. * @param {Yii.CModelEvent} event event parameter
  8593. */
  8594. Yii.CAsyncRecordBehavior.prototype.afterSave = function (event) {
  8595. };
  8596. /**
  8597. * Responds to {@link CAsyncRecord::onBeforeDelete} event.
  8598. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  8599. * You may set {@link CModelEvent::isValid} to be false to quit the deletion process.
  8600. * @param {Yii.CEvent} event event parameter
  8601. */
  8602. Yii.CAsyncRecordBehavior.prototype.beforeDelete = function (event) {
  8603. };
  8604. /**
  8605. * Responds to {@link CAsyncRecord::onAfterDelete} event.
  8606. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  8607. * @param {Yii.CEvent} event event parameter
  8608. */
  8609. Yii.CAsyncRecordBehavior.prototype.afterDelete = function (event) {
  8610. };
  8611. /**
  8612. * Responds to {@link CAsyncRecord::onBeforeFind} event.
  8613. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  8614. * @param {Yii.CEvent} event event parameter
  8615. * @since 1.0.9
  8616. */
  8617. Yii.CAsyncRecordBehavior.prototype.beforeFind = function (event) {
  8618. };
  8619. /**
  8620. * Responds to {@link CAsyncRecord::onAfterFind} event.
  8621. * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
  8622. * @param {Yii.CEvent} event event parameter
  8623. */
  8624. Yii.CAsyncRecordBehavior.prototype.afterFind = function (event) {
  8625. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  8626. /**
  8627. * A class for retrieving data from JSON data sources
  8628. * @package system.ds
  8629. * @since 1.0
  8630. * @author Charles Pick
  8631. * @class
  8632. * @extends Yii.CActiveDataSource
  8633. */
  8634. Yii.CJSONDataSource = function CJSONDataSource (construct) {
  8635. if (construct !== false) {
  8636. this.ajaxOptions = {};
  8637. this.cacheDuration = null;
  8638. this.cacheDependency = null;
  8639. this.cacheKey = null;
  8640. }
  8641. };
  8642. Yii.CJSONDataSource.prototype = new Yii.CActiveDataSource();
  8643. Yii.CJSONDataSource.prototype.constructor = Yii.CJSONDataSource;
  8644. Yii.CJSONDataSource.prototype.cacheDependency = null;
  8645. Yii.CJSONDataSource.prototype.cacheDuration = null;
  8646. Yii.CJSONDataSource.prototype._cacheKey = null;
  8647. Yii.CJSONDataSource.prototype.cache = function (duration, dependency) {
  8648. this.cacheDuration = duration;
  8649. this.cacheDependency = dependency;
  8650. };
  8651. /**
  8652. * Gets the cache key
  8653. */
  8654. Yii.CJSONDataSource.prototype.getCacheKey = function() {
  8655. if (this._cacheKey === null) {
  8656. this._cacheKey = Yii.CJSON.encode(this.ajaxOptions);
  8657. }
  8658. return this._cacheKey;
  8659. };
  8660. /**
  8661. * Whether to use JSONP or not, defaults to false meaning use AJAX for requests.
  8662. * @var Boolean
  8663. */
  8664. Yii.CJSONDataSource.prototype.useJSONP = false;
  8665. /**
  8666. * Options to pass to the ajax request.
  8667. * @var Object
  8668. */
  8669. Yii.CJSONDataSource.prototype.ajaxOptions = {};
  8670. /**
  8671. * A list of actions and their respective URLs. has the format:
  8672. * {
  8673. * 'list': 'http://example.com/products/list.json',
  8674. * 'search': ['product/search', {'format': 'json'}],
  8675. * 'create': ['product/create', {'format': 'json'}],
  8676. * 'update': ['product/update', {'format': 'json'}]
  8677. * }
  8678. * @see Yii.CHtml.normalizeUrl
  8679. * @var Object
  8680. */
  8681. Yii.CJSONDataSource.prototype.routes = {};
  8682. /**
  8683. * Makes the request and executes the callback when data arrives.
  8684. * @param {Function} callback The callback function to execute, this will recieve the
  8685. * data as its first parameter and the data source as its second parameter.
  8686. * @returns {jQuery.ajaxRequest} The ajax request
  8687. */
  8688. Yii.CJSONDataSource.prototype.makeRequest = function (callback) {
  8689. var options, source = this, result;
  8690. if (this.ajaxOptions.type === undefined) {
  8691. this.ajaxOptions.type = "GET";
  8692. }
  8693. this.ajaxOptions.success = function (data) {
  8694. if (source.cacheDuration !== null && source.ajaxOptions.type.toLowerCase() === "get") {
  8695. Yii.app().getCache().set(source.getCacheKey(), data, source.cacheDuration);
  8696. }
  8697. callback(data, source);
  8698. };
  8699. if (source.ajaxOptions.type.toLowerCase() === "get" && source.cacheDuration !== null && (result = Yii.app().getCache().get(source.getCacheKey())) !== false) {
  8700. return callback(result, source);
  8701. }
  8702. return Yii.app().ajax.makeRequest(this.ajaxOptions);
  8703. };
  8704. /**
  8705. * Gets a list of items from the data source
  8706. * @param {Function} callback the callback function to execute, this will
  8707. * receive the response from the server as its first parameter and the data source
  8708. * as the second parameter
  8709. * @returns {jQuery.ajaxRequest} The ajax request
  8710. */
  8711. Yii.CJSONDataSource.prototype.list = function (callback) {
  8712. this.ajaxOptions.url = this.routes.list;
  8713. return this.makeRequest(callback);
  8714. };
  8715. /**
  8716. * Searches for items from the data source.
  8717. * @param {Object} criteria The search criteria, field:'search query'
  8718. * @param {Function} callback the callback function to execute, this will
  8719. * receive the response from the server as its first parameter and the data source
  8720. * as the second parameter
  8721. * @returns {jQuery.ajaxRequest} The ajax request
  8722. */
  8723. Yii.CJSONDataSource.prototype.search = function (criteria, callback) {
  8724. this.ajaxOptions.data = criteria;
  8725. this.ajaxOptions.url = this.routes.search;
  8726. return this.makeRequest(callback);
  8727. };
  8728. /**
  8729. * Creates a new item.
  8730. * @param {Object} data The data to post to the server
  8731. * @param {Function} callback the callback function to execute, this will
  8732. * receive the response from the server as its first parameter and the data source
  8733. * as the second parameter
  8734. * @returns {jQuery.ajaxRequest} The ajax request
  8735. */
  8736. Yii.CJSONDataSource.prototype.create = function (data, callback) {
  8737. this.ajaxOptions.data = data;
  8738. if (this.ajaxOptions.type === undefined || this.ajaxOptions.type.toLowerCase() === "get") {
  8739. this.ajaxOptions.type = "post";
  8740. }
  8741. this.ajaxOptions.url = this.routes.create;
  8742. return this.makeRequest(callback);
  8743. };
  8744. /**
  8745. * Updates an item
  8746. * @param {Object} data The data to post to the server
  8747. * @param {Function} callback the callback function to execute, this will
  8748. * receive the response from the server as its first parameter and the data source
  8749. * as the second parameter
  8750. * @returns {jQuery.ajaxRequest} The ajax request
  8751. */
  8752. Yii.CJSONDataSource.prototype.update = function (data, callback) {
  8753. this.ajaxOptions.data = data;
  8754. if (this.ajaxOptions.type === undefined || this.ajaxOptions.type.toLowerCase() === "get") {
  8755. this.ajaxOptions.type = "post";
  8756. }
  8757. this.ajaxOptions.url = this.routes.update;
  8758. return this.makeRequest(callback);
  8759. };
  8760. /**
  8761. * Deletes an item
  8762. * @param {Object} data The data to post to the server
  8763. * @param {Function} callback the callback function to execute, this will
  8764. * receive the response from the server as its first parameter and the data source
  8765. * as the second parameter
  8766. * @returns {jQuery.ajaxRequest} The ajax request
  8767. */
  8768. Yii.CJSONDataSource.prototype.remove = function (data, callback) {
  8769. this.ajaxOptions.data = data;
  8770. if (this.ajaxOptions.type === undefined || this.ajaxOptions.type.toLowerCase() === "get") {
  8771. this.ajaxOptions.type = "post";
  8772. }
  8773. this.ajaxOptions.url = this.routes.remove;
  8774. return this.makeRequest(callback);
  8775. };
  8776. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  8777. /**
  8778. * CChoiceFormat is a helper that chooses an appropriate message based on the specified number value.
  8779. * The candidate messages are given as a string in the following format:
  8780. * <pre>
  8781. * 'expr1#message1|expr2#message2|expr3#message3'
  8782. * </pre>
  8783. * where each expression should be a valid PHP expression with 'n' as the only variable.
  8784. * For example, 'n==1' and 'n%10==2 && n>10' are both valid expressions.
  8785. * The variable 'n' will take the given number value, and if an expression evaluates true,
  8786. * the corresponding message will be returned.
  8787. *
  8788. * For example, given the candidate messages 'n==1#one|n==2#two|n>2#others' and
  8789. * the number value 2, the resulting message will be 'two'.
  8790. *
  8791. * For expressions like 'n==1', we can also use a shortcut '1'. So the above example
  8792. * candidate messages can be simplified as '1#one|2#two|n>2#others'.
  8793. *
  8794. * In case the given number doesn't select any message, the last candidate message
  8795. * will be returned.
  8796. *
  8797. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  8798. * @version $Id: CChoiceFormat.php 2899 2011-01-20 21:10:03Z alexander.makarow $
  8799. * @package system.i18n
  8800. * @since 1.0.2
  8801. * @author Charles Pick
  8802. * @class
  8803. */
  8804. Yii.CChoiceFormat = function CChoiceFormat () {
  8805. };
  8806. /**
  8807. * Formats a message according to the specified number value.
  8808. * @param {String} messages the candidate messages in the format of 'expr1#message1|expr2#message2|expr3#message3'.
  8809. * See {@link CChoiceFormat} for more details.
  8810. * @param {Mixed} number the number value
  8811. * @returns {String} the selected message
  8812. */
  8813. Yii.CChoiceFormat.prototype.format = function (messages, number) {
  8814. var n, matches, i, expression, message, match;
  8815. matches = (messages + "|").match(/\s*([^#]*)\s*#([^\|]*)\|/g);
  8816. if (matches !== null) {
  8817. n = matches.length;
  8818. }
  8819. else {
  8820. return messages;
  8821. }
  8822. if(n===0) {
  8823. return messages;
  8824. }
  8825. for(i=0;i<n;++i) {
  8826. match = matches[i].match(/\s*([^#]*)\s*#([^\|]*)\|/);
  8827. expression=match[0];
  8828. message=match[1];
  8829. if(expression===String(Number(expression))) {
  8830. if(expression==number) {
  8831. return message;
  8832. }
  8833. }
  8834. else if(this.evaluate(expression,number)) {
  8835. return message;
  8836. }
  8837. }
  8838. return message; // return the last choice
  8839. };
  8840. /**
  8841. * Evaluates a PHP expression with the given number value.
  8842. * @param {String} expression the PHP expression
  8843. * @param {Mixed} n the number value
  8844. * @returns {Boolean} the expression result
  8845. */
  8846. Yii.CChoiceFormat.prototype.evaluate = function (expression, n) {
  8847. return eval(expression);
  8848. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  8849. /**
  8850. * CDateFormatter provides date/time localization functionalities.
  8851. *
  8852. * CDateFormatter allows you to format dates and times in a locale-sensitive manner.
  8853. * Patterns are interpreted in the locale that the CDateFormatter instance
  8854. * is associated with. For example, month names and weekday names may vary
  8855. * under different locales, which yields different formatting results.
  8856. * The patterns that CDateFormatter recognizes are as defined in
  8857. * {@link http://www.unicode.org/reports/tr35/#Date_Format_Patterns CLDR}.
  8858. *
  8859. * CDateFormatter supports predefined patterns as well as customized ones:
  8860. * <ul>
  8861. * <li>The method {@link formatDateTime()} formats date or time or both using
  8862. * predefined patterns which include 'full', 'long', 'medium' (default) and 'short'.</li>
  8863. * <li>The method {@link format()} formats datetime using the specified pattern.
  8864. * See {@link http://www.unicode.org/reports/tr35/#Date_Format_Patterns} for
  8865. * details about the recognized pattern characters.</li>
  8866. * </ul>
  8867. *
  8868. * @originalAuthor Wei Zhuo <weizhuo[at]gmail[dot]com>
  8869. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  8870. * @version $Id: CDateFormatter.php 2798 2011-01-01 19:29:03Z qiang.xue $
  8871. * @package system.i18n
  8872. * @since 1.0
  8873. * @author Charles Pick
  8874. * @class
  8875. * @extends Yii.CComponent
  8876. */
  8877. Yii.CDateFormatter = function CDateFormatter (locale) {
  8878. if (locale !== false) {
  8879. this.construct(false);
  8880. }
  8881. };
  8882. Yii.CDateFormatter.prototype = new Yii.CComponent();
  8883. Yii.CDateFormatter.prototype.constructor = Yii.CDateFormatter;
  8884. /**
  8885. * @var {Array} pattern characters mapping to the corresponding translator methods
  8886. */
  8887. Yii.CDateFormatter.prototype._formatters = {'G':'formatEra','y':'formatYear','M':'formatMonth','L':'formatMonth','d':'formatDay','h':'formatHour12','H':'formatHour24','m':'formatMinutes','s':'formatSeconds','E':'formatDayInWeek','c':'formatDayInWeek','e':'formatDayInWeek','D':'formatDayInYear','F':'formatDayInMonth','w':'formatWeekInYear','W':'formatWeekInMonth','a':'formatPeriod','k':'formatHourInDay','K':'formatHourInPeriod','z':'formatTimeZone','Z':'formatTimeZone','v':'formatTimeZone'};
  8888. Yii.CDateFormatter.prototype._locale = null;
  8889. Yii.CDateFormatter.prototype._formats = [];
  8890. /**
  8891. * Constructor.
  8892. * @param {Mixed} locale locale ID (string) or CLocale instance
  8893. */
  8894. Yii.CDateFormatter.prototype.construct = function (locale) {
  8895. if(typeof(locale) === 'string') {
  8896. this._locale=Yii.CLocale.getInstance(locale);
  8897. }
  8898. else {
  8899. this._locale=locale;
  8900. }
  8901. };
  8902. /**
  8903. * Formats a date according to a customized pattern.
  8904. * @param {String} pattern the pattern (See {@link http://www.unicode.org/reports/tr35/#Date_Format_Patterns})
  8905. * @param {Mixed} time UNIX timestamp or a string in strtotime format
  8906. * @returns {String} formatted date time.
  8907. */
  8908. Yii.CDateFormatter.prototype.format = function (pattern, time) {
  8909. var date, tokens, i, token;
  8910. if(typeof(time) === 'string')
  8911. {
  8912. if(php.ctype_digit(time)) {
  8913. time=Number(time);
  8914. }
  8915. else {
  8916. time=php.strtotime(time);
  8917. }
  8918. }
  8919. date=Yii.CTimestamp.getdate(time,false,false);
  8920. tokens=this.parseFormat(pattern);
  8921. for (i in tokens) {
  8922. if (tokens.hasOwnProperty(i)) {
  8923. if(Object.prototype.toString.call(tokens[i]) === '[object Array]') {
  8924. // a callback: method name, sub-pattern
  8925. tokens[i]=this[tokens[i][0]](tokens[i][1],date);
  8926. }
  8927. }
  8928. }
  8929. return tokens.join('');
  8930. };
  8931. /**
  8932. * Formats a date according to a predefined pattern.
  8933. * The predefined pattern is determined based on the date pattern width and time pattern width.
  8934. * @param {Mixed} timestamp UNIX timestamp or a string in strtotime format
  8935. * @param {String} dateWidth width of the date pattern. It can be 'full', 'long', 'medium' and 'short'.
  8936. * If null, it means the date portion will NOT appear in the formatting result
  8937. * @param {String} timeWidth width of the time pattern. It can be 'full', 'long', 'medium' and 'short'.
  8938. * If null, it means the time portion will NOT appear in the formatting result
  8939. * @returns {String} formatted date time.
  8940. */
  8941. Yii.CDateFormatter.prototype.formatDateTime = function (timestamp, dateWidth, timeWidth) {
  8942. var date, time, dateTimePattern;
  8943. if (dateWidth === undefined) {
  8944. dateWidth = 'medium';
  8945. }
  8946. if (timeWidth === undefined) {
  8947. timeWidth = 'medium';
  8948. }
  8949. if(!php.empty(dateWidth)) {
  8950. date=this.format(this._locale.getDateFormat(dateWidth),timestamp);
  8951. }
  8952. if(!php.empty(timeWidth)) {
  8953. time=this.format(this._locale.getTimeFormat(timeWidth),timestamp);
  8954. }
  8955. if(date !== undefined && time !== undefined) {
  8956. dateTimePattern=this._locale.getDateTimeFormat();
  8957. return php.strtr(dateTimePattern,{'{0}':time,'{1}':date});
  8958. }
  8959. else if(date !== undefined) {
  8960. return date;
  8961. }
  8962. else if(time !== undefined) {
  8963. return time;
  8964. }
  8965. };
  8966. /**
  8967. * Parses the datetime format pattern.
  8968. * @param {String} pattern the pattern to be parsed
  8969. * @returns {Array} tokenized parsing result
  8970. */
  8971. Yii.CDateFormatter.prototype.parseFormat = function (pattern) {
  8972. var tokens, n, isLiteral, literal, i, c, j, p, _formatters;
  8973. if(this._formats[pattern] !== undefined) {
  8974. return this._formats[pattern];
  8975. }
  8976. tokens=[];
  8977. n=php.strlen(pattern);
  8978. isLiteral=false;
  8979. literal='';
  8980. for(i=0;i<n;++i) {
  8981. c=pattern[i];
  8982. if(c==="'") {
  8983. if(i<n-1 && pattern[i+1]==="'"){
  8984. tokens.push("'");
  8985. i++;
  8986. }
  8987. else if(isLiteral){
  8988. tokens.push(literal);
  8989. literal='';
  8990. isLiteral=false;
  8991. }
  8992. else{
  8993. isLiteral=true;
  8994. literal='';
  8995. }
  8996. }
  8997. else if(isLiteral) {
  8998. literal+=c;
  8999. }
  9000. else {
  9001. for(j=i+1;j<n;++j) {
  9002. if(pattern[j]!==c) {
  9003. break;
  9004. }
  9005. }
  9006. p=php.str_repeat(c,j-i);
  9007. if(this._formatters[c] !== undefined) {
  9008. tokens.push([this._formatters[c],p]);
  9009. }
  9010. else {
  9011. tokens.push(p);
  9012. }
  9013. i=j-1;
  9014. }
  9015. }
  9016. if(literal!=='') {
  9017. tokens.push(literal);
  9018. }
  9019. return (this._formats[pattern]=tokens);
  9020. };
  9021. /**
  9022. * Get the year.
  9023. * "yy" will return the last two digits of year.
  9024. * "y...y" will pad the year with 0 in the front, e.g. "yyyyy" will generate "02008" for year 2008.
  9025. * @param {String} pattern a pattern.
  9026. * @param {Array} date result of {@link CTimestamp::getdate}.
  9027. * @returns {String} formatted year
  9028. */
  9029. Yii.CDateFormatter.prototype.formatYear = function (pattern, date) {
  9030. var year;
  9031. year=date.year;
  9032. if(pattern==='yy') {
  9033. return php.str_pad(year%100,2,'0','STR_PAD_LEFT');
  9034. }
  9035. else {
  9036. return php.str_pad(year,php.strlen(pattern),'0','STR_PAD_LEFT');
  9037. }
  9038. };
  9039. /**
  9040. * Get the month.
  9041. * "M" will return integer 1 through 12;
  9042. * "MM" will return two digits month number with necessary zero padding, e.g. 05;
  9043. * "MMM" will return the abrreviated month name, e.g. "Jan";
  9044. * "MMMM" will return the full month name, e.g. "January";
  9045. * "MMMMM" will return the narrow month name, e.g. "J";
  9046. * @param {String} pattern a pattern.
  9047. * @param {Array} date result of {@link CTimestamp::getdate}.
  9048. * @returns {String} month name
  9049. */
  9050. Yii.CDateFormatter.prototype.formatMonth = function (pattern, date) {
  9051. var month;
  9052. month=date.mon;
  9053. switch(pattern) {
  9054. case 'M':
  9055. return month;
  9056. case 'MM':
  9057. return php.str_pad(month,2,'0','STR_PAD_LEFT');
  9058. case 'MMM':
  9059. return this._locale.getMonthName(month,'abbreviated');
  9060. case 'MMMM':
  9061. return this._locale.getMonthName(month,'wide');
  9062. case 'MMMMM':
  9063. return this._locale.getMonthName(month,'narrow');
  9064. case 'L':
  9065. return month;
  9066. case 'LL':
  9067. return php.str_pad(month,2,'0','STR_PAD_LEFT');
  9068. case 'LLL':
  9069. return this._locale.getMonthName(month,'abbreviated', true);
  9070. case 'LLLL':
  9071. return this._locale.getMonthName(month,'wide', true);
  9072. case 'LLLLL':
  9073. return this._locale.getMonthName(month,'narrow', true);
  9074. default:
  9075. throw new Yii.CException(Yii.t('yii','The pattern for month must be "M", "MM", "MMM", "MMMM", "L", "LL", "LLL" or "LLLL".'));
  9076. }
  9077. };
  9078. /**
  9079. * Get the day of the month.
  9080. * "d" for non-padding, "dd" will always return 2 digits day numbers, e.g. 05.
  9081. * @param {String} pattern a pattern.
  9082. * @param {Array} date result of {@link CTimestamp::getdate}.
  9083. * @returns {String} day of the month
  9084. */
  9085. Yii.CDateFormatter.prototype.formatDay = function (pattern, date) {
  9086. var day;
  9087. day=date.mday;
  9088. if(pattern==='d') {
  9089. return day;
  9090. }
  9091. else if(pattern==='dd') {
  9092. return php.str_pad(day,2,'0','STR_PAD_LEFT');
  9093. }
  9094. else {
  9095. throw new Yii.CException(Yii.t('yii','The pattern for day of the month must be "d" or "dd".'));
  9096. }
  9097. };
  9098. /**
  9099. * Get the day in the year, e.g. [1-366]
  9100. * @param {String} pattern a pattern.
  9101. * @param {Array} date result of {@link CTimestamp::getdate}.
  9102. * @returns {Integer} hours in AM/PM format.
  9103. */
  9104. Yii.CDateFormatter.prototype.formatDayInYear = function (pattern, date) {
  9105. var day, n;
  9106. day=date.yday;
  9107. if((n=php.strlen(pattern))<=3) {
  9108. return php.str_pad(day,n,'0','STR_PAD_LEFT');
  9109. }
  9110. else {
  9111. throw new Yii.CException(Yii.t('yii','The pattern for day in year must be "D", "DD" or "DDD".'));
  9112. }
  9113. };
  9114. /**
  9115. * Get day of week in the month, e.g. 2nd Wed in July.
  9116. * @param {String} pattern a pattern.
  9117. * @param {Array} date result of {@link CTimestamp::getdate}.
  9118. * @returns {Integer} day in month
  9119. * @see http://www.unicode.org/reports/tr35/#Date_Format_Patterns
  9120. */
  9121. Yii.CDateFormatter.prototype.formatDayInMonth = function (pattern, date) {
  9122. if(pattern==='F') {
  9123. return Number((date.mday+6)/7);
  9124. }
  9125. else {
  9126. throw new Yii.CException(Yii.t('yii','The pattern for day in month must be "F".'));
  9127. }
  9128. };
  9129. /**
  9130. * Get the day of the week.
  9131. * "E", "EE", "EEE" will return abbreviated week day name, e.g. "Tues";
  9132. * "EEEE" will return full week day name;
  9133. * "EEEEE" will return the narrow week day name, e.g. "T";
  9134. * @param {String} pattern a pattern.
  9135. * @param {Array} date result of {@link CTimestamp::getdate}.
  9136. * @returns {String} day of the week.
  9137. * @see http://www.unicode.org/reports/tr35/#Date_Format_Patterns
  9138. */
  9139. Yii.CDateFormatter.prototype.formatDayInWeek = function (pattern, date) {
  9140. var day;
  9141. day=date.wday;
  9142. switch(pattern) {
  9143. case 'E':
  9144. case 'EE':
  9145. case 'EEE':
  9146. case 'eee':
  9147. return this._locale.getWeekDayName(day,'abbreviated');
  9148. case 'EEEE':
  9149. case 'eeee':
  9150. return this._locale.getWeekDayName(day,'wide');
  9151. case 'EEEEE':
  9152. case 'eeeee':
  9153. return this._locale.getWeekDayName(day,'narrow');
  9154. case 'e':
  9155. case 'ee':
  9156. case 'c':
  9157. return day ? day : 7;
  9158. case 'ccc':
  9159. return this._locale.getWeekDayName(day,'abbreviated',true);
  9160. case 'cccc':
  9161. return this._locale.getWeekDayName(day,'wide',true);
  9162. case 'ccccc':
  9163. return this._locale.getWeekDayName(day,'narrow',true);
  9164. default:
  9165. throw new Yii.CException(Yii.t('yii','The pattern for day of the week must be "E", "EE", "EEE", "EEEE", "EEEEE", "e", "ee", "eee", "eeee", "eeeee", "c", "cccc" or "ccccc".'));
  9166. }
  9167. };
  9168. /**
  9169. * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
  9170. * @param {String} pattern a pattern.
  9171. * @param {Array} date result of {@link CTimestamp::getdate}.
  9172. * @returns {String} AM or PM designator
  9173. */
  9174. Yii.CDateFormatter.prototype.formatPeriod = function (pattern, date) {
  9175. if(pattern==='a') {
  9176. if(php.intval(date.hours/12)) {
  9177. return this._locale.getPMName();
  9178. }
  9179. else {
  9180. return this._locale.getAMName();
  9181. }
  9182. }
  9183. else {
  9184. throw new Yii.CException(Yii.t('yii','The pattern for AM/PM marker must be "a".'));
  9185. }
  9186. };
  9187. /**
  9188. * Get the hours in 24 hour format, i.e. [0-23].
  9189. * "H" for non-padding, "HH" will always return 2 characters.
  9190. * @param {String} pattern a pattern.
  9191. * @param {Array} date result of {@link CTimestamp::getdate}.
  9192. * @returns {String} hours in 24 hour format.
  9193. */
  9194. Yii.CDateFormatter.prototype.formatHour24 = function (pattern, date) {
  9195. var hour;
  9196. hour=date.hours;
  9197. if(pattern==='H') {
  9198. return hour;
  9199. }
  9200. else if(pattern==='HH') {
  9201. return php.str_pad(hour,2,'0','STR_PAD_LEFT');
  9202. }
  9203. else {
  9204. throw new Yii.CException(Yii.t('yii','The pattern for 24 hour format must be "H" or "HH".'));
  9205. }
  9206. };
  9207. /**
  9208. * Get the hours in 12 hour format, i.e., [1-12]
  9209. * "h" for non-padding, "hh" will always return 2 characters.
  9210. * @param {String} pattern a pattern.
  9211. * @param {Array} date result of {@link CTimestamp::getdate}.
  9212. * @returns {String} hours in 12 hour format.
  9213. */
  9214. Yii.CDateFormatter.prototype.formatHour12 = function (pattern, date) {
  9215. var hour;
  9216. hour=date.hours;
  9217. hour=(hour==12|hour===0)?12:(hour)%12;
  9218. if(pattern==='h') {
  9219. return hour;
  9220. }
  9221. else if(pattern==='hh') {
  9222. return php.str_pad(hour,2,'0','STR_PAD_LEFT');
  9223. }
  9224. else {
  9225. throw new Yii.CException(Yii.t('yii','The pattern for 12 hour format must be "h" or "hh".'));
  9226. }
  9227. };
  9228. /**
  9229. * Get the hours [1-24].
  9230. * 'k' for non-padding, and 'kk' with 2 characters padding.
  9231. * @param {String} pattern a pattern.
  9232. * @param {Array} date result of {@link CTimestamp::getdate}.
  9233. * @returns {Integer} hours [1-24]
  9234. */
  9235. Yii.CDateFormatter.prototype.formatHourInDay = function (pattern, date) {
  9236. var hour;
  9237. hour=date.hours==0?24:date.hours;
  9238. if(pattern==='k') {
  9239. return hour;
  9240. }
  9241. else if(pattern==='kk') {
  9242. return php.str_pad(hour,2,'0','STR_PAD_LEFT');
  9243. }
  9244. else {
  9245. throw new Yii.CException(Yii.t('yii','The pattern for hour in day must be "k" or "kk".'));
  9246. }
  9247. };
  9248. /**
  9249. * Get the hours in AM/PM format, e.g [0-11]
  9250. * "K" for non-padding, "KK" will always return 2 characters.
  9251. * @param {String} pattern a pattern.
  9252. * @param {Array} date result of {@link CTimestamp::getdate}.
  9253. * @returns {Integer} hours in AM/PM format.
  9254. */
  9255. Yii.CDateFormatter.prototype.formatHourInPeriod = function (pattern, date) {
  9256. var hour;
  9257. hour=date.hours%12;
  9258. if(pattern==='K') {
  9259. return hour;
  9260. }
  9261. else if(pattern==='KK') {
  9262. return php.str_pad(hour,2,'0','STR_PAD_LEFT');
  9263. }
  9264. else {
  9265. throw new Yii.CException(Yii.t('yii','The pattern for hour in AM/PM must be "K" or "KK".'));
  9266. }
  9267. };
  9268. /**
  9269. * Get the minutes.
  9270. * "m" for non-padding, "mm" will always return 2 characters.
  9271. * @param {String} pattern a pattern.
  9272. * @param {Array} date result of {@link CTimestamp::getdate}.
  9273. * @returns {String} minutes.
  9274. */
  9275. Yii.CDateFormatter.prototype.formatMinutes = function (pattern, date) {
  9276. var minutes;
  9277. minutes=date.minutes;
  9278. if(pattern==='m') {
  9279. return minutes;
  9280. }
  9281. else if(pattern==='mm') {
  9282. return php.str_pad(minutes,2,'0','STR_PAD_LEFT');
  9283. }
  9284. else {
  9285. throw new Yii.CException(Yii.t('yii','The pattern for minutes must be "m" or "mm".'));
  9286. }
  9287. };
  9288. /**
  9289. * Get the seconds.
  9290. * "s" for non-padding, "ss" will always return 2 characters.
  9291. * @param {String} pattern a pattern.
  9292. * @param {Array} date result of {@link CTimestamp::getdate}.
  9293. * @returns {String} seconds
  9294. */
  9295. Yii.CDateFormatter.prototype.formatSeconds = function (pattern, date) {
  9296. var seconds;
  9297. seconds=date.seconds;
  9298. if(pattern==='s') {
  9299. return seconds;
  9300. }
  9301. else if(pattern==='ss') {
  9302. return php.str_pad(seconds,2,'0','STR_PAD_LEFT');
  9303. }
  9304. else {
  9305. throw new Yii.CException(Yii.t('yii','The pattern for seconds must be "s" or "ss".'));
  9306. }
  9307. };
  9308. /**
  9309. * Get the week in the year.
  9310. * @param {String} pattern a pattern.
  9311. * @param {Array} date result of {@link CTimestamp::getdate}.
  9312. * @returns {Integer} week in year
  9313. */
  9314. Yii.CDateFormatter.prototype.formatWeekInYear = function (pattern, date) {
  9315. if(pattern==='w') {
  9316. return php.date('W',php.mktime(0,0,0,date.mon,date.mday,date.year));
  9317. }
  9318. else {
  9319. throw new Yii.CException(Yii.t('yii','The pattern for week in year must be "w".'));
  9320. }
  9321. };
  9322. /**
  9323. * Get week in the month.
  9324. * @param {Array} pattern result of {@link CTimestamp::getdate}.
  9325. * @param {String} date a pattern.
  9326. * @returns {Integer} week in month
  9327. */
  9328. Yii.CDateFormatter.prototype.formatWeekInMonth = function (pattern, date) {
  9329. if(pattern==='W') {
  9330. return php.date('W',php.mktime(0,0,0,date.mon, date.mday,date.year))-php.date('W', php.mktime(0,0,0,date.mon,1,date.year))+1;
  9331. }
  9332. else {
  9333. throw new Yii.CException(Yii.t('yii','The pattern for week in month must be "W".'));
  9334. }
  9335. };
  9336. /**
  9337. * Get the timezone of the server machine.
  9338. * @param {String} pattern a pattern.
  9339. * @param {Array} date result of {@link CTimestamp::getdate}.
  9340. * @returns {String} time zone
  9341. * @todo How to get the timezone for a different region?
  9342. */
  9343. Yii.CDateFormatter.prototype.formatTimeZone = function (pattern, date) {
  9344. if(pattern[0]==='z' || pattern[0]==='v') {
  9345. return php.date('T', php.mktime(date.hours, date.minutes, date.seconds, date.mon, date.mday, date.year));
  9346. }
  9347. else if(pattern[0]==='Z') {
  9348. return php.date('O', php.mktime(date.hours, date.minutes, date.seconds, date.mon, date.mday, date.year));
  9349. }
  9350. else {
  9351. throw new Yii.CException(Yii.t('yii','The pattern for time zone must be "z" or "v".'));
  9352. }
  9353. };
  9354. /**
  9355. * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
  9356. * @param {String} pattern a pattern.
  9357. * @param {Array} date result of {@link CTimestamp::getdate}.
  9358. * @returns {String} era
  9359. * @todo How to support multiple Eras?, e.g. Japanese.
  9360. */
  9361. Yii.CDateFormatter.prototype.formatEra = function (pattern, date) {
  9362. var era;
  9363. era=date.year>0 ? 1 : 0;
  9364. switch(pattern)
  9365. {
  9366. case 'G':
  9367. case 'GG':
  9368. case 'GGG':
  9369. return this._locale.getEraName(era,'abbreviated');
  9370. case 'GGGG':
  9371. return this._locale.getEraName(era,'wide');
  9372. case 'GGGGG':
  9373. return this._locale.getEraName(era,'narrow');
  9374. default:
  9375. throw new Yii.CException(Yii.t('yii','The pattern for era must be "G", "GG", "GGG", "GGGG" or "GGGGG".'));
  9376. }
  9377. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  9378. /**
  9379. * CJavaScriptMessageSource represents a message source that stores translated messages in JavaScript scripts.
  9380. *
  9381. * CJavaScriptMessageSource uses JavaScript files and arrays to keep message translations.
  9382. * <ul>
  9383. * <li>All translations are saved under the {@link basePath} directory.</li>
  9384. * <li>Translations in one language are kept as JavaScript files under an individual subdirectory
  9385. * whose name is the same as the language ID. Each JavaScript file contains messages
  9386. * belonging to the same category, and the file name is the same as the category name.</li>
  9387. * <li>Within a JavaScript file, an object of (source, translation) pairs is returned.
  9388. * For example:
  9389. * <pre>
  9390. * ({
  9391. * 'original message 1' : 'translated message 1',
  9392. * 'original message 2' : 'translated message 2'
  9393. * });
  9394. * </pre>
  9395. * </li>
  9396. * </ul>
  9397. * When {@link cachingDuration} is set as a positive number, message translations will be cached.
  9398. *
  9399. * Starting from version 1.0.10, messages for an extension class (e.g. a widget, a module) can be specially managed and used.
  9400. * In particular, if a message belongs to an extension whose class name is Xyz, then the message category
  9401. * can be specified in the format of 'Xyz.categoryName'. And the corresponding message file
  9402. * is assumed to be 'BasePath/messages/LanguageID/categoryName.php', where 'BasePath' refers to
  9403. * the directory that contains the extension class file. When using Yii.t() to translate an extension message,
  9404. * the category name should be set as 'Xyz.categoryName'.
  9405. *
  9406. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9407. * @version $Id: CJavaScriptMessageSource.php 2798 2011-01-01 19:29:03Z qiang.xue $
  9408. * @package system.i18n
  9409. * @since 1.0
  9410. * @author Charles Pick
  9411. * @class
  9412. * @extends Yii.CMessageSource
  9413. */
  9414. Yii.CJavaScriptMessageSource = function CJavaScriptMessageSource () {
  9415. };
  9416. Yii.CJavaScriptMessageSource.prototype = new Yii.CMessageSource(false);
  9417. Yii.CJavaScriptMessageSource.prototype.constructor = Yii.CJavaScriptMessageSource;
  9418. /**
  9419. * @const
  9420. */
  9421. Yii.CJavaScriptMessageSource.CACHE_KEY_PREFIX = 'Yii.CJavaScriptMessageSource.';
  9422. /**
  9423. * @var {Integer} the time in seconds that the messages can remain valid in cache.
  9424. * Defaults to 0, meaning the caching is disabled.
  9425. */
  9426. Yii.CJavaScriptMessageSource.prototype.cachingDuration = 0;
  9427. /**
  9428. * @var {String} the ID of the cache application component that is used to cache the messages.
  9429. * Defaults to 'cache' which refers to the primary cache application component.
  9430. * Set this property to false if you want to disable caching the messages.
  9431. * @since 1.0.10
  9432. */
  9433. Yii.CJavaScriptMessageSource.prototype.cacheID = 'cache';
  9434. /**
  9435. * @var {String} the base path for all translated messages. Defaults to null, meaning
  9436. * the "messages" subdirectory of the application directory (e.g. "protected/messages").
  9437. */
  9438. Yii.CJavaScriptMessageSource.prototype.basePath = null;
  9439. Yii.CJavaScriptMessageSource.prototype._files = {};
  9440. /**
  9441. * Initializes the application component.
  9442. * This method overrides the parent implementation by preprocessing
  9443. * the user request data.
  9444. */
  9445. Yii.CJavaScriptMessageSource.prototype.init = function () {
  9446. Yii.CMessageSource.prototype.init.call(this);
  9447. if(this.basePath===null) {
  9448. this.basePath=Yii.getPathOfAlias('application.messages');
  9449. }
  9450. };
  9451. /**
  9452. * Determines the message file name based on the given category and language.
  9453. * If the category name contains a dot, it will be split into the module class name and the category name.
  9454. * In this case, the message file will be assumed to be located within the 'messages' subdirectory of
  9455. * the directory containing the module class file.
  9456. * Otherwise, the message file is assumed to be under the {@link basePath}.
  9457. * @param {String} category category name
  9458. * @param {String} language language ID
  9459. * @returns {String} the message file path
  9460. * @since 1.0.10
  9461. */
  9462. Yii.CJavaScriptMessageSource.prototype.getMessageFile = function (category, language) {
  9463. var pos, moduleClass, moduleCategory, classVar;
  9464. if (this._files[category] === undefined) {
  9465. this._files[category] = {};
  9466. }
  9467. if(this._files[category][language] === undefined) {
  9468. if((pos=php.strpos(category,'.'))!==false) {
  9469. moduleClass=category.slice(0, pos);
  9470. moduleCategory=category.slice(pos+1);
  9471. this._files[category][language]=Yii.getPathOfAlias(moduleClass + ".messages." + moduleCategory) + ".js";
  9472. }
  9473. else {
  9474. this._files[category][language]=this.basePath+'/'+language+'/'+category+'.js';
  9475. }
  9476. }
  9477. return this._files[category][language];
  9478. };
  9479. /**
  9480. * Loads the message translation for the specified language and category.
  9481. * @param {String} category the message category
  9482. * @param {String} language the target language
  9483. * @returns {Object} the loaded messages
  9484. */
  9485. Yii.CJavaScriptMessageSource.prototype.loadMessages = function (category, language) {
  9486. var messageFile, cache, key, data, messages, dependency;
  9487. messageFile=this.getMessageFile(category,language);
  9488. if(this.cachingDuration>0 && this.cacheID!==false && (cache=Yii.app().getComponent(this.cacheID))!==null) {
  9489. key=this.Yii.CACHE_KEY_PREFIX + messageFile;
  9490. if((data=cache.get(key))!==false) {
  9491. if (!data instanceof "Object") {
  9492. data = Yii.CJSON.decode(data);
  9493. }
  9494. return data;
  9495. }
  9496. }
  9497. try {
  9498. data = Yii.include(messageFile, false);
  9499. if (data === false) {
  9500. return {};
  9501. }
  9502. if (this.cachingDuration > 0 && this.cacheID !== false && (cache=Yii.app().getComponent(this.cacheID))!==null) {
  9503. key=this.Yii.CACHE_KEY_PREFIX + messageFile;
  9504. cache.set(key, data, this.cachingDuration);
  9505. }
  9506. return data;
  9507. }
  9508. catch (e) {
  9509. return {};
  9510. }
  9511. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  9512. /**
  9513. * CLocale represents the data relevant to a locale.
  9514. *
  9515. * The data includes the number formatting information and date formatting information.
  9516. *
  9517. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9518. * @version $Id: CLocale.php 2844 2011-01-13 01:29:55Z alexander.makarow $
  9519. * @package system.i18n
  9520. * @since 1.0
  9521. * @author Charles Pick
  9522. * @class
  9523. * @extends Yii.CComponent
  9524. */
  9525. Yii.CLocale = function CLocale (id) {
  9526. if (id !== false) {
  9527. this.construct(id);
  9528. }
  9529. };
  9530. Yii.CLocale._locales = null;
  9531. Yii.CLocale.prototype = new Yii.CComponent();
  9532. Yii.CLocale.prototype.constructor = Yii.CLocale;
  9533. /**
  9534. * @var {String} the directory that contains the locale data. If this property is not set,
  9535. * the locale data will be loaded from 'framework/i18n/data'.
  9536. * @since 1.1.0
  9537. */
  9538. Yii.CLocale.prototype.dataPath = null;
  9539. Yii.CLocale.prototype._id = null;
  9540. Yii.CLocale.prototype._data = null;
  9541. Yii.CLocale.prototype._dateFormatter = null;
  9542. Yii.CLocale.prototype._numberFormatter = null;
  9543. /**
  9544. * Returns the instance of the specified locale.
  9545. * Since the constructor of CLocale is protected, you can only use
  9546. * this method to obtain an instance of the specified locale.
  9547. * @param {String} id the locale ID (e.g. en_US)
  9548. * @returns {Yii.CLocale} the locale instance
  9549. */
  9550. Yii.CLocale.getInstance = function (id) {
  9551. if(this._locales === null) {
  9552. this._locales = {};
  9553. }
  9554. if(this._locales[id] !== undefined) {
  9555. return this._locales[id];
  9556. }
  9557. else {
  9558. return (this._locales[id]=new Yii.CLocale(id));
  9559. }
  9560. };
  9561. /**
  9562. * @returns {Array} IDs of the locales which the framework can recognize
  9563. */
  9564. Yii.CLocale.prototype.getLocaleIDs = function () {
  9565. var locales;
  9566. locales=["aa","aa_dj","aa_er","aa_et","af","af_na","af_za","ak","ak_gh","am","am_et","ar","ar_ae","ar_bh","ar_dz","ar_eg","ar_iq","ar_jo","ar_kw","ar_lb","ar_ly","ar_ma","ar_om","ar_qa","ar_sa","ar_sd","ar_sy","ar_tn","ar_ye","as","as_in","asa","asa_tz","az","az_arab","az_arab_ir","az_az","az_cyrl","az_cyrl_az","az_ir","az_latn","az_latn_az","be","be_by","bem","bem_zm","bez","bez_tz","bg","bg_bg","bm","bm_ml","bn","bn_bd","bn_in","bo","bo_cn","bo_in","br","br_fr","brx","brx_in","bs","bs_ba","byn","byn_er","ca","ca_es","cch","cch_ng","cgg","cgg_ug","chr","chr_us","cs","cs_cz","cy","cy_gb","da","da_dk","dav","dav_ke","de","de_at","de_be","de_ch","de_de","de_li","de_lu","dv","dv_mv","dz","dz_bt","ebu","ebu_ke","ee","ee_gh","ee_tg","el","el_cy","el_gr","el_polyton","en","en_as","en_au","en_be","en_bw","en_bz","en_ca","en_dsrt","en_dsrt_us","en_gb","en_gu","en_hk","en_ie","en_in","en_jm","en_mh","en_mp","en_mt","en_mu","en_na","en_nz","en_ph","en_pk","en_sg","en_shaw","en_tt","en_um","en_us","en_us_posix","en_vi","en_za","en_zw","en_zz","eo","es","es_419","es_ar","es_bo","es_cl","es_co","es_cr","es_do","es_ec","es_es","es_gq","es_gt","es_hn","es_mx","es_ni","es_pa","es_pe","es_pr","es_py","es_sv","es_us","es_uy","es_ve","et","et_ee","eu","eu_es","fa","fa_af","fa_ir","ff","ff_sn","fi","fi_fi","fil","fil_ph","fo","fo_fo","fr","fr_be","fr_bf","fr_bi","fr_bj","fr_bl","fr_ca","fr_cd","fr_cf","fr_cg","fr_ch","fr_ci","fr_cm","fr_dj","fr_fr","fr_ga","fr_gn","fr_gp","fr_gq","fr_km","fr_lu","fr_mc","fr_mf","fr_mg","fr_ml","fr_mq","fr_ne","fr_re","fr_rw","fr_sn","fr_td","fr_tg","fur","fur_it","ga","ga_ie","gaa","gaa_gh","gez","gez_er","gez_et","gl","gl_es","gsw","gsw_ch","gu","gu_in","guz","guz_ke","gv","gv_gb","ha","ha_arab","ha_arab_ng","ha_arab_sd","ha_gh","ha_latn","ha_latn_gh","ha_latn_ne","ha_latn_ng","ha_ne","ha_ng","ha_sd","haw","haw_us","he","he_il","hi","hi_in","hr","hr_hr","hu","hu_hu","hy","hy_am","ia","id","id_id","ig","ig_ng","ii","ii_cn","in","is","is_is","it","it_ch","it_it","iu","iw","ja","ja_jp","jmc","jmc_tz","ka","ka_ge","kab","kab_dz","kaj","kaj_ng","kam","kam_ke","kcg","kcg_ng","kde","kde_tz","kea","kea_cv","kfo","kfo_ci","khq","khq_ml","ki","ki_ke","kk","kk_cyrl","kk_cyrl_kz","kk_kz","kl","kl_gl","kln","kln_ke","km","km_kh","kn","kn_in","ko","ko_kr","kok","kok_in","kpe","kpe_gn","kpe_lr","ksb","ksb_tz","ksh","ksh_de","ku","ku_arab","ku_arab_iq","ku_arab_ir","ku_iq","ku_ir","ku_latn","ku_latn_sy","ku_latn_tr","ku_sy","ku_tr","kw","kw_gb","ky","ky_kg","lag","lag_tz","lg","lg_ug","ln","ln_cd","ln_cg","lo","lo_la","lt","lt_lt","luo","luo_ke","luy","luy_ke","lv","lv_lv","mas","mas_ke","mas_tz","mer","mer_ke","mfe","mfe_mu","mg","mg_mg","mi","mi_nz","mk","mk_mk","ml","ml_in","mn","mn_cn","mn_cyrl","mn_cyrl_mn","mn_mn","mn_mong","mn_mong_cn","mo","mr","mr_in","ms","ms_bn","ms_my","mt","mt_mt","my","my_mm","naq","naq_na","nb","nb_no","nd","nd_zw","nds","nds_de","ne","ne_in","ne_np","nl","nl_be","nl_nl","nn","nn_no","no","nr","nr_za","nso","nso_za","ny","ny_mw","nyn","nyn_ug","oc","oc_fr","om","om_et","om_ke","or","or_in","pa","pa_arab","pa_arab_pk","pa_guru","pa_guru_in","pa_in","pa_pk","pl","pl_pl","ps","ps_af","pt","pt_ao","pt_br","pt_gw","pt_mz","pt_pt","rm","rm_ch","ro","ro_md","ro_ro","rof","rof_tz","root","ru","ru_md","ru_ru","ru_ua","rw","rw_rw","rwk","rwk_tz","sa","sa_in","saq","saq_ke","se","se_fi","se_no","seh","seh_mz","ses","ses_ml","sg","sg_cf","sh","sh_ba","sh_cs","sh_yu","shi","shi_latn","shi_latn_ma","shi_ma","shi_tfng","shi_tfng_ma","si","si_lk","sid","sid_et","sk","sk_sk","sl","sl_si","sn","sn_zw","so","so_dj","so_et","so_ke","so_so","sq","sq_al","sr","sr_ba","sr_cs","sr_cyrl","sr_cyrl_ba","sr_cyrl_cs","sr_cyrl_me","sr_cyrl_rs","sr_cyrl_yu","sr_latn","sr_latn_ba","sr_latn_cs","sr_latn_me","sr_latn_rs","sr_latn_yu","sr_me","sr_rs","sr_yu","ss","ss_sz","ss_za","ssy","ssy_er","st","st_ls","st_za","sv","sv_fi","sv_se","sw","sw_ke","sw_tz","syr","syr_sy","ta","ta_in","ta_lk","te","te_in","teo","teo_ke","teo_ug","tg","tg_cyrl","tg_cyrl_tj","tg_tj","th","th_th","ti","ti_er","ti_et","tig","tig_er","tl","tl_ph","tn","tn_za","to","to_to","tr","tr_tr","trv","trv_tw","ts","ts_za","tt","tt_ru","tzm","tzm_latn","tzm_latn_ma","tzm_ma","ug","ug_arab","ug_arab_cn","ug_cn","uk","uk_ua","ur","ur_in","ur_pk","uz","uz_af","uz_arab","uz_arab_af","uz_cyrl","uz_cyrl_uz","uz_latn","uz_latn_uz","uz_uz","ve","ve_za","vi","vi_vn","vun","vun_tz","wal","wal_et","wo","wo_latn","wo_latn_sn","wo_sn","xh","xh_za","xog","xog_ug","yo","yo_ng","zh","zh_cn","zh_hans","zh_hans_cn","zh_hans_hk","zh_hans_mo","zh_hans_sg","zh_hant","zh_hant_hk","zh_hant_mo","zh_hant_tw","zh_hk","zh_mo","zh_sg","zh_tw","zu","zu_za"];
  9567. return locales;
  9568. };
  9569. /**
  9570. * Constructor.
  9571. * Since the constructor is protected, please use {@link getInstance}
  9572. * to obtain an instance of the specified locale.
  9573. * @param {String} id the locale ID (e.g. en_US)
  9574. */
  9575. Yii.CLocale.prototype.construct = function (id) {
  9576. var dataPath, dataFile;
  9577. this._id=this.getCanonicalID(id);
  9578. dataPath=this.dataPath===null ? YII_PATH + '/i18n/data' : this.dataPath;
  9579. dataFile=dataPath+"/"+this._id+'.js';
  9580. this._data= Yii.include(dataFile,false);
  9581. };
  9582. /**
  9583. * Converts a locale ID to its canonical form.
  9584. * In canonical form, a locale ID consists of only underscores and lower-case letters.
  9585. * @param {String} id the locale ID to be converted
  9586. * @returns {String} the locale ID in canonical form
  9587. */
  9588. Yii.CLocale.prototype.getCanonicalID = function (id) {
  9589. return php.str_replace('-','_',id).toLowerCase();
  9590. };
  9591. /**
  9592. * @returns {String} the locale ID (in canonical form)
  9593. */
  9594. Yii.CLocale.prototype.getId = function () {
  9595. return this._id;
  9596. };
  9597. /**
  9598. * @returns {Yii.CNumberFormatter} the number formatter for this locale
  9599. */
  9600. Yii.CLocale.prototype.getNumberFormatter = function () {
  9601. if(this._numberFormatter===null) {
  9602. this._numberFormatter=new Yii.CNumberFormatter(this);
  9603. }
  9604. return this._numberFormatter;
  9605. };
  9606. /**
  9607. * @returns {Yii.CDateFormatter} the date formatter for this locale
  9608. */
  9609. Yii.CLocale.prototype.getDateFormatter = function () {
  9610. if(this._dateFormatter===null) {
  9611. this._dateFormatter=new Yii.CDateFormatter(this);
  9612. }
  9613. return this._dateFormatter;
  9614. };
  9615. /**
  9616. * @param {String} currency 3-letter ISO 4217 code. For example, the code "USD" represents the US Dollar and "EUR" represents the Euro currency.
  9617. * @returns {String} the localized currency symbol. Null if the symbol does not exist.
  9618. */
  9619. Yii.CLocale.prototype.getCurrencySymbol = function (currency) {
  9620. return this._data.currencySymbols[currency] !== undefined ? this._data.currencySymbols[currency] : null;
  9621. };
  9622. /**
  9623. * @param {String} name symbol name
  9624. * @returns {String} symbol
  9625. */
  9626. Yii.CLocale.prototype.getNumberSymbol = function (name) {
  9627. return this._data.numberSymbols[name] !== undefined ? this._data.numberSymbols[name] : null;
  9628. };
  9629. /**
  9630. * @returns {String} the decimal format
  9631. */
  9632. Yii.CLocale.prototype.getDecimalFormat = function () {
  9633. return this._data.decimalFormat;
  9634. };
  9635. /**
  9636. * @returns {String} the currency format
  9637. */
  9638. Yii.CLocale.prototype.getCurrencyFormat = function () {
  9639. return this._data.currencyFormat;
  9640. };
  9641. /**
  9642. * @returns {String} the percent format
  9643. */
  9644. Yii.CLocale.prototype.getPercentFormat = function () {
  9645. return this._data.percentFormat;
  9646. };
  9647. /**
  9648. * @returns {String} the scientific format
  9649. */
  9650. Yii.CLocale.prototype.getScientificFormat = function () {
  9651. return this._data.scientificFormat;
  9652. };
  9653. /**
  9654. * @param {Integer} month month (1-12)
  9655. * @param {String} width month name width. It can be 'wide', 'abbreviated' or 'narrow'.
  9656. * @param {Boolean} standAlone whether the month name should be returned in stand-alone format
  9657. * @returns {String} the month name
  9658. */
  9659. Yii.CLocale.prototype.getMonthName = function (month, width, standAlone) {
  9660. if (width === undefined) {
  9661. width = 'wide';
  9662. }
  9663. if (standAlone === undefined) {
  9664. standAlone = false;
  9665. }
  9666. if(standAlone) {
  9667. return this._data.monthNamesSA[width][month] !== undefined ? this._data.monthNamesSA[width][month] : this._data.monthNames[width][month];
  9668. }
  9669. else {
  9670. return this._data.monthNames[width][month] !== undefined ? this._data.monthNames[width][month] : this._data.monthNamesSA[width][month];
  9671. }
  9672. };
  9673. /**
  9674. * Returns the month names in the specified width.
  9675. * @param {String} width month name width. It can be 'wide', 'abbreviated' or 'narrow'.
  9676. * @param {Boolean} standAlone whether the month names should be returned in stand-alone format
  9677. * @returns {Array} month names indexed by month values (1-12)
  9678. * @since 1.0.9
  9679. */
  9680. Yii.CLocale.prototype.getMonthNames = function (width, standAlone) {
  9681. if (width === undefined) {
  9682. width = 'wide';
  9683. }
  9684. if (standAlone === undefined) {
  9685. standAlone = false;
  9686. }
  9687. if(standAlone) {
  9688. return this._data.monthNamesSA[width] !== undefined ? this._data.monthNamesSA[width] : this._data.monthNames[width];
  9689. }
  9690. else {
  9691. return this._data.monthNames[width] !== undefined ? this._data.monthNames[width] : this._data.monthNamesSA[width];
  9692. }
  9693. };
  9694. /**
  9695. * @param {Integer} day weekday (0-6, 0 means Sunday)
  9696. * @param {String} width weekday name width. It can be 'wide', 'abbreviated' or 'narrow'.
  9697. * @param {Boolean} standAlone whether the week day name should be returned in stand-alone format
  9698. * @returns {String} the weekday name
  9699. */
  9700. Yii.CLocale.prototype.getWeekDayName = function (day, width, standAlone) {
  9701. if (width === undefined) {
  9702. width = 'wide';
  9703. }
  9704. if (standAlone === undefined) {
  9705. standAlone = false;
  9706. }
  9707. if(standAlone) {
  9708. return this._data.weekDayNamesSA[width][day] !== undefined ? this._data.weekDayNamesSA[width][day] : this._data.weekDayNames[width][day];
  9709. }
  9710. else {
  9711. return this._data.weekDayNames[width][day] !== undefined ? this._data.weekDayNames[width][day] : this._data.weekDayNamesSA[width][day];
  9712. }
  9713. };
  9714. /**
  9715. * Returns the week day names in the specified width.
  9716. * @param {String} width weekday name width. It can be 'wide', 'abbreviated' or 'narrow'.
  9717. * @param {Boolean} standAlone whether the week day name should be returned in stand-alone format
  9718. * @returns {Array} the weekday names indexed by weekday values (0-6, 0 means Sunday, 1 Monday, etc.)
  9719. * @since 1.0.9
  9720. */
  9721. Yii.CLocale.prototype.getWeekDayNames = function (width, standAlone) {
  9722. if (width === undefined) {
  9723. width = 'wide';
  9724. }
  9725. if (standAlone === undefined) {
  9726. standAlone = false;
  9727. }
  9728. if(standAlone) {
  9729. return this._data.weekDayNamesSA[width] !== undefined ? this._data.weekDayNamesSA[width] : this._data.weekDayNames[width];
  9730. }
  9731. else {
  9732. return this._data.weekDayNames[width] !== undefined ? this._data.weekDayNames[width] : this._data.weekDayNamesSA[width];
  9733. }
  9734. };
  9735. /**
  9736. * @param {Integer} era era (0,1)
  9737. * @param {String} width era name width. It can be 'wide', 'abbreviated' or 'narrow'.
  9738. * @returns {String} the era name
  9739. */
  9740. Yii.CLocale.prototype.getEraName = function (era, width) {
  9741. if (width === undefined) {
  9742. width = 'wide';
  9743. }
  9744. return this._data.eraNames[width][era];
  9745. };
  9746. /**
  9747. * @returns {String} the AM name
  9748. */
  9749. Yii.CLocale.prototype.getAMName = function () {
  9750. return this._data.amName;
  9751. };
  9752. /**
  9753. * @returns {String} the PM name
  9754. */
  9755. Yii.CLocale.prototype.getPMName = function () {
  9756. return this._data.pmName;
  9757. };
  9758. /**
  9759. * @param {String} width date format width. It can be 'full', 'long', 'medium' or 'short'.
  9760. * @returns {String} date format
  9761. */
  9762. Yii.CLocale.prototype.getDateFormat = function (width) {
  9763. if (width === undefined) {
  9764. width = 'medium';
  9765. }
  9766. return this._data.dateFormats[width];
  9767. };
  9768. /**
  9769. * @param {String} width time format width. It can be 'full', 'long', 'medium' or 'short'.
  9770. * @returns {String} date format
  9771. */
  9772. Yii.CLocale.prototype.getTimeFormat = function (width) {
  9773. if (width === undefined) {
  9774. width = 'medium';
  9775. }
  9776. return this._data.timeFormats[width];
  9777. };
  9778. /**
  9779. * @returns {String} datetime format, i.e., the order of date and time.
  9780. */
  9781. Yii.CLocale.prototype.getDateTimeFormat = function () {
  9782. return this._data.dateTimeFormat;
  9783. };
  9784. /**
  9785. * @returns {String} the character orientation, which is either 'ltr' (left-to-right) or 'rtl' (right-to-left)
  9786. * @since 1.1.2
  9787. */
  9788. Yii.CLocale.prototype.getOrientation = function () {
  9789. return this._data.orientation !== undefined ? this._data.orientation : 'ltr';
  9790. };
  9791. /**
  9792. * @returns {Array} plural forms expressions
  9793. */
  9794. Yii.CLocale.prototype.getPluralRules = function () {
  9795. return this._data.pluralRules !== undefined ? this._data.pluralRules : [];
  9796. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  9797. /**
  9798. * CMissingTranslationEvent represents the parameter for the {@link CMessageSource::onMissingTranslation onMissingTranslation} event.
  9799. *
  9800. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9801. * @version $Id: CMessageSource.php 2798 2011-01-01 19:29:03Z qiang.xue $
  9802. * @package system.i18n
  9803. * @since 1.0
  9804. * @author Charles Pick
  9805. * @class
  9806. * @extends Yii.CEvent
  9807. */
  9808. Yii.CMissingTranslationEvent = function CMissingTranslationEvent (sender, params) {
  9809. if (sender !== false) {
  9810. this.construct(sender, params);
  9811. }
  9812. };
  9813. Yii.CMissingTranslationEvent.prototype = new Yii.CEvent(false);
  9814. Yii.CMissingTranslationEvent.prototype.constructor = Yii.CMissingTranslationEvent;
  9815. /**
  9816. * @var {String} the message to be translated
  9817. */
  9818. Yii.CMissingTranslationEvent.prototype.message = null;
  9819. /**
  9820. * @var {String} the category that the message belongs to
  9821. */
  9822. Yii.CMissingTranslationEvent.prototype.category = null;
  9823. /**
  9824. * @var {String} the ID of the language that the message is to be translated to
  9825. */
  9826. Yii.CMissingTranslationEvent.prototype.language = null;
  9827. /**
  9828. * Constructor.
  9829. * @param {Mixed} sender sender of this event
  9830. * @param {String} category the category that the message belongs to
  9831. * @param {String} message the message to be translated
  9832. * @param {String} language the ID of the language that the message is to be translated to
  9833. */
  9834. Yii.CMissingTranslationEvent.prototype.construct = function (sender, category, message, language) {
  9835. Yii.CEvent.prototype.construct.call(this, sender);
  9836. this.message=message;
  9837. this.category=category;
  9838. this.language=language;
  9839. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  9840. /**
  9841. * CLogFilter preprocesses the logged messages before they are handled by a log route.
  9842. *
  9843. * CLogFilter is meant to be used by a log route to preprocess the logged messages
  9844. * before they are handled by the route. The default implementation of CLogFilter
  9845. * prepends additional context information to the logged messages. In particular,
  9846. * by setting {@link logVars}, predefined PHP variables such as
  9847. * $_SERVER, $_POST, etc. can be saved as a log message, which may help identify/debug
  9848. * issues encountered.
  9849. *
  9850. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9851. * @version $Id: CLogFilter.php 2799 2011-01-01 19:31:13Z qiang.xue $
  9852. * @package system.logging
  9853. * @since 1.0.6
  9854. * @author Charles Pick
  9855. * @class
  9856. * @extends Yii.CComponent
  9857. */
  9858. Yii.CLogFilter = function CLogFilter () {
  9859. };
  9860. Yii.CLogFilter.prototype = new Yii.CComponent();
  9861. Yii.CLogFilter.prototype.constructor = Yii.CLogFilter;
  9862. /**
  9863. * @var {Boolean} whether to prefix each log message with the current user session ID.
  9864. * Defaults to false.
  9865. */
  9866. Yii.CLogFilter.prototype.prefixSession = false;
  9867. /**
  9868. * @var {Boolean} whether to prefix each log message with the current user
  9869. * {@link CWebUser::name name} and {@link CWebUser::id ID}. Defaults to false.
  9870. */
  9871. Yii.CLogFilter.prototype.prefixUser = false;
  9872. /**
  9873. * @var {Boolean} whether to log the current user name and ID. Defaults to true.
  9874. */
  9875. Yii.CLogFilter.prototype.logUser = true;
  9876. /**
  9877. * @var {Array} list of the predefined variables that should be logged.
  9878. * Note that a variable must be globally accessible. Otherwise it won't be logged.
  9879. */
  9880. Yii.CLogFilter.prototype.logVars = [];
  9881. /**
  9882. * Filters the given log messages.
  9883. * This is the main method of CLogFilter. It processes the log messages
  9884. * by adding context information, etc.
  9885. * @param {Array} logs the log messages
  9886. */
  9887. Yii.CLogFilter.prototype.filter = function (logs) {
  9888. var message;
  9889. if (!php.empty(logs)) {
  9890. if((message=this.getContext())!=='') {
  9891. php.array_unshift(logs,[message,Yii.CLogger.LEVEL_INFO,'application',YII_BEGIN_TIME]);
  9892. }
  9893. this.format(logs);
  9894. }
  9895. return logs;
  9896. };
  9897. /**
  9898. * Formats the log messages.
  9899. * The default implementation will prefix each message with session ID
  9900. * if {@link prefixSession} is set true. It may also prefix each message
  9901. * with the current user's name and ID if {@link prefixUser} is true.
  9902. * @param {Array} logs the log messages
  9903. */
  9904. Yii.CLogFilter.prototype.format = function (logs) {
  9905. var prefix, id, user, i, log;
  9906. prefix='';
  9907. if(this.prefixSession && (id=document.cookie.match(/PHPSESSID=[^;]+/))!==null) {
  9908. prefix+="[" + id + "]";
  9909. }
  9910. if(this.prefixUser && (user=Yii.app().getComponent('user',false))!==null) {
  9911. prefix+='['+user.getName()+']['+user.getId()+']';
  9912. }
  9913. if(prefix!=='') {
  9914. for (i in logs) {
  9915. if (logs.hasOwnProperty(i)) {
  9916. logs[i][0]=prefix+' '+logs[i][0];
  9917. }
  9918. }
  9919. }
  9920. };
  9921. /**
  9922. * Generates the context information to be logged.
  9923. * The default implementation will dump user information, system variables, etc.
  9924. * @returns {String} the context information. If an empty string, it means no context information.
  9925. */
  9926. Yii.CLogFilter.prototype.getContext = function () {
  9927. var context, user, i, name;
  9928. context=[];
  9929. if(this.logUser && (user=Yii.app().getComponent('user',false))!==null) {
  9930. context.push('User: '+user.getName()+' (ID: '+user.getId()+')');
  9931. }
  9932. for (i in this.logVars) {
  9933. if (this.logVars.hasOwnProperty(i)) {
  9934. name = this.logVars[i];
  9935. if(window[name] !== undefined) {
  9936. context.push(name + " = " + window[name]);
  9937. }
  9938. }
  9939. }
  9940. return context.join("\n\n");
  9941. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  9942. /**
  9943. * CLogRouter manages log routes that record log messages in different media.
  9944. *
  9945. * For example, a file log route {@link CFileLogRoute} records log messages
  9946. * in log files. An email log route {@link CEmailLogRoute} sends log messages
  9947. * to specific email addresses. See {@link CLogRoute} for more details about
  9948. * different log routes.
  9949. *
  9950. * Log routes may be configured in application configuration like following:
  9951. * <pre>
  9952. * {
  9953. * 'preload':{'log'}, // preload log component when app starts
  9954. * 'components':{
  9955. * 'log':{
  9956. * 'class':'CLogRouter',
  9957. * 'routes':{
  9958. * {
  9959. * 'class':'CFileLogRoute',
  9960. * 'levels':'trace, info',
  9961. * 'categories':'system.*',
  9962. * },
  9963. * {
  9964. * 'class':'CEmailLogRoute',
  9965. * 'levels':'error, warning',
  9966. * 'email':'admin@example.com',
  9967. * },
  9968. * ),
  9969. * ),
  9970. * ),
  9971. * }
  9972. * </pre>
  9973. *
  9974. * You can specify multiple routes with different filtering conditions and different
  9975. * targets, even if the routes are of the same type.
  9976. *
  9977. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  9978. * @version $Id: CLogRouter.php 3066 2011-03-13 14:22:55Z qiang.xue $
  9979. * @package system.logging
  9980. * @since 1.0
  9981. * @author Charles Pick
  9982. * @class
  9983. * @extends Yii.CApplicationComponent
  9984. */
  9985. Yii.CLogRouter = function CLogRouter () {
  9986. };
  9987. Yii.CLogRouter.prototype = new Yii.CApplicationComponent();
  9988. Yii.CLogRouter.prototype.constructor = Yii.CLogRouter;
  9989. Yii.CLogRouter.prototype._routes = [];
  9990. /**
  9991. * Initializes this application component.
  9992. * This method is required by the IApplicationComponent interface.
  9993. */
  9994. Yii.CLogRouter.prototype.init = function () {
  9995. var route, name;
  9996. Yii.CApplicationComponent.prototype.init();
  9997. for (name in this._routes) {
  9998. if (this._routes.hasOwnProperty(name)) {
  9999. route = this._routes[name];
  10000. route=Yii.createComponent(route);
  10001. route.init();
  10002. this._routes[name]=route;
  10003. }
  10004. }
  10005. Yii.getLogger().attachEventHandler('onFlush',[this,'collectLogs']);
  10006. Yii.app().attachEventHandler('onEndRequest',[this,'processLogs']);
  10007. };
  10008. /**
  10009. * @returns {Array} the currently initialized routes
  10010. */
  10011. Yii.CLogRouter.prototype.getRoutes = function () {
  10012. return new Yii.CMap(this._routes);
  10013. };
  10014. /**
  10015. * @param {Array} config list of route configurations. Each array element represents
  10016. * the configuration for a single route and has the following array structure:
  10017. * <ul>
  10018. * <li>class: specifies the class name or alias for the route class.</li>
  10019. * <li>name-value pairs: configure the initial property values of the route.</li>
  10020. * </ul>
  10021. */
  10022. Yii.CLogRouter.prototype.setRoutes = function (config) {
  10023. var name, route;
  10024. for (name in config) {
  10025. if (config.hasOwnProperty(name)) {
  10026. route = config[name];
  10027. this._routes[name]=route;
  10028. }
  10029. }
  10030. };
  10031. /**
  10032. * Collects log messages from a logger.
  10033. * This method is an event handler to the {@link CLogger::onFlush} event.
  10034. * @param {Yii.CEvent} event event parameter
  10035. */
  10036. Yii.CLogRouter.prototype.collectLogs = function (event) {
  10037. var logger, dumpLogs, i, route;
  10038. logger=Yii.getLogger();
  10039. dumpLogs=event.params.dumpLogs !== undefined && event.params.dumpLogs;
  10040. for (i in this._routes) {
  10041. if (this._routes.hasOwnProperty(i)) {
  10042. route = this._routes[i];
  10043. if(route.enabled) {
  10044. route.collectLogs(logger,dumpLogs);
  10045. }
  10046. }
  10047. }
  10048. };
  10049. /**
  10050. * Collects and processes log messages from a logger.
  10051. * This method is an event handler to the {@link CApplication::onEndRequest} event.
  10052. * @param {Yii.CEvent} event event parameter
  10053. * @since 1.1.0
  10054. */
  10055. Yii.CLogRouter.prototype.processLogs = function (event) {
  10056. var logger, i, route;
  10057. logger=Yii.getLogger();
  10058. for (i in this._routes) {
  10059. if (this._routes.hasOwnProperty(i)) {
  10060. route = this._routes[i];
  10061. if(route.enabled) {
  10062. route.collectLogs(logger,true);
  10063. }
  10064. }
  10065. }
  10066. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  10067. /**
  10068. * CLogger records log messages in memory.
  10069. *
  10070. * CLogger implements the methods to retrieve the messages with
  10071. * various filter conditions, including log levels and log categories.
  10072. *
  10073. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  10074. * @version $Id: CLogger.php 3137 2011-03-28 11:08:06Z mdomba $
  10075. * @package system.logging
  10076. * @since 1.0
  10077. * @author Charles Pick
  10078. * @class
  10079. * @extends Yii.CComponent
  10080. */
  10081. Yii.CLogger = function() {
  10082. };
  10083. Yii.CLogger.prototype = new Yii.CComponent();
  10084. Yii.CLogger.prototype.constructor = Yii.CLogger;
  10085. /**
  10086. * @const
  10087. */
  10088. Yii.CLogger.prototype.LEVEL_TRACE = 'trace';
  10089. /**
  10090. * @const
  10091. */
  10092. Yii.CLogger.prototype.LEVEL_WARNING = 'warning';
  10093. /**
  10094. * @const
  10095. */
  10096. Yii.CLogger.prototype.LEVEL_ERROR = 'error';
  10097. /**
  10098. * @const
  10099. */
  10100. Yii.CLogger.prototype.LEVEL_INFO = 'info';
  10101. /**
  10102. * @const
  10103. */
  10104. Yii.CLogger.prototype.LEVEL_PROFILE = 'profile';
  10105. /**
  10106. * @var {Integer} how many messages should be logged before they are flushed to destinations.
  10107. * Defaults to 10,000, meaning for every 10,000 messages, the {@link flush} method will be
  10108. * automatically invoked once. If this is 0, it means messages will never be flushed automatically.
  10109. * @since 1.1.0
  10110. */
  10111. Yii.CLogger.prototype.autoFlush = 10000;
  10112. /**
  10113. * @var {Array} log messages
  10114. */
  10115. Yii.CLogger.prototype._logs = [];
  10116. /**
  10117. * @var {Integer} number of log messages
  10118. */
  10119. Yii.CLogger.prototype._logCount = 0;
  10120. /**
  10121. * @var {Array} log levels for filtering (used when filtering)
  10122. */
  10123. Yii.CLogger.prototype._levels = null;
  10124. /**
  10125. * @var {Array} log categories for filtering (used when filtering)
  10126. */
  10127. Yii.CLogger.prototype._categories = null;
  10128. /**
  10129. * @var {Array} the profiling results (category, token => time in seconds)
  10130. * @since 1.0.6
  10131. */
  10132. Yii.CLogger.prototype._timings = null;
  10133. /**
  10134. * Logs a message.
  10135. * Messages logged by this method may be retrieved back via {@link getLogs}.
  10136. * @param {String} message message to be logged
  10137. * @param {String} level level of the message (e.g. 'Trace', 'Warning', 'Error'). It is case-insensitive.
  10138. * @param {String} category category of the message (e.g. 'system.web'). It is case-insensitive.
  10139. * @see getLogs
  10140. */
  10141. Yii.CLogger.prototype.log = function (message, level, category) {
  10142. if (level === undefined) {
  10143. level = 'info';
  10144. }
  10145. if (category === undefined) {
  10146. category = 'application';
  10147. }
  10148. this._logs.push([message,level,category,php.microtime(true)]);
  10149. this._logCount++;
  10150. if(this.autoFlush>0 && this._logCount>=this.autoFlush) {
  10151. this.flush();
  10152. }
  10153. };
  10154. /**
  10155. * Retrieves log messages.
  10156. *
  10157. * Messages may be filtered by log levels and/or categories.
  10158. * A level filter is specified by a list of levels separated by comma or space
  10159. * (e.g. 'trace, error'). A category filter is similar to level filter
  10160. * (e.g. 'system, system.web'). A difference is that in category filter
  10161. * you can use pattern like 'system.*' to indicate all categories starting
  10162. * with 'system'.
  10163. *
  10164. * If you do not specify level filter, it will bring back logs at all levels.
  10165. * The same applies to category filter.
  10166. *
  10167. * Level filter and category filter are combinational, i.e., only messages
  10168. * satisfying both filter conditions will be returned.
  10169. *
  10170. * @param {String} levels level filter
  10171. * @param {String} categories category filter
  10172. * @returns {Array} list of messages. Each array elements represents one message
  10173. * with the following structure:
  10174. * array(
  10175. * [0] => message (string)
  10176. * [1] => level (string)
  10177. * [2] => category (string)
  10178. * [3] => timestamp (float, obtained by microtime(true));
  10179. */
  10180. Yii.CLogger.prototype.getLogs = function (levels, categories) {
  10181. var ret, self;
  10182. if (levels === undefined) {
  10183. levels = '';
  10184. this._levels = [];
  10185. }
  10186. else {
  10187. this._levels=levels.toLowerCase().split(/[\s,]+/);
  10188. }
  10189. if (categories === undefined) {
  10190. categories = '';
  10191. this._categories = [];
  10192. }
  10193. else {
  10194. this._categories=categories.toLowerCase().split(/[\s,]+/);
  10195. }
  10196. self = this;
  10197. if(php.empty(levels) && php.empty(categories)) {
  10198. return this._logs;
  10199. }
  10200. else if(php.empty(levels)) {
  10201. return Yii.filter(this._logs,function(value, k, arr) {
  10202. var matched = false, cat = value[2].toLowerCase(), c;
  10203. Yii.forEach(self._categories, function(i, category) {
  10204. if(cat===category || ((c=php.rtrim(category,'.*'))!==category && php.strpos(cat,c)===0)) {
  10205. matched = true;
  10206. return false;
  10207. }
  10208. });
  10209. return matched ? value : false;
  10210. });
  10211. }
  10212. else if(php.empty(categories)) {
  10213. return Yii.filter(this._logs,function(value, k, arr) {
  10214. var matched = false, matchLevel = value[1].toLowerCase();
  10215. Yii.forEach(self._levels, function(i, level) {
  10216. if (level === matchLevel) {
  10217. matched = true;
  10218. return false;
  10219. }
  10220. });
  10221. return matched ? value : false;
  10222. });
  10223. }
  10224. else {
  10225. return Yii.filter(Yii.filter(this._logs,function(value, k, arr) {
  10226. var matched = false, cat = value[2].toLowerCase(), c;
  10227. Yii.forEach(self._categories, function(i, category) {
  10228. if(cat===category || ((c=php.rtrim(category,'.*'))!==category && php.strpos(cat,c)===0)) {
  10229. matched = true;
  10230. return false;
  10231. }
  10232. });
  10233. return matched ? value : false;
  10234. }), function(value, k, arr) {
  10235. var matched = false, matchLevel = value[1].toLowerCase();
  10236. Yii.forEach(self._levels, function(i, level) {
  10237. if (level === matchLevel) {
  10238. matched = true;
  10239. return false;
  10240. }
  10241. });
  10242. return matched ? value : false;
  10243. });
  10244. }
  10245. };
  10246. /**
  10247. * Filter function used by {@link getLogs}
  10248. * @param {Array} value element to be filtered
  10249. * @returns {Array} valid log, false if not.
  10250. */
  10251. Yii.CLogger.prototype.filterByCategory = function (value) {
  10252. var i, cat, category, c;
  10253. for (i in this._categories) {
  10254. if (this._categories.hasOwnProperty(i)) {
  10255. category = this._categories[i];
  10256. cat=value[2].toLowerCase();
  10257. if(cat===category || ((c=php.rtrim(category,'.*'))!==category && php.strpos(cat,c)===0)) {
  10258. return value;
  10259. }
  10260. }
  10261. }
  10262. return false;
  10263. };
  10264. /**
  10265. * Filter function used by {@link getLogs}
  10266. * @param {Array} value element to be filtered
  10267. * @returns {Array} valid log, false if not.
  10268. */
  10269. Yii.CLogger.prototype.filterByLevel = function (value) {
  10270. var matched = false, matchLevel = value[1].toLowerCase();
  10271. Yii.forEach(this._levels, function(i, level) {
  10272. console.log(level);
  10273. if (level === matchLevel) {
  10274. matched = true;
  10275. return false;
  10276. }
  10277. });
  10278. return matched ? value : false;
  10279. };
  10280. /**
  10281. * Returns the total time for serving the current request.
  10282. * This method calculates the difference between now and the timestamp
  10283. * defined by constant YII_BEGIN_TIME.
  10284. * To estimate the execution time more accurately, the constant should
  10285. * be defined as early as possible (best at the beginning of the entry script.)
  10286. * @returns {Float} the total time for serving the current request.
  10287. */
  10288. Yii.CLogger.prototype.getExecutionTime = function () {
  10289. return php.microtime(true)-YII_BEGIN_TIME;
  10290. };
  10291. /**
  10292. * Not Available in JavaScript, always returns 0
  10293. * @returns {Integer} memory usage of the application (in bytes).
  10294. */
  10295. Yii.CLogger.prototype.getMemoryUsage = function () {
  10296. return 0;
  10297. };
  10298. /**
  10299. * Returns the profiling results.
  10300. * The results may be filtered by token and/or category.
  10301. * If no filter is specified, the returned results would be an array with each element
  10302. * being array($token,$category,$time).
  10303. * If a filter is specified, the results would be an array of timings.
  10304. * @param {String} token token filter. Defaults to null, meaning not filtered by token.
  10305. * @param {String} category category filter. Defaults to null, meaning not filtered by category.
  10306. * @param {Boolean} refresh whether to refresh the internal timing calculations. If false,
  10307. * only the first time calling this method will the timings be calculated internally.
  10308. * @returns {Array} the profiling results.
  10309. * @since 1.0.6
  10310. */
  10311. Yii.CLogger.prototype.getProfilingResults = function (token, category, refresh) {
  10312. var results, i, timing;
  10313. if (token === undefined) {
  10314. token = null;
  10315. }
  10316. if (category === undefined) {
  10317. category = null;
  10318. }
  10319. if (refresh === undefined) {
  10320. refresh = false;
  10321. }
  10322. if(this._timings===null || refresh) {
  10323. this.calculateTimings();
  10324. }
  10325. if(token===null && category===null) {
  10326. return this._timings;
  10327. }
  10328. results=[];
  10329. for (i in this._timings) {
  10330. if (this._timings.hasOwnProperty(i)) {
  10331. timing = this._timings[i];
  10332. if((category===null || timing[1]===category) && (token===null || timing[0]===token)) {
  10333. results.push(timing[2]);
  10334. }
  10335. }
  10336. }
  10337. return results;
  10338. };
  10339. Yii.CLogger.prototype.calculateTimings = function () {
  10340. var stack, i, log, message, level, category, timestamp, token, last, delta, now;
  10341. this._timings=[];
  10342. stack=[];
  10343. for (i in this._logs) {
  10344. if (this._logs.hasOwnProperty(i)) {
  10345. log = this._logs[i];
  10346. if(log[1]!==Yii.CLogger.prototype.LEVEL_PROFILE) {
  10347. continue;
  10348. }
  10349. message = log[0];
  10350. level = log[1];
  10351. category = log[2];
  10352. timestamp = log[3];
  10353. if(!php.strncasecmp(message,'begin:',6)) {
  10354. log[0]=message.slice(6);
  10355. stack.push(log);
  10356. }
  10357. else if(!php.strncasecmp(message,'end:',4)) {
  10358. token=message.slice(4);
  10359. if((last=php.array_pop(stack))!==null && last[0]===token) {
  10360. delta=log[3]-last[3];
  10361. this._timings.push([message,category,delta]);
  10362. }
  10363. else {
  10364. throw new Yii.CException(Yii.t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
  10365. {'{token}':token}));
  10366. }
  10367. }
  10368. }
  10369. }
  10370. now=php.microtime(true);
  10371. while((last=php.array_pop(stack))!==null) {
  10372. delta=now-last[3];
  10373. this._timings.push([last[0],last[2],delta]);
  10374. }
  10375. };
  10376. /**
  10377. * Removes all recorded messages from the memory.
  10378. * This method will raise an {@link onFlush} event.
  10379. * The attached event handlers can process the log messages before they are removed.
  10380. * @param {Boolean} dumpLogs whether to process the logs
  10381. * @since 1.1.0
  10382. */
  10383. Yii.CLogger.prototype.flush = function (dumpLogs) {
  10384. if (dumpLogs === undefined) {
  10385. dumpLogs = false;
  10386. }
  10387. this.onFlush(new Yii.CEvent(this, {'dumpLogs':dumpLogs}));
  10388. this._logs=[];
  10389. this._logCount=0;
  10390. };
  10391. /**
  10392. * Raises an <code>onFlush</code> event.
  10393. * @param {Yii.CEvent} event the event parameter
  10394. * @since 1.1.0
  10395. */
  10396. Yii.CLogger.prototype.onFlush = function (event) {
  10397. this.raiseEvent('onFlush', event);
  10398. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  10399. /**
  10400. * CProfileLogRoute displays the profiling results in Web page.
  10401. *
  10402. * The profiling is done by calling {@link YiiBase::beginProfile()} and {@link YiiBase::endProfile()},
  10403. * which marks the begin and end of a code block.
  10404. *
  10405. * CProfileLogRoute supports two types of report by setting the {@link setReport report} property:
  10406. * <ul>
  10407. * <li>summary: list the execution time of every marked code block</li>
  10408. * <li>callstack: list the mark code blocks in a hierarchical view reflecting their calling sequence.</li>
  10409. * </ul>
  10410. *
  10411. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  10412. * @version $Id: CProfileLogRoute.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  10413. * @package system.logging
  10414. * @since 1.0
  10415. * @author Charles Pick
  10416. * @class
  10417. * @extends Yii.CWebLogRoute
  10418. */
  10419. Yii.CProfileLogRoute = function CProfileLogRoute () {
  10420. };
  10421. Yii.CProfileLogRoute.prototype = new Yii.CWebLogRoute();
  10422. Yii.CProfileLogRoute.prototype.constructor = Yii.CProfileLogRoute;
  10423. /**
  10424. * @var {Boolean} whether to aggregate results according to profiling tokens.
  10425. * If false, the results will be aggregated by categories.
  10426. * Defaults to true. Note that this property only affects the summary report
  10427. * that is enabled when {@link report} is 'summary'.
  10428. * @since 1.0.6
  10429. */
  10430. Yii.CProfileLogRoute.prototype.groupByToken = true;
  10431. /**
  10432. * @var {String} type of profiling report to display
  10433. */
  10434. Yii.CProfileLogRoute.prototype._report = 'summary';
  10435. /**
  10436. * Initializes the route.
  10437. * This method is invoked after the route is created by the route manager.
  10438. */
  10439. Yii.CProfileLogRoute.prototype.init = function () {
  10440. this.levels=Yii.CLogger.prototype.LEVEL_PROFILE;
  10441. };
  10442. /**
  10443. * @returns {String} the type of the profiling report to display. Defaults to 'summary'.
  10444. */
  10445. Yii.CProfileLogRoute.prototype.getReport = function () {
  10446. return this._report;
  10447. };
  10448. /**
  10449. * @param {String} value the type of the profiling report to display. Valid values include 'summary' and 'callstack'.
  10450. */
  10451. Yii.CProfileLogRoute.prototype.setReport = function (value) {
  10452. if(value==='summary' || value==='callstack') {
  10453. this._report=value;
  10454. }
  10455. else {
  10456. throw new Yii.CException(Yii.t('yii','CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".',
  10457. {'{report}':value}));
  10458. }
  10459. };
  10460. /**
  10461. * Displays the log messages.
  10462. * @param {Array} logs list of log messages
  10463. */
  10464. Yii.CProfileLogRoute.prototype.processLogs = function (logs) {
  10465. var app;
  10466. app=Yii.app();
  10467. if(!(app instanceof Yii.CWebApplication) || app.getRequest().getIsAjaxRequest()) {
  10468. return;
  10469. }
  10470. if(this.getReport()==='summary') {
  10471. this.displaySummary(logs);
  10472. }
  10473. else {
  10474. this.displayCallstack(logs);
  10475. }
  10476. };
  10477. /**
  10478. * Displays the callstack of the profiling procedures for display.
  10479. * @param {Array} logs list of logs
  10480. */
  10481. Yii.CProfileLogRoute.prototype.displayCallstack = function (logs) {
  10482. var stack, results, n, i, log, message, token, last, delta, now;
  10483. stack=[];
  10484. results={};
  10485. n=0;
  10486. for (i in logs) {
  10487. if (logs.hasOwnProperty(i)) {
  10488. log = logs[i];
  10489. if(log[1]!==Yii.CLogger.prototype.LEVEL_PROFILE) {
  10490. continue;
  10491. }
  10492. message=log[0];
  10493. if(!php.strncasecmp(message,'begin:',6)){
  10494. log[0]=message.slice(6);
  10495. log[4]=n;
  10496. stack.push(log);
  10497. n++;
  10498. }
  10499. else if(!php.strncasecmp(message,'end:',4)) {
  10500. token=message.slice(4);
  10501. if((last=php.array_pop(stack))!==null && last[0]===token) {
  10502. delta=log[3]-last[3];
  10503. results[last[4]]=[token,delta,php.count(stack)];
  10504. }
  10505. else {
  10506. throw new Yii.CException(Yii.t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
  10507. {'{token}':token}));
  10508. }
  10509. }
  10510. }
  10511. }
  10512. // remaining entries should be closed here
  10513. now=php.microtime(true);
  10514. while((last=php.array_pop(stack))!==null) {
  10515. results[last[4]]=[last[0],now-last[3],php.count(stack)];
  10516. }
  10517. php.ksort(results);
  10518. this.render('profile-callstack',results);
  10519. };
  10520. /**
  10521. * Displays the summary report of the profiling result.
  10522. * @param {Array} logs list of logs
  10523. */
  10524. Yii.CProfileLogRoute.prototype.displaySummary = function (logs) {
  10525. var stack, i, log, message, token, last, delta, results = {}, now, entries, func, data;
  10526. stack=[];
  10527. for (i in logs) {
  10528. if (logs.hasOwnProperty(i)) {
  10529. log = logs[i];
  10530. if(log[1]!==Yii.CLogger.prototype.LEVEL_PROFILE) {
  10531. continue;
  10532. }
  10533. message=log[0];
  10534. if(!php.strncasecmp(message,'begin:',6)) {
  10535. log[0]=message.slice(6);
  10536. stack.push(log);
  10537. }
  10538. else if(!php.strncasecmp(message,'end:',4)) {
  10539. token=message.slice(4);
  10540. if((last=php.array_pop(stack))!==null && last[0]===token) {
  10541. delta=log[3]-last[3];
  10542. if(!this.groupByToken) {
  10543. token=log[2];
  10544. }
  10545. if(results[token] !== undefined) {
  10546. results[token]=this.aggregateResult(results[token],delta);
  10547. }
  10548. else {
  10549. results[token]=[token,1,delta,delta,delta];
  10550. }
  10551. }
  10552. else {
  10553. throw new Yii.CException(Yii.t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
  10554. {'{token}':token}));
  10555. }
  10556. }
  10557. }
  10558. }
  10559. now=php.microtime(true);
  10560. while((last=php.array_pop(stack))!==null) {
  10561. delta=now-last[3];
  10562. token=this.groupByToken ? last[0] : last[2];
  10563. if(results[token] !== undefined) {
  10564. results[token]=this.aggregateResult(results[token],delta);
  10565. }
  10566. else {
  10567. results[token]=[token,1,delta,delta,delta];
  10568. }
  10569. }
  10570. entries=php.array_values(results);
  10571. func = function(a,b) {
  10572. return a[4] < b[4] ? 1 : 0;
  10573. };
  10574. php.usort(entries,func);
  10575. data = {
  10576. time: php.sprintf('%0.5f',Yii.getLogger().getExecutionTime()),
  10577. entries: []
  10578. };
  10579. Yii.forEach(entries, function(k, entry) {
  10580. data.entries.push({
  10581. 'proc': Yii.CHtml.encode(entry[0]),
  10582. 'count': php.sprintf('%5d',entry[1]),
  10583. 'min': php.sprintf('%0.5f',entry[2]),
  10584. 'max': php.sprintf('%0.5f',entry[3]),
  10585. 'total': php.sprintf('%0.5f',entry[4]),
  10586. 'average': php.sprintf('%0.5f',entry[4] / entry[1])
  10587. });
  10588. });
  10589. if (this.showInFireBug && window['console'] !== undefined) {
  10590. if (console.group !== undefined) {
  10591. console.group("Profiling Summary Report");
  10592. }
  10593. console.log(" count total average min max ");
  10594. Yii.forEach(data.entries, function(k, entry) {
  10595. console.log(" " + entry.count + " " + entry.total + " " + entry.average + " " + entry.min + " " + entry.max + " " + entry.proc);
  10596. });
  10597. if (console.group !== undefined) {
  10598. console.groupEnd();
  10599. }
  10600. }
  10601. else {
  10602. this.render('profile-summary',data);
  10603. }
  10604. };
  10605. /**
  10606. * Aggregates the report result.
  10607. * @param {Array} result log result for this code block
  10608. * @param {Float} delta time spent for this code block
  10609. */
  10610. Yii.CProfileLogRoute.prototype.aggregateResult = function (result, delta) {
  10611. var token, calls, min, max, total;
  10612. token = result[0];
  10613. calls = result[1];
  10614. min = result[2];
  10615. max = result[3];
  10616. total = result[4];
  10617. if(delta<min) {
  10618. min=delta;
  10619. }
  10620. else if(delta>max) {
  10621. max=delta;
  10622. }
  10623. calls++;
  10624. total+=delta;
  10625. return [token,calls,min,max,total];
  10626. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  10627. /**
  10628. * CDateTimeParser converts a date/time string to a UNIX timestamp according to the specified pattern.
  10629. *
  10630. * The following pattern characters are recognized:
  10631. * <pre>
  10632. * Pattern | Description
  10633. * ----------------------------------------------------
  10634. * d | Day of month 1 to 31, no padding
  10635. * dd | Day of month 01 to 31, zero leading
  10636. * M | Month digit 1 to 12, no padding
  10637. * MM | Month digit 01 to 12, zero leading
  10638. * yy | 2 year digit, e+g+, 96, 05
  10639. * yyyy | 4 year digit, e+g+, 2005
  10640. * h | Hour in 0 to 23, no padding
  10641. * hh | Hour in 00 to 23, zero leading
  10642. * H | Hour in 0 to 23, no padding
  10643. * HH | Hour in 00 to 23, zero leading
  10644. * m | Minutes in 0 to 59, no padding
  10645. * mm | Minutes in 00 to 59, zero leading
  10646. * s | Seconds in 0 to 59, no padding
  10647. * ss | Seconds in 00 to 59, zero leading
  10648. * a | AM or PM, case-insensitive (since version 1.1.5)
  10649. * ----------------------------------------------------
  10650. * </pre>
  10651. * All other characters must appear in the date string at the corresponding positions.
  10652. *
  10653. * For example, to parse a date string '21/10/2008', use the following:
  10654. * <pre>
  10655. * timestamp=Yii.CDateTimeParser.parse('21/10/2008','dd/MM/yyyy');
  10656. * </pre>
  10657. *
  10658. * To format a timestamp to a date string, please use {@link CDateFormatter}.
  10659. *
  10660. * @originalAuthor Wei Zhuo <weizhuo[at]gmail[dot]com>
  10661. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  10662. * @version $Id: CDateTimeParser.php 2928 2011-02-01 17:41:51Z alexander.makarow $
  10663. * @package system.utils
  10664. * @since 1.0
  10665. * @author Charles Pick
  10666. * @class
  10667. */
  10668. Yii.CDateTimeParser = {
  10669. };
  10670. /**
  10671. * Converts a date string to a timestamp.
  10672. * @param {String} value the date string to be parsed
  10673. * @param {String} pattern the pattern that the date string is following
  10674. * @param {Array} defaults the default values for year, month, day, hour, minute and second.
  10675. * The default values will be used in case when the pattern doesn't specify the
  10676. * corresponding fields. For example, if the pattern is 'MM/dd/yyyy' and this
  10677. * parameter is array('minute'=>0, 'second'=>0), then the actual minute and second
  10678. * for the parsing result will take value 0, while the actual hour value will be
  10679. * the current hour obtained by date('H'). This parameter has been available since version 1.1.5.
  10680. * @returns {Integer} timestamp for the date string. False if parsing fails.
  10681. */
  10682. Yii.CDateTimeParser.parse = function (value, pattern, defaults) {
  10683. var tokens, i, n, j, token, year, month, day, hour, minute, second, ampm, tn;
  10684. if (pattern === undefined) {
  10685. pattern = 'MM/dd/yyyy';
  10686. }
  10687. if (defaults === undefined) {
  10688. defaults = [];
  10689. }
  10690. tokens=this.tokenize(pattern);
  10691. i=0;
  10692. n=php.strlen(value);
  10693. for (j in tokens)
  10694. {
  10695. if (tokens.hasOwnProperty(j)) {
  10696. token = tokens[j];
  10697. switch(token)
  10698. {
  10699. case 'yyyy':
  10700. if((year=this.parseInteger(value,i,4,4))===false) {
  10701. return false;
  10702. }
  10703. i+=4;
  10704. break;
  10705. case 'yy':
  10706. if((year=this.parseInteger(value,i,1,2))===false) {
  10707. return false;
  10708. }
  10709. i+=php.strlen(year);
  10710. break;
  10711. case 'MM':
  10712. if((month=this.parseInteger(value,i,2,2))===false) {
  10713. return false;
  10714. }
  10715. i+=2;
  10716. break;
  10717. case 'M':
  10718. if((month=this.parseInteger(value,i,1,2))===false) {
  10719. return false;
  10720. }
  10721. i+=php.strlen(month);
  10722. break;
  10723. case 'dd':
  10724. if((day=this.parseInteger(value,i,2,2))===false) {
  10725. return false;
  10726. }
  10727. i+=2;
  10728. break;
  10729. case 'd':
  10730. if((day=this.parseInteger(value,i,1,2))===false) {
  10731. return false;
  10732. }
  10733. i+=php.strlen(day);
  10734. break;
  10735. case 'h':
  10736. case 'H':
  10737. if((hour=this.parseInteger(value,i,1,2))===false) {
  10738. return false;
  10739. }
  10740. i+=php.strlen(hour);
  10741. break;
  10742. case 'hh':
  10743. case 'HH':
  10744. if((hour=this.parseInteger(value,i,2,2))===false) {
  10745. return false;
  10746. }
  10747. i+=2;
  10748. break;
  10749. case 'm':
  10750. if((minute=this.parseInteger(value,i,1,2))===false) {
  10751. return false;
  10752. }
  10753. i+=php.strlen(minute);
  10754. break;
  10755. case 'mm':
  10756. if((minute=this.parseInteger(value,i,2,2))===false) {
  10757. return false;
  10758. }
  10759. i+=2;
  10760. break;
  10761. case 's':
  10762. if((second=this.parseInteger(value,i,1,2))===false) {
  10763. return false;
  10764. }
  10765. i+=php.strlen(second);
  10766. break;
  10767. case 'ss':
  10768. if((second=this.parseInteger(value,i,2,2))===false) {
  10769. return false;
  10770. }
  10771. i+=2;
  10772. break;
  10773. case 'a':
  10774. if((ampm=this.parseAmPm(value,i))===false) {
  10775. return false;
  10776. }
  10777. if(hour !== undefined)
  10778. {
  10779. if(hour==12 && ampm==='am') {
  10780. hour=0;
  10781. }
  10782. else if(hour<12 && ampm==='pm') {
  10783. hour+=12;
  10784. }
  10785. }
  10786. i+=2;
  10787. break;
  10788. default:
  10789. tn=php.strlen(token);
  10790. if(i>=n || value.slice(i, tn)!==token) {
  10791. return false;
  10792. }
  10793. i+=tn;
  10794. break;
  10795. }
  10796. }
  10797. }
  10798. if(i<n) {
  10799. return false;
  10800. }
  10801. if(year === undefined) {
  10802. year=defaults.year !== undefined ? defaults.year : php.date('Y');
  10803. }
  10804. if(month === undefined) {
  10805. month=defaults.month !== undefined ? defaults.month : php.date('n');
  10806. }
  10807. if(day === undefined) {
  10808. day=defaults.day !== undefined ? defaults.day : php.date('j');
  10809. }
  10810. if(php.strlen(year)===2) {
  10811. if(year>=70) {
  10812. year+=1900;
  10813. }
  10814. else {
  10815. year+=2000;
  10816. }
  10817. }
  10818. year=Number(year);
  10819. month=Number(month);
  10820. day=Number(day);
  10821. if(hour === undefined && minute === undefined && second === undefined && defaults.hour === undefined && defaults.minute === undefined && defaults.second === undefined) {
  10822. hour=minute=second=0;
  10823. }
  10824. else {
  10825. if(hour === undefined) {
  10826. hour=defaults.hour !== undefined ? defaults.hour : php.date('H');
  10827. }
  10828. if(minute === undefined) {
  10829. minute=defaults.minute !== undefined ? defaults.minute : php.date('i');
  10830. }
  10831. if(second === undefined) {
  10832. second=defaults.second !== undefined ? defaults.second : php.date('s');
  10833. }
  10834. hour=Number(hour);
  10835. minute=Number(minute);
  10836. second=Number(second);
  10837. }
  10838. if(Yii.CTimestamp.isValidDate(year,month,day) && Yii.CTimestamp.isValidTime(hour,minute,second)) {
  10839. return Yii.CTimestamp.getTimestamp(hour,minute,second,month,day,year);
  10840. }
  10841. else {
  10842. return false;
  10843. }
  10844. };
  10845. Yii.CDateTimeParser.tokenize = function (pattern) {
  10846. var n, tokens, c0, start, i, c;
  10847. if(!(n=php.strlen(pattern))) {
  10848. return [];
  10849. }
  10850. tokens=[];
  10851. for(c0=pattern[0],start=0,i=1;i<n;++i) {
  10852. if((c=pattern[i])!==c0) {
  10853. tokens.push(pattern.slice(start, i-start));
  10854. c0=c;
  10855. start=i;
  10856. }
  10857. }
  10858. tokens.push(pattern.slice(start, n-start));
  10859. return tokens;
  10860. };
  10861. Yii.CDateTimeParser.parseInteger = function (value, offset, minLength, maxLength) {
  10862. var len, v;
  10863. for(len=maxLength;len>=minLength;--len) {
  10864. v=value.slice(offset, len);
  10865. if(php.ctype_digit(v) && php.strlen(v)>=minLength) {
  10866. return v;
  10867. }
  10868. }
  10869. return false;
  10870. };
  10871. Yii.CDateTimeParser.parseAmPm = function (value, offset) {
  10872. var v;
  10873. v=value.slice(offset, 2).toLowerCase();
  10874. return v==='am' || v==='pm' ? v : false;
  10875. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  10876. /**
  10877. * CFormatter provides a set of commonly used data formatting methods.
  10878. *
  10879. * The formatting methods provided by CFormatter are all named in the form of <code>formatXyz</code>.
  10880. * The behavior of some of them may be configured via the properties of CFormatter. For example,
  10881. * by configuring {@link dateFormat}, one may control how {@link formatDate} formats the value into a date string.
  10882. *
  10883. * For convenience, CFormatter also implements the mechanism of calling formatting methods with their shortcuts (called types).
  10884. * In particular, if a formatting method is named <code>formatXyz</code>, then its shortcut method is <code>xyz</code>
  10885. * (case-insensitive). For example, calling <code>$formatter->date($value)</code> is equivalent to calling
  10886. * <code>$formatter->formatDate($value)</code>.
  10887. *
  10888. * Currently, the following types are recognizable:
  10889. * <ul>
  10890. * <li>raw: the attribute value will not be changed at all.</li>
  10891. * <li>text: the attribute value will be HTML-encoded when rendering.</li>
  10892. * <li>ntext: the {@link formatNtext} method will be called to format the attribute value as a HTML-encoded plain text with newlines converted as the HTML &lt;br /&gt; tags.</li>
  10893. * <li>html: the attribute value will be purified and then returned.</li>
  10894. * <li>date: the {@link formatDate} method will be called to format the attribute value as a date.</li>
  10895. * <li>time: the {@link formatTime} method will be called to format the attribute value as a time.</li>
  10896. * <li>datetime: the {@link formatDatetime} method will be called to format the attribute value as a date with time.</li>
  10897. * <li>boolean: the {@link formatBoolean} method will be called to format the attribute value as a boolean display.</li>
  10898. * <li>number: the {@link formatNumber} method will be called to format the attribute value as a number display.</li>
  10899. * <li>email: the {@link formatEmail} method will be called to format the attribute value as a mailto link.</li>
  10900. * <li>image: the {@link formatImage} method will be called to format the attribute value as an image tag where the attribute value is the image URL.</li>
  10901. * <li>url: the {@link formatUrl} method will be called to format the attribute value as a hyperlink where the attribute value is the URL.</li>
  10902. * </ul>
  10903. *
  10904. * By default, {@link CApplication} registers {@link CFormatter} as an application component whose ID is 'format'.
  10905. * Therefore, one may call <code>Yii::app()->format->boolean(1)</code>.
  10906. *
  10907. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  10908. * @version $Id: CFormatter.php 2799 2011-01-01 19:31:13Z qiang.xue $
  10909. * @package system.utils
  10910. * @since 1.1.0
  10911. * @author Charles Pick
  10912. * @class
  10913. * @extends Yii.CApplicationComponent
  10914. */
  10915. Yii.CFormatter = function CFormatter() {
  10916. };
  10917. Yii.CFormatter.prototype = new Yii.CApplicationComponent();
  10918. Yii.CFormatter.prototype.constructor = Yii.CFormatter;
  10919. Yii.CFormatter.prototype._htmlPurifier = null;
  10920. /**
  10921. * @var {String} the format string to be used to format a date using PHP date() function. Defaults to 'Y/m/d'.
  10922. */
  10923. Yii.CFormatter.prototype.dateFormat = 'Y/m/d';
  10924. /**
  10925. * @var {String} the format string to be used to format a time using PHP date() function. Defaults to 'h:i:s A'.
  10926. */
  10927. Yii.CFormatter.prototype.timeFormat = 'h:i:s A';
  10928. /**
  10929. * @var {String} the format string to be used to format a date and time using PHP date() function. Defaults to 'Y/m/d h:i:s A'.
  10930. */
  10931. Yii.CFormatter.prototype.datetimeFormat = 'Y/m/d h:i:s A';
  10932. /**
  10933. * @var {Array} the format used to format a number with PHP number_format() function.
  10934. * Three elements may be specified: "decimals", "decimalSeparator" and "thousandSeparator". They
  10935. * correspond to the number of digits after the decimal point, the character displayed as the decimal point,
  10936. * and the thousands separator character.
  10937. */
  10938. Yii.CFormatter.prototype.numberFormat = {
  10939. 'decimals':null,
  10940. 'decimalSeparator':null,
  10941. 'thousandSeparator':null
  10942. };
  10943. /**
  10944. * @var {Array} the text to be displayed when formatting a boolean value. The first element corresponds
  10945. * to the text display for false, the second element for true. Defaults to <code>array('No', 'Yes')</code>.
  10946. */
  10947. Yii.CFormatter.prototype.booleanFormat = ['No','Yes'];
  10948. /**
  10949. * Calls the format method when its shortcut is invoked.
  10950. * This is a PHP magic method that we override to implement the shortcut format methods.
  10951. * @param {String} name the method name
  10952. * @param {Array} parameters method parameters
  10953. * @returns {Mixed} the method return value
  10954. */
  10955. Yii.CFormatter.prototype.call = function (name, parameters) {
  10956. if(php.method_exists(this,'format'+name)) {
  10957. return php.call_user_func_array([this,'format'+name],parameters);
  10958. }
  10959. else {
  10960. return parent.call(name,parameters);
  10961. }
  10962. };
  10963. /**
  10964. * Formats a value based on the given type.
  10965. * @param {Mixed} value the value to be formatted
  10966. * @param {String} type the data type. This must correspond to a format method available in CFormatter.
  10967. * For example, we can use 'text' here because there is method named {@link formatText}.
  10968. * @returns {String} the formatted data
  10969. */
  10970. Yii.CFormatter.prototype.format = function (value, type) {
  10971. var method;
  10972. method='format'+php.ucfirst(type);
  10973. if(php.method_exists(this,method)) {
  10974. return this[method](value);
  10975. }
  10976. else {
  10977. throw new Yii.CException(Yii.t('yii','Unknown type "{type}".',{'{type}':type}));
  10978. }
  10979. };
  10980. /**
  10981. * Formats the value as is without any formatting.
  10982. * This method simply returns back the parameter without any format.
  10983. * @param {Mixed} value the value to be formatted
  10984. * @returns {String} the formatted result
  10985. */
  10986. Yii.CFormatter.prototype.formatRaw = function (value) {
  10987. return value;
  10988. };
  10989. /**
  10990. * Formats the value as a HTML-encoded plain text.
  10991. * @param {Mixed} value the value to be formatted
  10992. * @returns {String} the formatted result
  10993. */
  10994. Yii.CFormatter.prototype.formatText = function (value) {
  10995. return Yii.CHtml.encode(value);
  10996. };
  10997. /**
  10998. * Formats the value as a HTML-encoded plain text and converts newlines with HTML br tags.
  10999. * @param {Mixed} value the value to be formatted
  11000. * @returns {String} the formatted result
  11001. */
  11002. Yii.CFormatter.prototype.formatNtext = function (value) {
  11003. return php.nl2br(Yii.CHtml.encode(value));
  11004. };
  11005. /**
  11006. * Formats the value as HTML text without any encoding.
  11007. * @param {Mixed} value the value to be formatted
  11008. * @returns {String} the formatted result
  11009. */
  11010. Yii.CFormatter.prototype.formatHtml = function (value) {
  11011. return this.getHtmlPurifier().purify(value);
  11012. };
  11013. /**
  11014. * Formats the value as a date.
  11015. * @param {Mixed} value the value to be formatted
  11016. * @returns {String} the formatted result
  11017. * @see dateFormat
  11018. */
  11019. Yii.CFormatter.prototype.formatDate = function (value) {
  11020. return php.date(this.dateFormat,value);
  11021. };
  11022. /**
  11023. * Formats the value as a time.
  11024. * @param {Mixed} value the value to be formatted
  11025. * @returns {String} the formatted result
  11026. * @see timeFormat
  11027. */
  11028. Yii.CFormatter.prototype.formatTime = function (value) {
  11029. return php.date(this.timeFormat,value);
  11030. };
  11031. /**
  11032. * Formats the value as a date and time.
  11033. * @param {Mixed} value the value to be formatted
  11034. * @returns {String} the formatted result
  11035. * @see datetimeFormat
  11036. */
  11037. Yii.CFormatter.prototype.formatDatetime = function (value) {
  11038. return php.date(this.datetimeFormat,value);
  11039. };
  11040. /**
  11041. * Formats the value as a boolean.
  11042. * @param {Mixed} value the value to be formatted
  11043. * @returns {String} the formatted result
  11044. * @see trueText
  11045. * @see falseText
  11046. */
  11047. Yii.CFormatter.prototype.formatBoolean = function (value) {
  11048. return value ? this.booleanFormat[1] : this.booleanFormat[0];
  11049. };
  11050. /**
  11051. * Formats the value as a mailto link.
  11052. * @param {Mixed} value the value to be formatted
  11053. * @returns {String} the formatted result
  11054. */
  11055. Yii.CFormatter.prototype.formatEmail = function (value) {
  11056. return Yii.CHtml.mailto(value);
  11057. };
  11058. /**
  11059. * Formats the value as an image tag.
  11060. * @param {Mixed} value the value to be formatted
  11061. * @returns {String} the formatted result
  11062. */
  11063. Yii.CFormatter.prototype.formatImage = function (value) {
  11064. return Yii.CHtml.image(value);
  11065. };
  11066. /**
  11067. * Formats the value as a hyperlink.
  11068. * @param {Mixed} value the value to be formatted
  11069. * @returns {String} the formatted result
  11070. */
  11071. Yii.CFormatter.prototype.formatUrl = function (value) {
  11072. var url;
  11073. url=value;
  11074. if(php.strpos(url,'http://')!==0 && php.strpos(url,'https://')!==0) {
  11075. url='http://'+url;
  11076. }
  11077. return Yii.CHtml.link(Yii.CHtml.encode(value),url);
  11078. };
  11079. /**
  11080. * Formats the value as a number using PHP number_format() function.
  11081. * @param {Mixed} value the value to be formatted
  11082. * @returns {String} the formatted result
  11083. * @see numberFormat
  11084. */
  11085. Yii.CFormatter.prototype.formatNumber = function (value) {
  11086. return php.number_format(value,this.numberFormat['decimals'],this.numberFormat['decimalSeparator'],this.numberFormat['thousandSeparator']);
  11087. };
  11088. /**
  11089. * @returns {Yii.CHtmlPurifier} the HTML purifier instance
  11090. */
  11091. Yii.CFormatter.prototype.getHtmlPurifier = function () {
  11092. if(this._htmlPurifier===null) {
  11093. this._htmlPurifier=new Yii.CHtmlPurifier();
  11094. }
  11095. return this._htmlPurifier;
  11096. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11097. /**
  11098. * CTimestamp represents a timestamp.
  11099. *
  11100. * Part of this class was adapted from the ADOdb Date Library
  11101. * {@link http://phplens.com/phpeverywhere/ ADOdb abstraction library}.
  11102. * The original source code was released under both BSD and GNU Lesser GPL
  11103. * library license, with the following copyright notice:
  11104. * Copyright (c) 2000, 2001, 2002, 2003, 2004 John Lim
  11105. * All rights reserved.
  11106. *
  11107. * This class is provided to support UNIX timestamp that is beyond the range
  11108. * of 1901-2038 on Unix and1970-2038 on Windows. Except {@link getTimestamp},
  11109. * all other methods in this class can work with the extended timestamp range.
  11110. * For {@link getTimestamp}, because it is merely a wrapper of
  11111. * {@link mktime http://php.net/manual/en/function.mktime.php}, it may still
  11112. * be subject to the limit of timestamp range on certain platforms. Please refer
  11113. * to the PHP manual for more information.
  11114. *
  11115. * @originalAuthor Wei Zhuo <weizhuo[at]gmail[dot]com>
  11116. * @version $Id: CTimestamp.php 3046 2011-03-12 01:48:15Z qiang.xue $
  11117. * @package system.utils
  11118. * @since 1.0
  11119. * @author Charles Pick
  11120. * @class
  11121. */
  11122. Yii.CTimestamp = {
  11123. };
  11124. /**
  11125. * Gets day of week, 0 = Sunday,... 6=Saturday.
  11126. * Algorithm from PEAR::Date_Calc
  11127. * @param {Integer} year year
  11128. * @param {Integer} month month
  11129. * @param {Integer} day day
  11130. * @returns {Integer} day of week
  11131. */
  11132. Yii.CTimestamp.getDayofWeek = function (year, month, day) {
  11133. var greg_correction;
  11134. /*
  11135. Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and
  11136. proclaimed that from that time onwards 3 days would be dropped from the calendar
  11137. every 400 years.
  11138. Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian).
  11139. */
  11140. if (year <= 1582) {
  11141. if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day < 15)))) {
  11142. greg_correction = 3;
  11143. }
  11144. else {
  11145. greg_correction = 0;
  11146. }
  11147. }
  11148. else {
  11149. greg_correction = 0;
  11150. }
  11151. if(month > 2) {
  11152. month -= 2;
  11153. }
  11154. else {
  11155. month += 10;
  11156. year--;
  11157. }
  11158. day = php.floor((13 * month - 1) / 5) +
  11159. day + (year % 100) +
  11160. php.floor((year % 100) / 4) +
  11161. php.floor((year / 100) / 4) - 2 *
  11162. php.floor(year / 100) + 77 + greg_correction;
  11163. return day - 7 * php.floor(day / 7);
  11164. };
  11165. /**
  11166. * Checks for leap year, returns true if it is. No 2-digit year check. Also
  11167. * handles julian calendar correctly.
  11168. * @param {Integer} year year to check
  11169. * @returns {Boolean} true if is leap year
  11170. */
  11171. Yii.CTimestamp.isLeapYear = function (year) {
  11172. year = this.digitCheck(year);
  11173. if (year % 4 !== 0) {
  11174. return false;
  11175. }
  11176. if (year % 400 === 0) {
  11177. return true;
  11178. }
  11179. // if gregorian calendar (>1582), century not-divisible by 400 is not leap
  11180. else if (year > 1582 && year % 100 === 0 ) {
  11181. return false;
  11182. }
  11183. return true;
  11184. };
  11185. /**
  11186. * Fix 2-digit years. Works for any century.
  11187. * Assumes that if 2-digit is more than 30 years in future, then previous century.
  11188. * @param {Integer} y year
  11189. * @returns {Integer} change two digit year into multiple digits
  11190. */
  11191. Yii.CTimestamp.digitCheck = function (y) {
  11192. var yr, century, c1, c0;
  11193. if (y < 100){
  11194. yr = Number(php.date("Y"));
  11195. century = Number((yr /100));
  11196. if (yr%100 > 50) {
  11197. c1 = century + 1;
  11198. c0 = century;
  11199. } else {
  11200. c1 = century;
  11201. c0 = century - 1;
  11202. }
  11203. c1 *= 100;
  11204. // if 2-digit year is less than 30 years in future, set it to this century
  11205. // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
  11206. if ((y + c1) < yr+30) { y = y + c1;
  11207. }
  11208. else { y = y + c0*100;
  11209. }
  11210. }
  11211. return y;
  11212. };
  11213. /**
  11214. * Returns 4-digit representation of the year.
  11215. * @param {Integer} y year
  11216. * @returns {Integer} 4-digit representation of the year
  11217. */
  11218. Yii.CTimestamp.get4DigitYear = function (y) {
  11219. return this.digitCheck(y);
  11220. };
  11221. /**
  11222. * @returns {Integer} get local time zone offset from GMT
  11223. */
  11224. Yii.CTimestamp.getGMTDiff = function () {
  11225. var TZ;
  11226. if (TZ !== undefined) { return TZ; }
  11227. TZ = php.mktime(0,0,0,1,2,1970) - php.gmmktime(0,0,0,1,2,1970);
  11228. return TZ;
  11229. };
  11230. /**
  11231. * Returns the getdate() array.
  11232. * @param {Integer} d original date timestamp. False to use the current timestamp.
  11233. * @param {Boolean} fast false to compute the day of the week, default is true
  11234. * @param {Boolean} gmt true to calculate the GMT dates (ignored for now)
  11235. * @returns {Array} an array with date info.
  11236. */
  11237. Yii.CTimestamp.getDate = function (d, fast, gmt) {
  11238. var tz, result;
  11239. if (d === undefined) {
  11240. d = false;
  11241. }
  11242. if (fast === undefined) {
  11243. fast = false;
  11244. }
  11245. if (gmt === undefined) {
  11246. gmt = false;
  11247. }
  11248. result = php.getdate(d);
  11249. return result;
  11250. };
  11251. /**
  11252. * Checks to see if the year, month, day are valid combination.
  11253. * @param {Integer} y year
  11254. * @param {Integer} m month
  11255. * @param {Integer} d day
  11256. * @returns {Boolean} true if valid date, semantic check only.
  11257. */
  11258. Yii.CTimestamp.isValidDate = function (y, m, d) {
  11259. return php.checkdate(m, d, y);
  11260. };
  11261. /**
  11262. * Checks to see if the hour, minute and second are valid.
  11263. * @param {Integer} h hour
  11264. * @param {Integer} m minute
  11265. * @param {Integer} s second
  11266. * @param {Boolean} hs24 whether the hours should be 0 through 23 (default) or 1 through 12.
  11267. * @returns {Boolean} true if valid date, semantic check only.
  11268. * @since 1.0.5
  11269. */
  11270. Yii.CTimestamp.isValidTime = function (h, m, s, hs24) {
  11271. if (hs24 === undefined) {
  11272. hs24 = true;
  11273. }
  11274. if(hs24 && (h < 0 || h > 23) || !hs24 && (h < 1 || h > 12)) {
  11275. return false;
  11276. }
  11277. if(m > 59 || m < 0) {
  11278. return false;
  11279. }
  11280. if(s > 59 || s < 0) {
  11281. return false;
  11282. }
  11283. return true;
  11284. };
  11285. /**
  11286. * Formats a timestamp to a date string.
  11287. * @param {String} fmt format pattern
  11288. * @param {Integer} d timestamp
  11289. * @param {Boolean} is_gmt whether this is a GMT timestamp
  11290. * @returns {String} formatted date based on timestamp $d
  11291. */
  11292. Yii.CTimestamp.formatDate = function (fmt, d, is_gmt) {
  11293. var _day_power, arr, year, month, day, hour, min, secs, max, dates, i, gmt, d10, hh;
  11294. if (d === undefined) {
  11295. d = false;
  11296. }
  11297. if (is_gmt === undefined) {
  11298. is_gmt = false;
  11299. }
  11300. if (d === false) {
  11301. return (is_gmt)? php.gmdate(fmt): php.date(fmt);
  11302. }
  11303. // check if number in 32-bit signed range
  11304. if ((php.abs(d) <= 0x7FFFFFFF)) {
  11305. // if windows, must be +ve integer
  11306. if (d >= 0) {
  11307. return (is_gmt)? php.gmdate(fmt,d): php.date(fmt,d);
  11308. }
  11309. }
  11310. _day_power = 86400;
  11311. arr = this.getDate(d,true,is_gmt);
  11312. year = arr.year;
  11313. month = arr.mon;
  11314. day = arr.mday;
  11315. hour = arr.hours;
  11316. min = arr.minutes;
  11317. secs = arr.seconds;
  11318. max = php.strlen(fmt);
  11319. dates = '';
  11320. /*
  11321. at this point, we have the following integer vars to manipulate:
  11322. $year, $month, $day, $hour, $min, $secs
  11323. */
  11324. for (i=0; i < max; i++)
  11325. {
  11326. switch(fmt[i])
  11327. {
  11328. case 'T':
  11329. dates += php.date('T');
  11330. break;
  11331. // YEAR
  11332. case 'L':
  11333. dates += arr.leap ? '1' : '0';
  11334. break;
  11335. case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
  11336. // 4.3.11 uses '04 Jun 2004'
  11337. // 4.3.8 uses ' 4 Jun 2004'
  11338. dates += php.gmdate('D',_day_power*(3+this.getDayOfWeek(year,month,day)))+', ' + (day<10?'0'+day:day) + ' '+php.date('M',php.mktime(0,0,0,month,2,1971))+' '+year+' ';
  11339. if (hour < 10) {
  11340. dates += '0'+hour;
  11341. }
  11342. else {
  11343. dates += hour;
  11344. }
  11345. if (min < 10) {
  11346. dates += ':0'+min;
  11347. }
  11348. else {
  11349. dates += ':'+min;
  11350. }
  11351. if (secs < 10) {
  11352. dates += ':0'+secs;
  11353. }
  11354. else {
  11355. dates += ':'+secs;
  11356. }
  11357. gmt = this.getGMTDiff();
  11358. dates += php.sprintf(' %s%04d',(gmt<=0)?'+':'-',php.abs(gmt)/36);
  11359. break;
  11360. case 'Y':
  11361. dates += year;
  11362. break;
  11363. case 'y':
  11364. dates += year.slice(php.strlen(year)-2, 2);
  11365. break;
  11366. // MONTH
  11367. case 'm':
  11368. if (month<10) {
  11369. dates += '0'+month;
  11370. }
  11371. else {
  11372. dates += month;
  11373. }
  11374. break;
  11375. case 'Q':
  11376. dates += (month+3)>>2;
  11377. break;
  11378. case 'n':
  11379. dates += month;
  11380. break;
  11381. case 'M':
  11382. dates += php.date('M',php.mktime(0,0,0,month,2,1971));
  11383. break;
  11384. case 'F':
  11385. dates += php.date('F',php.mktime(0,0,0,month,2,1971));
  11386. break;
  11387. // DAY
  11388. case 't':
  11389. dates += arr.ndays;
  11390. break;
  11391. case 'z':
  11392. dates += arr.yday;
  11393. break;
  11394. case 'w':
  11395. dates += this.getDayOfWeek(year,month,day);
  11396. break;
  11397. case 'l':
  11398. dates += php.gmdate('l',_day_power*(3+this.getDayOfWeek(year,month,day)));
  11399. break;
  11400. case 'D':
  11401. dates += php.gmdate('D',_day_power*(3+this.getDayOfWeek(year,month,day)));
  11402. break;
  11403. case 'j':
  11404. dates += day;
  11405. break;
  11406. case 'd':
  11407. if (day<10) {
  11408. dates += '0'+day;
  11409. }
  11410. else {
  11411. dates += day;
  11412. }
  11413. break;
  11414. case 'S':
  11415. d10 = day % 10;
  11416. if (d10 == 1) {
  11417. dates += 'st';
  11418. }
  11419. else if (d10 == 2 && day != 12) {
  11420. dates += 'nd';
  11421. }
  11422. else if (d10 == 3) {
  11423. dates += 'rd';
  11424. }
  11425. else {
  11426. dates += 'th';
  11427. }
  11428. break;
  11429. // HOUR
  11430. case 'Z':
  11431. dates += (is_gmt) ? 0 : -this.getGMTDiff();
  11432. break;
  11433. case 'O':
  11434. gmt = (is_gmt) ? 0 : this.getGMTDiff();
  11435. dates += php.sprintf('%s%04d',(gmt<=0)?'+':'-',php.abs(gmt)/36);
  11436. break;
  11437. case 'H':
  11438. if (hour < 10) {
  11439. dates += '0'+hour;
  11440. }
  11441. else {
  11442. dates += hour;
  11443. }
  11444. break;
  11445. case 'h':
  11446. if (hour > 12) {
  11447. hh = hour - 12;
  11448. }
  11449. else {
  11450. if (hour === 0) {
  11451. hh = '12';
  11452. }
  11453. else {
  11454. hh = hour;
  11455. }
  11456. }
  11457. if (hh < 10) {
  11458. dates += '0'+hh;
  11459. }
  11460. else {
  11461. dates += hh;
  11462. }
  11463. break;
  11464. case 'G':
  11465. dates += hour;
  11466. break;
  11467. case 'g':
  11468. if (hour > 12) {
  11469. hh = hour - 12;
  11470. }
  11471. else {
  11472. if (hour === 0) {
  11473. hh = '12';
  11474. }
  11475. else {
  11476. hh = hour;
  11477. }
  11478. }
  11479. dates += hh;
  11480. break;
  11481. // MINUTES
  11482. case 'i':
  11483. if (min < 10) {
  11484. dates += '0'+min;
  11485. }
  11486. else {
  11487. dates += min;
  11488. }
  11489. break;
  11490. // SECONDS
  11491. case 'U':
  11492. dates += d;
  11493. break;
  11494. case 's':
  11495. if (secs < 10) {
  11496. dates += '0'+secs;
  11497. }
  11498. else {
  11499. dates += secs;
  11500. }
  11501. break;
  11502. // AM/PM
  11503. // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
  11504. case 'a':
  11505. if (hour>=12) {
  11506. dates += 'pm';
  11507. }
  11508. else {
  11509. dates += 'am';
  11510. }
  11511. break;
  11512. case 'A':
  11513. if (hour>=12) {
  11514. dates += 'PM';
  11515. }
  11516. else {
  11517. dates += 'AM';
  11518. }
  11519. break;
  11520. default:
  11521. dates += fmt[i];
  11522. break;
  11523. // ESCAPE
  11524. case "\\":
  11525. i++;
  11526. if (i < max) {
  11527. dates += fmt[i];
  11528. }
  11529. break;
  11530. }
  11531. }
  11532. return dates;
  11533. };
  11534. /**
  11535. * Generates a timestamp.
  11536. * This is the same as the PHP function {@link mktime http://php.net/manual/en/function.mktime.php}.
  11537. * @param {Integer} hr hour
  11538. * @param {Integer} min minute
  11539. * @param {Integer} sec second
  11540. * @param {Integer} mon month
  11541. * @param {Integer} day day
  11542. * @param {Integer} year year
  11543. * @param {Boolean} is_gmt whether this is GMT time. If true, gmmktime() will be used.
  11544. * @returns {Integer|float} a timestamp given a local time.
  11545. */
  11546. Yii.CTimestamp.getTimestamp = function (hr, min, sec, mon, day, year, is_gmt) {
  11547. if (mon === undefined) {
  11548. mon = false;
  11549. }
  11550. if (day === undefined) {
  11551. day = false;
  11552. }
  11553. if (year === undefined) {
  11554. year = false;
  11555. }
  11556. if (is_gmt === undefined) {
  11557. is_gmt = false;
  11558. }
  11559. if (mon === false) {
  11560. return is_gmt? php.gmmktime(hr,min,sec): php.mktime(hr,min,sec);
  11561. }
  11562. return is_gmt ? php.gmmktime(hr,min,sec,mon,day,year) : php.mktime(hr,min,sec,mon,day,year);
  11563. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11564. /**
  11565. * CBooleanValidator validates that the attribute value is either {@link trueValue} or {@link falseValue}.
  11566. *
  11567. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11568. * @version $Id: CBooleanValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $
  11569. * @package system.validators
  11570. * @since 1.0.10
  11571. * @author Charles Pick
  11572. * @class
  11573. * @extends Yii.CValidator
  11574. */
  11575. Yii.CBooleanValidator = function CBooleanValidator() {
  11576. };
  11577. Yii.CBooleanValidator.prototype = new Yii.CValidator();
  11578. Yii.CBooleanValidator.prototype.constructor = Yii.CBooleanValidator;
  11579. /**
  11580. * @var {Mixed} the value representing true status. Defaults to '1'.
  11581. */
  11582. Yii.CBooleanValidator.prototype.trueValue = '1';
  11583. /**
  11584. * @var {Mixed} the value representing false status. Defaults to '0'.
  11585. */
  11586. Yii.CBooleanValidator.prototype.falseValue = '0';
  11587. /**
  11588. * @var {Boolean} whether the comparison to {@link trueValue} and {@link falseValue} is strict.
  11589. * When this is true, the attribute value and type must both match those of {@link trueValue} or {@link falseValue}.
  11590. * Defaults to false, meaning only the value needs to be matched.
  11591. */
  11592. Yii.CBooleanValidator.prototype.strict = false;
  11593. /**
  11594. * @var {Boolean} whether the attribute value can be null or empty. Defaults to true,
  11595. * meaning that if the attribute is empty, it is considered valid.
  11596. */
  11597. Yii.CBooleanValidator.prototype.allowEmpty = true;
  11598. /**
  11599. * Validates the attribute of the object.
  11600. * If there is any error, the error message is added to the object.
  11601. * @param {Yii.CModel} object the object being validated
  11602. * @param {String} attribute the attribute being validated
  11603. */
  11604. Yii.CBooleanValidator.prototype.validateAttribute = function (object, attribute) {
  11605. var value, message;
  11606. value=object.get(attribute);
  11607. if(this.allowEmpty && this.isEmpty(value)) {
  11608. return;
  11609. }
  11610. if(!this.strict && value!=this.trueValue && value!=this.falseValue || this.strict && value!==this.trueValue && value!==this.falseValue) {
  11611. message=this.message!==null?this.message:Yii.t('yii','{attribute} must be either {true} or {false}.');
  11612. this.addError(object,attribute,message,{
  11613. '{true}':this.trueValue,
  11614. '{false}':this.falseValue
  11615. });
  11616. }
  11617. };
  11618. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11619. /**
  11620. * CEmailValidator validates that the attribute value is a valid email address.
  11621. *
  11622. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11623. * @version $Id: CEmailValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $
  11624. * @package system.validators
  11625. * @since 1.0
  11626. * @author Charles Pick
  11627. * @class
  11628. * @extends Yii.CValidator
  11629. */
  11630. Yii.CEmailValidator = function CEmailValidator() {
  11631. };
  11632. Yii.CEmailValidator.prototype = new Yii.CValidator();
  11633. Yii.CEmailValidator.prototype.constructor = Yii.CEmailValidator;
  11634. /**
  11635. * @var {String} the regular expression used to validate the attribute value.
  11636. * @see http://www.regular-expressions.info/email.html
  11637. */
  11638. Yii.CEmailValidator.prototype.pattern = '^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$';
  11639. /**
  11640. * @var {String} the regular expression used to validate email addresses with the name part.
  11641. * This property is used only when {@link allowName} is true.
  11642. * @since 1.0.5
  11643. * @see allowName
  11644. */
  11645. Yii.CEmailValidator.prototype.fullPattern = '^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$';
  11646. /**
  11647. * @var {Boolean} whether to allow name in the email address (e.g. "Qiang Xue <qiang.xue@gmail.com>"). Defaults to false.
  11648. * @since 1.0.5
  11649. * @see fullPattern
  11650. */
  11651. Yii.CEmailValidator.prototype.allowName = false;
  11652. /**
  11653. * @var {Boolean} whether the attribute value can be null or empty. Defaults to true,
  11654. * meaning that if the attribute is empty, it is considered valid.
  11655. */
  11656. Yii.CEmailValidator.prototype.allowEmpty = true;
  11657. /**
  11658. * Validates the attribute of the object.
  11659. * If there is any error, the error message is added to the object.
  11660. * @param {Yii.CModel} object the object being validated
  11661. * @param {String} attribute the attribute being validated
  11662. */
  11663. Yii.CEmailValidator.prototype.validateAttribute = function (object, attribute) {
  11664. var value, message;
  11665. value=object[attribute];
  11666. if(this.allowEmpty && this.isEmpty(value)) {
  11667. return;
  11668. }
  11669. if(!this.validateValue(value)) {
  11670. message=this.message!==null?this.message:Yii.t('yii','{attribute} is not a valid email address.');
  11671. this.addError(object,attribute,message);
  11672. }
  11673. };
  11674. /**
  11675. * Validates a static value to see if it is a valid email.
  11676. * Note that this method does not respect {@link allowEmpty} property.
  11677. * This method is provided so that you can call it directly without going through the model validation rule mechanism.
  11678. * @param {Mixed} value the value to be validated
  11679. * @returns {Boolean} whether the value is a valid email
  11680. * @since 1.1.1
  11681. */
  11682. Yii.CEmailValidator.prototype.validateValue = function (value) {
  11683. var valid, re, reFull;
  11684. re = new RegExp(this.pattern);
  11685. reFull = new RegExp(this.fullPattern);
  11686. valid=typeof(value) === 'string' && (re.exec(value) || this.allowName && reFull.exec(value));
  11687. return valid;
  11688. };
  11689. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11690. /**
  11691. * CInlineValidator represents a validator which is defined as a method in the object being validated.
  11692. *
  11693. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11694. * @version $Id: CInlineValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $
  11695. * @package system.validators
  11696. * @since 1.0
  11697. * @author Charles Pick
  11698. * @class
  11699. * @extends Yii.CValidator
  11700. */
  11701. Yii.CInlineValidator = function CInlineValidator() {
  11702. };
  11703. Yii.CInlineValidator.prototype = new Yii.CValidator();
  11704. Yii.CInlineValidator.prototype.constructor = Yii.CInlineValidator;
  11705. /**
  11706. * @var {String} the name of the validation method defined in the active record class
  11707. */
  11708. Yii.CInlineValidator.prototype.method = null;
  11709. /**
  11710. * @var {Array} additional parameters that are passed to the validation method
  11711. */
  11712. Yii.CInlineValidator.prototype.params = null;
  11713. /**
  11714. * Validates the attribute of the object.
  11715. * If there is any error, the error message is added to the object.
  11716. * @param {Yii.CModel} object the object being validated
  11717. * @param {String} attribute the attribute being validated
  11718. */
  11719. Yii.CInlineValidator.prototype.validateAttribute = function (object, attribute) {
  11720. var method;
  11721. method=this.method;
  11722. object[method](attribute,this.params);
  11723. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11724. /**
  11725. * CNumberValidator validates that the attribute value is a number.
  11726. *
  11727. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11728. * @version $Id: CNumberValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $
  11729. * @package system.validators
  11730. * @since 1.0
  11731. * @author Charles Pick
  11732. * @class
  11733. * @extends Yii.CValidator
  11734. */
  11735. Yii.CNumberValidator = function CNumberValidator() {
  11736. };
  11737. Yii.CNumberValidator.prototype = new Yii.CValidator();
  11738. Yii.CNumberValidator.prototype.constructor = Yii.CNumberValidator;
  11739. /**
  11740. * @var {Boolean} whether the attribute value can only be an integer. Defaults to false.
  11741. */
  11742. Yii.CNumberValidator.prototype.integerOnly = false;
  11743. /**
  11744. * @var {Boolean} whether the attribute value can be null or empty. Defaults to true,
  11745. * meaning that if the attribute is empty, it is considered valid.
  11746. */
  11747. Yii.CNumberValidator.prototype.allowEmpty = true;
  11748. /**
  11749. * @var {Integer|float} upper limit of the number. Defaults to null, meaning no upper limit.
  11750. */
  11751. Yii.CNumberValidator.prototype.max = null;
  11752. /**
  11753. * @var {Integer|float} lower limit of the number. Defaults to null, meaning no lower limit.
  11754. */
  11755. Yii.CNumberValidator.prototype.min = null;
  11756. /**
  11757. * @var {String} user-defined error message used when the value is too big.
  11758. */
  11759. Yii.CNumberValidator.prototype.tooBig = null;
  11760. /**
  11761. * @var {String} user-defined error message used when the value is too small.
  11762. */
  11763. Yii.CNumberValidator.prototype.tooSmall = null;
  11764. /**
  11765. * @var {String} the regular expression for matching integers.
  11766. * @since 1.1.7
  11767. */
  11768. Yii.CNumberValidator.prototype.integerPattern = '^\\s*[+-]?\\d+\\s*$';
  11769. /**
  11770. * @var {String} the regular expression for matching numbers.
  11771. * @since 1.1.7
  11772. */
  11773. Yii.CNumberValidator.prototype.numberPattern = '^\\s*[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?\\s*$';
  11774. /**
  11775. * Validates the attribute of the object.
  11776. * If there is any error, the error message is added to the object.
  11777. * @param {Yii.CModel} object the object being validated
  11778. * @param {String} attribute the attribute being validated
  11779. */
  11780. Yii.CNumberValidator.prototype.validateAttribute = function (object, attribute) {
  11781. var value, message, intRe = new RegExp(this.integerPattern), numRe = new RegExp(this.numberPattern);
  11782. value=String(object[attribute]);
  11783. if(this.allowEmpty && this.isEmpty(value)) {
  11784. return;
  11785. }
  11786. if(this.integerOnly) {
  11787. if(!intRe.exec(value)) {
  11788. message=this.message!==null?this.message:Yii.t('yii','{attribute} must be an integer.');
  11789. this.addError(object,attribute,message);
  11790. }
  11791. }
  11792. else {
  11793. if(!numRe.exec(value)) {
  11794. message=this.message!==null?this.message:Yii.t('yii','{attribute} must be a number.');
  11795. this.addError(object,attribute,message);
  11796. }
  11797. }
  11798. if(this.min!==null && value<this.min) {
  11799. message=this.tooSmall!==null?this.tooSmall:Yii.t('yii','{attribute} is too small (minimum is {min}).');
  11800. this.addError(object,attribute,message,{'{min}':this.min});
  11801. }
  11802. if(this.max!==null && value>this.max) {
  11803. message=this.tooBig!==null?this.tooBig:Yii.t('yii','{attribute} is too big (maximum is {max}).');
  11804. this.addError(object,attribute,message,{'{max}':this.max});
  11805. }
  11806. };
  11807. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11808. /**
  11809. * CRangeValidator validates that the attribute value is among the list (specified via {@link range}).
  11810. * You may invert the validation logic with help of the {@link not} property (available since 1.1.5).
  11811. *
  11812. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11813. * @version $Id: CRangeValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $
  11814. * @package system.validators
  11815. * @since 1.0
  11816. * @author Charles Pick
  11817. * @class
  11818. * @extends Yii.CValidator
  11819. */
  11820. Yii.CRangeValidator = function CRangeValidator() {
  11821. };
  11822. Yii.CRangeValidator.prototype = new Yii.CValidator();
  11823. Yii.CRangeValidator.prototype.constructor = Yii.CRangeValidator;
  11824. /**
  11825. * @var {Array} list of valid values that the attribute value should be among
  11826. */
  11827. Yii.CRangeValidator.prototype.range = null;
  11828. /**
  11829. * @var {Boolean} whether the comparison is strict (both type and value must be the same)
  11830. */
  11831. Yii.CRangeValidator.prototype.strict = false;
  11832. /**
  11833. * @var {Boolean} whether the attribute value can be null or empty. Defaults to true,
  11834. * meaning that if the attribute is empty, it is considered valid.
  11835. */
  11836. Yii.CRangeValidator.prototype.allowEmpty = true;
  11837. /**
  11838. * @var {Boolean} whether to invert the validation logic. Defaults to false. If set to true,
  11839. * the attribute value should NOT be among the list of values defined via {@link range}.
  11840. * @since 1.1.5
  11841. */
  11842. Yii.CRangeValidator.prototype.not = false;
  11843. /**
  11844. * Validates the attribute of the object.
  11845. * If there is any error, the error message is added to the object.
  11846. * @param {Yii.CModel} object the object being validated
  11847. * @param {String} attribute the attribute being validated
  11848. */
  11849. Yii.CRangeValidator.prototype.validateAttribute = function (object, attribute) {
  11850. var value, message;
  11851. value=object.get(attribute);
  11852. if(this.allowEmpty && this.isEmpty(value)) {
  11853. return;
  11854. }
  11855. if(Object.prototype.toString.call(this.range) !== '[object Array]') {
  11856. throw new Yii.CException(Yii.t('yii','The "range" property must be specified with a list of values.'));
  11857. }
  11858. if(!this.not && !php.in_array(value,this.range,this.strict))
  11859. {
  11860. message=this.message!==null?this.message:Yii.t('yii','{attribute} is not in the list.');
  11861. this.addError(object,attribute,message);
  11862. }
  11863. else if(this.not && php.in_array(value,this.range,this.strict))
  11864. {
  11865. message=this.message!==null?this.message:Yii.t('yii','{attribute} is in the list.');
  11866. this.addError(object,attribute,message);
  11867. }
  11868. };
  11869. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11870. /**
  11871. * CRequiredValidator validates that the specified attribute does not have null or empty value.
  11872. *
  11873. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11874. * @version $Id: CRequiredValidator.php 3157 2011-04-02 19:21:06Z qiang.xue $
  11875. * @package system.validators
  11876. * @since 1.0
  11877. * @author Charles Pick
  11878. * @class
  11879. * @extends Yii.CValidator
  11880. */
  11881. Yii.CRequiredValidator = function CRequiredValidator() {
  11882. };
  11883. Yii.CRequiredValidator.prototype = new Yii.CValidator();
  11884. Yii.CRequiredValidator.prototype.constructor = Yii.CRequiredValidator;
  11885. /**
  11886. * @var {Mixed} the desired value that the attribute must have.
  11887. * If this is null, the validator will validate that the specified attribute does not have null or empty value.
  11888. * If this is set as a value that is not null, the validator will validate that
  11889. * the attribute has a value that is the same as this property value.
  11890. * Defaults to null.
  11891. * @since 1.0.10
  11892. */
  11893. Yii.CRequiredValidator.prototype.requiredValue = null;
  11894. /**
  11895. * @var {Boolean} whether the comparison to {@link requiredValue} is strict.
  11896. * When this is true, the attribute value and type must both match those of {@link requiredValue}.
  11897. * Defaults to false, meaning only the value needs to be matched.
  11898. * This property is only used when {@link requiredValue} is not null.
  11899. * @since 1.0.10
  11900. */
  11901. Yii.CRequiredValidator.prototype.strict = false;
  11902. /**
  11903. * Validates the attribute of the object.
  11904. * If there is any error, the error message is added to the object.
  11905. * @param {Yii.CModel} object the object being validated
  11906. * @param {String} attribute the attribute being validated
  11907. */
  11908. Yii.CRequiredValidator.prototype.validateAttribute = function (object, attribute) {
  11909. var value, message;
  11910. value=object.get(attribute);
  11911. if(this.requiredValue!==null) {
  11912. if(!this.strict && value!=this.requiredValue || this.strict && value!==this.requiredValue) {
  11913. message=this.message!==null?this.message:Yii.t('yii','{attribute} must be {value}.',
  11914. {'{value}':this.requiredValue});
  11915. this.addError(object,attribute,message);
  11916. }
  11917. }
  11918. else if(this.isEmpty(value,true)) {
  11919. message=this.message!==null?this.message:Yii.t('yii','{attribute} cannot be blank.');
  11920. this.addError(object,attribute,message);
  11921. }
  11922. };
  11923. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  11924. /**
  11925. * CTypeValidator verifies if the attribute is of the type specified by {@link type}.
  11926. *
  11927. * The following data types are supported:
  11928. * <ul>
  11929. * <li><b>integer</b> A 32-bit signed integer data type.</li>
  11930. * <li><b>float</b> A double-precision floating point number data type.</li>
  11931. * <li><b>string</b> A string data type.</li>
  11932. * <li><b>array</b> An array value. </li>
  11933. * <li><b>date</b> A date data type.</li>
  11934. * <li><b>time</b> A time data type (available since version 1.0.5).</li>
  11935. * <li><b>datetime</b> A date and time data type (available since version 1.0.5).</li>
  11936. * </ul>
  11937. *
  11938. * For <b>date</b> type, the property {@link dateFormat}
  11939. * will be used to determine how to parse the date string. If the given date
  11940. * value doesn't follow the format, the attribute is considered as invalid.
  11941. *
  11942. * Starting from version 1.1.7, we have a dedicated date validator {@link CDateValidator}.
  11943. * Please consider using this validator to validate a date-typed value.
  11944. *
  11945. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  11946. * @version $Id: CTypeValidator.php 3052 2011-03-12 14:27:07Z qiang.xue $
  11947. * @package system.validators
  11948. * @since 1.0
  11949. * @author Charles Pick
  11950. * @class
  11951. * @extends Yii.CValidator
  11952. */
  11953. Yii.CTypeValidator = function CTypeValidator() {
  11954. };
  11955. Yii.CTypeValidator.prototype = new Yii.CValidator();
  11956. Yii.CTypeValidator.prototype.constructor = Yii.CTypeValidator;
  11957. /**
  11958. * @var {String} the data type that the attribute should be. Defaults to 'string'.
  11959. * Valid values include 'string', 'integer', 'float', 'array', 'date', 'time' and 'datetime'.
  11960. * Note that 'time' and 'datetime' have been available since version 1.0.5.
  11961. */
  11962. Yii.CTypeValidator.prototype.type = 'string';
  11963. /**
  11964. * @var {String} the format pattern that the date value should follow. Defaults to 'MM/dd/yyyy'.
  11965. * Please see {@link CDateTimeParser} for details about how to specify a date format.
  11966. * This property is effective only when {@link type} is 'date'.
  11967. */
  11968. Yii.CTypeValidator.prototype.dateFormat = 'MM/dd/yyyy';
  11969. /**
  11970. * @var {String} the format pattern that the time value should follow. Defaults to 'hh:mm'.
  11971. * Please see {@link CDateTimeParser} for details about how to specify a time format.
  11972. * This property is effective only when {@link type} is 'time'.
  11973. * @since 1.0.5
  11974. */
  11975. Yii.CTypeValidator.prototype.timeFormat = 'hh:mm';
  11976. /**
  11977. * @var {String} the format pattern that the datetime value should follow. Defaults to 'MM/dd/yyyy hh:mm'.
  11978. * Please see {@link CDateTimeParser} for details about how to specify a datetime format.
  11979. * This property is effective only when {@link type} is 'datetime'.
  11980. * @since 1.0.5
  11981. */
  11982. Yii.CTypeValidator.prototype.datetimeFormat = 'MM/dd/yyyy hh:mm';
  11983. /**
  11984. * @var {Boolean} whether the attribute value can be null or empty. Defaults to true,
  11985. * meaning that if the attribute is empty, it is considered valid.
  11986. */
  11987. Yii.CTypeValidator.prototype.allowEmpty = true;
  11988. /**
  11989. * Validates the attribute of the object.
  11990. * If there is any error, the error message is added to the object.
  11991. * @param {Yii.CModel} object the object being validated
  11992. * @param {String} attribute the attribute being validated
  11993. */
  11994. Yii.CTypeValidator.prototype.validateAttribute = function (object, attribute) {
  11995. var value, valid, message;
  11996. value=object.get(attribute);
  11997. if(this.allowEmpty && this.isEmpty(value)) {
  11998. return;
  11999. }
  12000. if(this.type==='integer') {
  12001. valid=/^[\-+]?[0-9]+$/.exec(php.trim(value));
  12002. }
  12003. else if(this.type==='float') {
  12004. valid=/^[\-+]?([0-9]*\.)?[0-9]+([eE][\-+]?[0-9]+)?$/.exec(php.trim(value));
  12005. }
  12006. else if(this.type==='date') {
  12007. valid=Yii.CDateTimeParser.parse(value,this.dateFormat,{'month':1,'day':1,'hour':0,'minute':0,'second':0})!==false;
  12008. }
  12009. else if(this.type==='time') {
  12010. valid=Yii.CDateTimeParser.parse(value,this.timeFormat)!==false;
  12011. }
  12012. else if(this.type==='datetime') {
  12013. valid=Yii.CDateTimeParser.parse(value,this.datetimeFormat, {'month':1,'day':1,'hour':0,'minute':0,'second':0})!==false;
  12014. }
  12015. else if(this.type==='array') {
  12016. valid=Object.prototype.toString.call(value) === '[object Array]';
  12017. }
  12018. else {
  12019. return;
  12020. }
  12021. if(!valid) {
  12022. message=this.message!==null?this.message : Yii.t('yii','{attribute} must be {type}.');
  12023. this.addError(object,attribute,message,{'{type}':this.type});
  12024. }
  12025. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  12026. /**
  12027. * CUrlValidator validates that the attribute value is a valid http or https URL.
  12028. *
  12029. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  12030. * @version $Id: CUrlValidator.php 3120 2011-03-25 01:50:48Z qiang.xue $
  12031. * @package system.validators
  12032. * @since 1.0
  12033. * @author Charles Pick
  12034. * @class
  12035. * @extends Yii.CValidator
  12036. */
  12037. Yii.CUrlValidator = function CUrlValidator() {
  12038. };
  12039. Yii.CUrlValidator.prototype = new Yii.CValidator();
  12040. Yii.CUrlValidator.prototype.constructor = Yii.CUrlValidator;
  12041. /**
  12042. * @var {String} the regular expression used to validate the attribute value.
  12043. * Since version 1.1.7 the pattern may contain a {schemes} token that will be replaced
  12044. * by a regular expression which represents the {@see validSchemes}.
  12045. */
  12046. Yii.CUrlValidator.prototype.pattern = '^{schemes}:\\/\\/(([A-Z0-9][A-Z0-9_-]*)(\\.[A-Z0-9][A-Z0-9_-]*)+)';
  12047. /**
  12048. * @var {Array} list of URI schemes which should be considered valid. By default, http and https
  12049. * are considered to be valid schemes.
  12050. * @since 1.1.7
  12051. */
  12052. Yii.CUrlValidator.prototype.validSchemes = ['http','https'];
  12053. /**
  12054. * @var {String} the default URI scheme. If the input doesn't contain the scheme part, the default
  12055. * scheme will be prepended to it (thus changing the input). Defaults to null, meaning a URL must
  12056. * contain the scheme part.
  12057. * @since 1.1.7
  12058. */
  12059. Yii.CUrlValidator.prototype.defaultScheme = null;
  12060. /**
  12061. * @var {Boolean} whether the attribute value can be null or empty. Defaults to true,
  12062. * meaning that if the attribute is empty, it is considered valid.
  12063. */
  12064. Yii.CUrlValidator.prototype.allowEmpty = true;
  12065. /**
  12066. * Validates the attribute of the object.
  12067. * If there is any error, the error message is added to the object.
  12068. * @param {Yii.CModel} object the object being validated
  12069. * @param {String} attribute the attribute being validated
  12070. */
  12071. Yii.CUrlValidator.prototype.validateAttribute = function (object, attribute) {
  12072. var value, message;
  12073. value=object.get(attribute);
  12074. if(this.allowEmpty && this.isEmpty(value)) {
  12075. return;
  12076. }
  12077. if((value=this.validateValue(value))!==false) {
  12078. object[attribute]=value;
  12079. }
  12080. else {
  12081. message=this.message!==null?this.message:Yii.t('yii','{attribute} is not a valid URL.');
  12082. this.addError(object,attribute,message);
  12083. }
  12084. };
  12085. /**
  12086. * Validates a static value to see if it is a valid URL.
  12087. * Note that this method does not respect {@link allowEmpty} property.
  12088. * This method is provided so that you can call it directly without going through the model validation rule mechanism.
  12089. * @param {Mixed} value the value to be validated
  12090. * @returns {Mixed} false if the the value is not a valid URL, otherwise the possibly modified value ({@see defaultScheme})
  12091. * @since 1.1.1
  12092. */
  12093. Yii.CUrlValidator.prototype.validateValue = function (value) {
  12094. var pattern, re;
  12095. if(typeof(value) === 'string') {
  12096. if(this.defaultScheme!==null && php.strpos(value,'://')===false) {
  12097. value=this.defaultScheme+'://'+value;
  12098. }
  12099. if(php.strpos(this.pattern,'{schemes}')!==false) {
  12100. pattern=php.str_replace('{schemes}','('+this.validSchemes.join('|')+')',this.pattern);
  12101. }
  12102. else {
  12103. pattern=this.pattern;
  12104. }
  12105. re = new RegExp(this.pattern,"i");
  12106. if(re.exec(value)) {
  12107. return value;
  12108. }
  12109. }
  12110. return false;
  12111. };
  12112. /*
  12113. * Original script by Josh Fraser (http://www.onlineaspect.com)
  12114. * Continued by Jon Nylander, (jon at pageloom dot com)
  12115. * According to both of us, you are absolutely free to do whatever
  12116. * you want with this code.
  12117. *
  12118. * This code is maintained at bitbucket.org as jsTimezoneDetect.
  12119. */
  12120. /**
  12121. * Namespace to hold all the code for timezone detection.
  12122. */
  12123. var jzTimezoneDetector = {};
  12124. jzTimezoneDetector.HEMISPHERE_SOUTH = 'SOUTH';
  12125. jzTimezoneDetector.HEMISPHERE_NORTH = 'NORTH';
  12126. jzTimezoneDetector.HEMISPHERE_UNKNOWN = 'N/A';
  12127. jzTimezoneDetector.olson = {};
  12128. /**
  12129. * A simple object containing information of utc_offset, which olson timezone key to use,
  12130. * and if the timezone cares about daylight savings or not.
  12131. *
  12132. * @constructor
  12133. * @param {string} offset - for example '-11:00'
  12134. * @param {string} olson_tz - the olson Identifier, such as "America/Denver"
  12135. * @param {boolean} uses_dst - flag for whether the time zone somehow cares about daylight savings.
  12136. */
  12137. jzTimezoneDetector.TimeZone = function (offset, olson_tz, uses_dst) {
  12138. this.utc_offset = offset;
  12139. this.olson_tz = olson_tz;
  12140. this.uses_dst = uses_dst;
  12141. };
  12142. /**
  12143. * Prints out the result.
  12144. * But before it does that, it calls this.ambiguity_check.
  12145. */
  12146. jzTimezoneDetector.TimeZone.prototype.display = function() {
  12147. this.ambiguity_check();
  12148. var response_text = '<b>UTC-offset</b>: ' + this.utc_offset + '<br/>';
  12149. response_text += '<b>Zoneinfo key</b>: ' + this.olson_tz + '<br/>';
  12150. response_text += '<b>Zone uses DST</b>: ' + (this.uses_dst ? 'yes' : 'no') + '<br/>';
  12151. return response_text;
  12152. };
  12153. /**
  12154. * Checks if a timezone has possible ambiguities. I.e timezones that are similar.
  12155. *
  12156. * If the preliminary scan determines that we're in America/Denver. We double check
  12157. * here that we're really there and not in America/Mazatlan.
  12158. *
  12159. * This is done by checking known dates for when daylight savings start for different
  12160. * timezones.
  12161. */
  12162. jzTimezoneDetector.TimeZone.prototype.ambiguity_check = function() {
  12163. var local_ambiguity_list = jzTimezoneDetector.olson.ambiguity_list[this.olson_tz];
  12164. if (typeof(local_ambiguity_list) == 'undefined') {
  12165. return;
  12166. }
  12167. var length = local_ambiguity_list.length;
  12168. for (var i = 0; i < length; i++) {
  12169. var tz = local_ambiguity_list[i];
  12170. if (jzTimezoneDetector.date_is_dst(jzTimezoneDetector.olson.dst_start_dates[tz])) {
  12171. this.olson_tz = tz;
  12172. return;
  12173. }
  12174. }
  12175. };
  12176. /**
  12177. * Checks whether a given date is in daylight savings time.
  12178. *
  12179. * If the date supplied is after june, we assume that we're checking
  12180. * for southern hemisphere DST.
  12181. *
  12182. * @param {Date} date
  12183. * @returns {boolean}
  12184. */
  12185. jzTimezoneDetector.date_is_dst = function (date) {
  12186. var base_offset, date_offset;
  12187. base_offset = ( (date.getMonth() > 5 ? jzTimezoneDetector.get_june_offset() : jzTimezoneDetector.get_january_offset()) );
  12188. date_offset = jzTimezoneDetector.get_date_offset(date);
  12189. return (base_offset - date_offset) !== 0;
  12190. };
  12191. /**
  12192. * Gets the offset in minutes from UTC for a certain date.
  12193. *
  12194. * @param date
  12195. * @returns {number}
  12196. */
  12197. jzTimezoneDetector.get_date_offset = function (date) {
  12198. return -date.getTimezoneOffset();
  12199. };
  12200. /**
  12201. * This function does some basic calculations to create information about
  12202. * the user's timezone.
  12203. *
  12204. * Returns a primitive object on the format
  12205. * {'utc_offset' : -9, 'dst': 1, hemisphere' : 'north'}
  12206. * where dst is 1 if the region uses daylight savings.
  12207. *
  12208. * @returns {Object}
  12209. */
  12210. jzTimezoneDetector.get_timezone_info = function () {
  12211. var january_offset = jzTimezoneDetector.get_january_offset();
  12212. var june_offset = jzTimezoneDetector.get_june_offset();
  12213. var diff = january_offset - june_offset;
  12214. if (diff < 0) {
  12215. return {'utc_offset' : january_offset,
  12216. 'dst': 1,
  12217. 'hemisphere' : jzTimezoneDetector.HEMISPHERE_NORTH};
  12218. }
  12219. else if (diff > 0) {
  12220. return {'utc_offset' : june_offset,
  12221. 'dst' : 1,
  12222. 'hemisphere' : jzTimezoneDetector.HEMISPHERE_SOUTH};
  12223. }
  12224. return {'utc_offset' : january_offset,
  12225. 'dst': 0,
  12226. 'hemisphere' : jzTimezoneDetector.HEMISPHERE_UNKNOWN};
  12227. };
  12228. jzTimezoneDetector.get_january_offset = function () {
  12229. return jzTimezoneDetector.get_date_offset(new Date(2011, 0, 1, 0, 0, 0, 0));
  12230. };
  12231. jzTimezoneDetector.get_june_offset = function () {
  12232. return jzTimezoneDetector.get_date_offset(new Date(2011, 5, 1, 0, 0, 0, 0));
  12233. };
  12234. /**
  12235. * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary.
  12236. *
  12237. * Returns a primitive object on the format:
  12238. * {'timezone': TimeZone, 'key' : 'the key used to find the TimeZone object'}
  12239. *
  12240. * @returns Object
  12241. */
  12242. jzTimezoneDetector.determine_timezone = function () {
  12243. var tz_key, timezone_key_info = jzTimezoneDetector.get_timezone_info(), hemisphere_suffix = '';
  12244. if (timezone_key_info.hemisphere == jzTimezoneDetector.HEMISPHERE_SOUTH) {
  12245. hemisphere_suffix = ',s';
  12246. }
  12247. tz_key = timezone_key_info.utc_offset + ',' + timezone_key_info.dst + hemisphere_suffix;
  12248. return {'timezone' : jzTimezoneDetector.olson.timezones[tz_key], 'key' : tz_key};
  12249. };
  12250. /**
  12251. * The keys in this dictionary are comma separated as such:
  12252. *
  12253. * First the offset compared to UTC time in minutes.
  12254. *
  12255. * Then a flag which is 0 if the timezone does not take daylight savings into account and 1 if it does.
  12256. *
  12257. * Thirdly an optional 's' signifies that the timezone is in the southern hemisphere, only interesting for timezones with DST.
  12258. *
  12259. * The values of the dictionary are TimeZone objects.
  12260. */
  12261. jzTimezoneDetector.olson.timezones = {
  12262. '-720,0' : new jzTimezoneDetector.TimeZone('-12:00','Etc/GMT+12', false),
  12263. '-660,0' : new jzTimezoneDetector.TimeZone('-11:00','Pacific/Pago_Pago', false),
  12264. '-600,1' : new jzTimezoneDetector.TimeZone('-11:00','America/Adak',true),
  12265. '-660,1,s' : new jzTimezoneDetector.TimeZone('-11:00','Pacific/Apia', true),
  12266. '-600,0' : new jzTimezoneDetector.TimeZone('-10:00','Pacific/Honolulu', false),
  12267. '-570,0' : new jzTimezoneDetector.TimeZone('-10:30','Pacific/Marquesas',false),
  12268. '-540,0' : new jzTimezoneDetector.TimeZone('-09:00','Pacific/Gambier',false),
  12269. '-540,1' : new jzTimezoneDetector.TimeZone('-09:00','America/Anchorage', true),
  12270. '-480,1' : new jzTimezoneDetector.TimeZone('-08:00','America/Los_Angeles', true),
  12271. '-480,0' : new jzTimezoneDetector.TimeZone('-08:00','Pacific/Pitcairn',false),
  12272. '-420,0' : new jzTimezoneDetector.TimeZone('-07:00','America/Phoenix', false),
  12273. '-420,1' : new jzTimezoneDetector.TimeZone('-07:00','America/Denver', true),
  12274. '-360,0' : new jzTimezoneDetector.TimeZone('-06:00','America/Guatemala', false),
  12275. '-360,1' : new jzTimezoneDetector.TimeZone('-06:00','America/Chicago', true),
  12276. '-360,1,s' : new jzTimezoneDetector.TimeZone('-06:00','Pacific/Easter',true),
  12277. '-300,0' : new jzTimezoneDetector.TimeZone('-05:00','America/Bogota', false),
  12278. '-300,1' : new jzTimezoneDetector.TimeZone('-05:00','America/New_York', true),
  12279. '-270,0' : new jzTimezoneDetector.TimeZone('-04:30','America/Caracas', false),
  12280. '-240,1' : new jzTimezoneDetector.TimeZone('-04:00','America/Halifax', true),
  12281. '-240,0' : new jzTimezoneDetector.TimeZone('-04:00','America/Santo_Domingo', false),
  12282. '-240,1,s' : new jzTimezoneDetector.TimeZone('-04:00','America/Asuncion', true),
  12283. '-210,1' : new jzTimezoneDetector.TimeZone('-03:30','America/St_Johns', true),
  12284. '-180,1' : new jzTimezoneDetector.TimeZone('-03:00','America/Godthab', true),
  12285. '-180,0' : new jzTimezoneDetector.TimeZone('-03:00','America/Argentina/Buenos_Aires', false),
  12286. '-180,1,s' : new jzTimezoneDetector.TimeZone('-03:00','America/Montevideo', true),
  12287. '-120,0' : new jzTimezoneDetector.TimeZone('-02:00','America/Noronha', false),
  12288. '-120,1' : new jzTimezoneDetector.TimeZone('-02:00','Etc/GMT+2', true),
  12289. '-60,1' : new jzTimezoneDetector.TimeZone('-01:00','Atlantic/Azores', true),
  12290. '-60,0' : new jzTimezoneDetector.TimeZone('-01:00','Atlantic/Cape_Verde', false),
  12291. '0,0' : new jzTimezoneDetector.TimeZone('00:00','Etc/UTC', false),
  12292. '0,1' : new jzTimezoneDetector.TimeZone('00:00','Europe/London', true),
  12293. '60,1' : new jzTimezoneDetector.TimeZone('+01:00','Europe/Berlin', true),
  12294. '60,0' : new jzTimezoneDetector.TimeZone('+01:00','Africa/Lagos', false),
  12295. '60,1,s' : new jzTimezoneDetector.TimeZone('+01:00','Africa/Windhoek',true),
  12296. '120,1' : new jzTimezoneDetector.TimeZone('+02:00','Asia/Beirut', true),
  12297. '120,0' : new jzTimezoneDetector.TimeZone('+02:00','Africa/Johannesburg', false),
  12298. '180,1' : new jzTimezoneDetector.TimeZone('+03:00','Europe/Moscow', true),
  12299. '180,0' : new jzTimezoneDetector.TimeZone('+03:00','Asia/Baghdad', false),
  12300. '210,1' : new jzTimezoneDetector.TimeZone('+03:30','Asia/Tehran', true),
  12301. '240,0' : new jzTimezoneDetector.TimeZone('+04:00','Asia/Dubai', false),
  12302. '240,1' : new jzTimezoneDetector.TimeZone('+04:00','Asia/Yerevan', true),
  12303. '270,0' : new jzTimezoneDetector.TimeZone('+04:30','Asia/Kabul', false),
  12304. '300,1' : new jzTimezoneDetector.TimeZone('+05:00','Asia/Yekaterinburg', true),
  12305. '300,0' : new jzTimezoneDetector.TimeZone('+05:00','Asia/Karachi', false),
  12306. '330,0' : new jzTimezoneDetector.TimeZone('+05:30','Asia/Kolkata', false),
  12307. '345,0' : new jzTimezoneDetector.TimeZone('+05:45','Asia/Kathmandu', false),
  12308. '360,0' : new jzTimezoneDetector.TimeZone('+06:00','Asia/Dhaka', false),
  12309. '360,1' : new jzTimezoneDetector.TimeZone('+06:00','Asia/Omsk', true),
  12310. '390,0' : new jzTimezoneDetector.TimeZone('+06:30','Asia/Rangoon', false),
  12311. '420,1' : new jzTimezoneDetector.TimeZone('+07:00','Asia/Krasnoyarsk', true),
  12312. '420,0' : new jzTimezoneDetector.TimeZone('+07:00','Asia/Jakarta', false),
  12313. '480,0' : new jzTimezoneDetector.TimeZone('+08:00','Asia/Shanghai', false),
  12314. '480,1' : new jzTimezoneDetector.TimeZone('+08:00','Asia/Irkutsk', true),
  12315. '525,0' : new jzTimezoneDetector.TimeZone('+08:45','Australia/Eucla', true),
  12316. '525,1,s' : new jzTimezoneDetector.TimeZone('+08:45','Australia/Eucla', true),
  12317. '540,1' : new jzTimezoneDetector.TimeZone('+09:00','Asia/Yakutsk', true),
  12318. '540,0' : new jzTimezoneDetector.TimeZone('+09:00','Asia/Tokyo', false),
  12319. '570,0' : new jzTimezoneDetector.TimeZone('+09:30','Australia/Darwin', false),
  12320. '570,1,s' : new jzTimezoneDetector.TimeZone('+09:30','Australia/Adelaide', true),
  12321. '600,0' : new jzTimezoneDetector.TimeZone('+10:00','Australia/Brisbane', false),
  12322. '600,1' : new jzTimezoneDetector.TimeZone('+10:00','Asia/Vladivostok', true),
  12323. '600,1,s' : new jzTimezoneDetector.TimeZone('+10:00','Australia/Sydney', true),
  12324. '630,1,s' : new jzTimezoneDetector.TimeZone('+10:30','Australia/Lord_Howe', true),
  12325. '660,1' : new jzTimezoneDetector.TimeZone('+11:00','Asia/Kamchatka', true),
  12326. '660,0' : new jzTimezoneDetector.TimeZone('+11:00','Pacific/Noumea', false),
  12327. '690,0' : new jzTimezoneDetector.TimeZone('+11:30','Pacific/Norfolk', false),
  12328. '720,1,s' : new jzTimezoneDetector.TimeZone('+12:00','Pacific/Auckland', true),
  12329. '720,0' : new jzTimezoneDetector.TimeZone('+12:00','Pacific/Tarawa', false),
  12330. '765,1,s' : new jzTimezoneDetector.TimeZone('+12:45','Pacific/Chatham', true),
  12331. '780,0' : new jzTimezoneDetector.TimeZone('+13:00','Pacific/Tongatapu', false),
  12332. '840,0' : new jzTimezoneDetector.TimeZone('+14:00','Pacific/Kiritimati', false)
  12333. };
  12334. /**
  12335. * This object contains information on when daylight savings starts for
  12336. * different timezones.
  12337. *
  12338. * The list is short for a reason. Often we do not have to be very specific
  12339. * to single out the correct timezone. But when we do, this list comes in
  12340. * handy.
  12341. *
  12342. * Each value is a date denoting when daylight savings starts for that timezone.
  12343. */
  12344. jzTimezoneDetector.olson.dst_start_dates = {
  12345. 'America/Denver' : new Date(2011, 2, 13, 3, 0, 0, 0),
  12346. 'America/Mazatlan' : new Date(2011, 3, 3, 3, 0, 0, 0),
  12347. 'America/Chicago' : new Date(2011, 2, 13, 3, 0, 0, 0),
  12348. 'America/Mexico_City' : new Date(2011, 3, 3, 3, 0, 0, 0),
  12349. 'Atlantic/Stanley' : new Date(2011, 8, 4, 7, 0, 0, 0),
  12350. 'America/Asuncion' : new Date(2011, 9, 2, 3, 0, 0, 0),
  12351. 'America/Santiago' : new Date(2011, 9, 9, 3, 0, 0, 0),
  12352. 'America/Campo_Grande' : new Date(2011, 9, 16, 5, 0, 0, 0),
  12353. 'America/Montevideo' : new Date(2011, 9, 2, 3, 0, 0, 0),
  12354. 'America/Sao_Paulo' : new Date(2011, 9, 16, 5, 0, 0, 0),
  12355. 'America/Los_Angeles' : new Date(2011, 2, 13, 8, 0, 0, 0),
  12356. 'America/Santa_Isabel' : new Date(2011, 3, 5, 8, 0, 0, 0),
  12357. 'America/Havana' : new Date(2011, 2, 13, 2, 0, 0, 0),
  12358. 'America/New_York' : new Date(2011, 2, 13, 7, 0, 0, 0),
  12359. 'Asia/Gaza' : new Date(2011, 2, 26, 23, 0, 0, 0),
  12360. 'Asia/Beirut' : new Date(2011, 2, 27, 1, 0, 0, 0),
  12361. 'Europe/Minsk' : new Date(2011, 2, 27, 3, 0, 0, 0),
  12362. 'Europe/Istanbul' : new Date(2011, 2, 27, 7, 0, 0, 0),
  12363. 'Asia/Damascus' : new Date(2011, 3, 1, 2, 0, 0, 0),
  12364. 'Asia/Jerusalem' : new Date(2011, 3, 1, 6, 0, 0, 0),
  12365. 'Africa/Cairo' : new Date(2011, 3, 29, 4, 0, 0, 0),
  12366. 'Asia/Yerevan' : new Date(2011, 2, 27, 4, 0, 0, 0),
  12367. 'Asia/Baku' : new Date(2011, 2, 27, 8, 0, 0, 0),
  12368. 'Pacific/Auckland' : new Date(2011, 8, 26, 7, 0, 0, 0),
  12369. 'Pacific/Fiji' : new Date(2010, 11, 29, 23, 0, 0, 0),
  12370. 'America/Halifax' : new Date(2011, 2, 13, 6, 0, 0, 0),
  12371. 'America/Goose_Bay' : new Date(2011, 2, 13, 2, 1, 0, 0),
  12372. 'America/Miquelon' : new Date(2011, 2, 13, 5, 0, 0, 0),
  12373. 'America/Godthab' : new Date(2011, 2, 27, 1, 0, 0, 0)
  12374. };
  12375. /**
  12376. * The keys in this object are timezones that we know may be ambiguous after
  12377. * a preliminary scan through the olson_tz object.
  12378. *
  12379. * The array of timezones to compare must be in the order that daylight savings
  12380. * starts for the regions.
  12381. */
  12382. jzTimezoneDetector.olson.ambiguity_list = {
  12383. 'America/Denver' : ['America/Denver','America/Mazatlan'],
  12384. 'America/Chicago' : ['America/Chicago','America/Mexico_City'],
  12385. 'America/Asuncion' : ['Atlantic/Stanley', 'America/Asuncion', 'America/Santiago','America/Campo_Grande'],
  12386. 'America/Montevideo' : ['America/Montevideo', 'America/Sao_Paulo'],
  12387. 'Asia/Beirut' : ['Asia/Gaza','Asia/Beirut', 'Europe/Minsk', 'Europe/Istanbul', 'Asia/Damascus', 'Asia/Jerusalem','Africa/Cairo'],
  12388. 'Asia/Yerevan' : ['Asia/Yerevan', 'Asia/Baku'],
  12389. 'Pacific/Auckland' : ['Pacific/Auckland', 'Pacific/Fiji'],
  12390. 'America/Los_Angeles' : ['America/Los_Angeles', 'America/Santa_Isabel'],
  12391. 'America/New_York' : ['America/Havana','America/New_York'],
  12392. 'America/Halifax' : ['America/Goose_Bay','America/Halifax'],
  12393. 'America/Godthab' : ['America/Miquelon', 'America/Godthab']
  12394. };
  12395. /*
  12396. mustache.js — Logic-less templates in JavaScript
  12397. See http://mustache.github.com/ for more info.
  12398. */
  12399. var Mustache = function() {
  12400. var Renderer = function() {};
  12401. Renderer.prototype = {
  12402. otag: "{{",
  12403. ctag: "}}",
  12404. pragmas: {},
  12405. buffer: [],
  12406. pragmas_implemented: {
  12407. "IMPLICIT-ITERATOR": true
  12408. },
  12409. context: {},
  12410. render: function(template, context, partials, in_recursion) {
  12411. // reset buffer & set context
  12412. if(!in_recursion) {
  12413. this.context = context;
  12414. this.buffer = []; // TODO: make this non-lazy
  12415. }
  12416. // fail fast
  12417. if(!this.includes("", template)) {
  12418. if(in_recursion) {
  12419. return template;
  12420. } else {
  12421. this.send(template);
  12422. return;
  12423. }
  12424. }
  12425. template = this.render_pragmas(template);
  12426. var html = this.render_section(template, context, partials);
  12427. if(in_recursion) {
  12428. return this.render_tags(html, context, partials, in_recursion);
  12429. }
  12430. this.render_tags(html, context, partials, in_recursion);
  12431. },
  12432. /*
  12433. Sends parsed lines
  12434. */
  12435. send: function(line) {
  12436. if(line != "") {
  12437. this.buffer.push(line);
  12438. }
  12439. },
  12440. /*
  12441. Looks for %PRAGMAS
  12442. */
  12443. render_pragmas: function(template) {
  12444. // no pragmas
  12445. if(!this.includes("%", template)) {
  12446. return template;
  12447. }
  12448. var that = this;
  12449. var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
  12450. this.ctag);
  12451. return template.replace(regex, function(match, pragma, options) {
  12452. if(!that.pragmas_implemented[pragma]) {
  12453. throw({message:
  12454. "This implementation of mustache doesn't understand the '" +
  12455. pragma + "' pragma"});
  12456. }
  12457. that.pragmas[pragma] = {};
  12458. if(options) {
  12459. var opts = options.split("=");
  12460. that.pragmas[pragma][opts[0]] = opts[1];
  12461. }
  12462. return "";
  12463. // ignore unknown pragmas silently
  12464. });
  12465. },
  12466. /*
  12467. Tries to find a partial in the curent scope and render it
  12468. */
  12469. render_partial: function(name, context, partials) {
  12470. name = this.trim(name);
  12471. if(!partials || partials[name] === undefined) {
  12472. throw({message: "unknown_partial '" + name + "'"});
  12473. }
  12474. if(typeof(context[name]) != "object") {
  12475. return this.render(partials[name], context, partials, true);
  12476. }
  12477. return this.render(partials[name], context[name], partials, true);
  12478. },
  12479. /*
  12480. Renders inverted (^) and normal (#) sections
  12481. */
  12482. render_section: function(template, context, partials) {
  12483. if(!this.includes("#", template) && !this.includes("^", template)) {
  12484. return template;
  12485. }
  12486. var that = this;
  12487. // CSW - Added "+?" so it finds the tighest bound, not the widest
  12488. var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
  12489. "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
  12490. "\\s*", "mg");
  12491. // for each {{#foo}}{{/foo}} section do...
  12492. return template.replace(regex, function(match, type, name, content) {
  12493. var value = that.find(name, context);
  12494. if(type == "^") { // inverted section
  12495. if(!value || that.is_array(value) && value.length === 0) {
  12496. // false or empty list, render it
  12497. return that.render(content, context, partials, true);
  12498. } else {
  12499. return "";
  12500. }
  12501. } else if(type == "#") { // normal section
  12502. if(that.is_array(value)) { // Enumerable, Let's loop!
  12503. return that.map(value, function(row) {
  12504. return that.render(content, that.create_context(row),
  12505. partials, true);
  12506. }).join("");
  12507. } else if(that.is_object(value)) { // Object, Use it as subcontext!
  12508. return that.render(content, that.create_context(value),
  12509. partials, true);
  12510. } else if(typeof value === "function") {
  12511. // higher order section
  12512. return value.call(context, content, function(text) {
  12513. return that.render(text, context, partials, true);
  12514. });
  12515. } else if(value) { // boolean section
  12516. return that.render(content, context, partials, true);
  12517. } else {
  12518. return "";
  12519. }
  12520. }
  12521. });
  12522. },
  12523. /*
  12524. Replace {{foo}} and friends with values from our view
  12525. */
  12526. render_tags: function(template, context, partials, in_recursion) {
  12527. // tit for tat
  12528. var that = this;
  12529. var new_regex = function() {
  12530. return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
  12531. that.ctag + "+", "g");
  12532. };
  12533. var regex = new_regex();
  12534. var tag_replace_callback = function(match, operator, name) {
  12535. switch(operator) {
  12536. case "!": // ignore comments
  12537. return "";
  12538. case "=": // set new delimiters, rebuild the replace regexp
  12539. that.set_delimiters(name);
  12540. regex = new_regex();
  12541. return "";
  12542. case ">": // render partial
  12543. return that.render_partial(name, context, partials);
  12544. case "{": // the triple mustache is unescaped
  12545. return that.find(name, context);
  12546. default: // escape the value
  12547. return that.escape(that.find(name, context));
  12548. }
  12549. };
  12550. var lines = template.split("\n");
  12551. for(var i = 0; i < lines.length; i++) {
  12552. lines[i] = lines[i].replace(regex, tag_replace_callback, this);
  12553. if(!in_recursion) {
  12554. this.send(lines[i]);
  12555. }
  12556. }
  12557. if(in_recursion) {
  12558. return lines.join("\n");
  12559. }
  12560. },
  12561. set_delimiters: function(delimiters) {
  12562. var dels = delimiters.split(" ");
  12563. this.otag = this.escape_regex(dels[0]);
  12564. this.ctag = this.escape_regex(dels[1]);
  12565. },
  12566. escape_regex: function(text) {
  12567. // thank you Simon Willison
  12568. if(!arguments.callee.sRE) {
  12569. var specials = [
  12570. '/', '.', '*', '+', '?', '|',
  12571. '(', ')', '[', ']', '{', '}', '\\'
  12572. ];
  12573. arguments.callee.sRE = new RegExp(
  12574. '(\\' + specials.join('|\\') + ')', 'g'
  12575. );
  12576. }
  12577. return text.replace(arguments.callee.sRE, '\\$1');
  12578. },
  12579. /*
  12580. find `name` in current `context`. That is find me a value
  12581. from the view object
  12582. */
  12583. find: function(name, context) {
  12584. name = this.trim(name);
  12585. // Checks whether a value is thruthy or false or 0
  12586. function is_kinda_truthy(bool) {
  12587. return bool === false || bool === 0 || bool;
  12588. }
  12589. var value = context;
  12590. var path = name.split(/\./);
  12591. for(var i = 0; i < path.length; i++) {
  12592. name = path[i];
  12593. if(value && is_kinda_truthy(value[name])) {
  12594. value = value[name];
  12595. } else if(i == 0 && is_kinda_truthy(this.context[name])) {
  12596. value = this.context[name];
  12597. } else {
  12598. value = undefined;
  12599. }
  12600. }
  12601. if(typeof value === "function") {
  12602. return value.apply(context);
  12603. }
  12604. if(value !== undefined) {
  12605. return value;
  12606. }
  12607. // silently ignore unkown variables
  12608. return "";
  12609. },
  12610. // Utility methods
  12611. /* includes tag */
  12612. includes: function(needle, haystack) {
  12613. return haystack.indexOf(this.otag + needle) != -1;
  12614. },
  12615. /*
  12616. Does away with nasty characters
  12617. */
  12618. escape: function(s) {
  12619. s = String(s === null ? "" : s);
  12620. return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
  12621. switch(s) {
  12622. case "&": return "&amp;";
  12623. case "\\": return "\\\\";
  12624. case '"': return '&quot;';
  12625. case "'": return '&#39;';
  12626. case "<": return "&lt;";
  12627. case ">": return "&gt;";
  12628. default: return s;
  12629. }
  12630. });
  12631. },
  12632. // by @langalex, support for arrays of strings
  12633. create_context: function(_context) {
  12634. if(this.is_object(_context)) {
  12635. return _context;
  12636. } else {
  12637. var iterator = ".";
  12638. if(this.pragmas["IMPLICIT-ITERATOR"]) {
  12639. iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
  12640. }
  12641. var ctx = {};
  12642. ctx[iterator] = _context;
  12643. return ctx;
  12644. }
  12645. },
  12646. is_object: function(a) {
  12647. return a && typeof a == "object";
  12648. },
  12649. is_array: function(a) {
  12650. return Object.prototype.toString.call(a) === '[object Array]';
  12651. },
  12652. /*
  12653. Gets rid of leading and trailing whitespace
  12654. */
  12655. trim: function(s) {
  12656. return s.replace(/^\s*|\s*$/g, "");
  12657. },
  12658. /*
  12659. Why, why, why? Because IE. Cry, cry cry.
  12660. */
  12661. map: function(array, fn) {
  12662. if (typeof array.map == "function") {
  12663. return array.map(fn);
  12664. } else {
  12665. var r = [];
  12666. var l = array.length;
  12667. for(var i = 0; i < l; i++) {
  12668. r.push(fn(array[i]));
  12669. }
  12670. return r;
  12671. }
  12672. }
  12673. };
  12674. return({
  12675. name: "mustache.js",
  12676. version: "0.3.1-dev",
  12677. /*
  12678. Turns a template and view into HTML
  12679. */
  12680. to_html: function(template, view, partials, send_fun) {
  12681. var renderer = new Renderer();
  12682. if(send_fun) {
  12683. renderer.send = send_fun;
  12684. }
  12685. renderer.render(template, view, partials);
  12686. if(!send_fun) {
  12687. return renderer.buffer.join("\n");
  12688. }
  12689. }
  12690. });
  12691. }();
  12692. /*
  12693. * More info at: http://phpjs.org
  12694. *
  12695. * This is version: 3.24
  12696. * php.js is copyright 2011 Kevin van Zonneveld.
  12697. *
  12698. * Portions copyright Brett Zamir (http://brett-zamir.me), Kevin van Zonneveld
  12699. * (http://kevin.vanzonneveld.net), Onno Marsman, Theriault, Michael White
  12700. * (http://getsprink.com), Waldo Malqui Silva, Paulo Freitas, Jonas Raoni
  12701. * Soares Silva (http://www.jsfromhell.com), Jack, Philip Peterson, Ates Goral
  12702. * (http://magnetiq.com), Legaev Andrey, Ratheous, Alex, Martijn Wieringa,
  12703. * Nate, lmeyrick (https://sourceforge.net/projects/bcmath-js/), Enrique
  12704. * Gonzalez, Philippe Baumann, Rafał Kukawski (http://blog.kukawski.pl),
  12705. * Webtoolkit.info (http://www.webtoolkit.info/), Ole Vrijenhoek, Ash Searle
  12706. * (http://hexmen.com/blog/), travc, Carlos R. L. Rodrigues
  12707. * (http://www.jsfromhell.com), Jani Hartikainen, stag019, GeekFG
  12708. * (http://geekfg.blogspot.com), WebDevHobo (http://webdevhobo.blogspot.com/),
  12709. * Erkekjetter, pilus, Rafał Kukawski (http://blog.kukawski.pl/), Johnny Mast
  12710. * (http://www.phpvrouwen.nl), T.Wild,
  12711. * http://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hex-in-javascript,
  12712. * d3x, Michael Grier, Andrea Giammarchi (http://webreflection.blogspot.com),
  12713. * marrtins, Mailfaker (http://www.weedem.fr/), Steve Hilder, gettimeofday,
  12714. * mdsjack (http://www.mdsjack.bo.it), felix, majak, Steven Levithan
  12715. * (http://blog.stevenlevithan.com), Mirek Slugen, Oleg Eremeev, Felix
  12716. * Geisendoerfer (http://www.debuggable.com/felix), Martin
  12717. * (http://www.erlenwiese.de/), gorthaur, Lars Fischer, Joris, AJ, Paul Smith,
  12718. * Tim de Koning (http://www.kingsquare.nl), KELAN, Josh Fraser
  12719. * (http://onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/),
  12720. * Chris, Marc Palau, Kevin van Zonneveld (http://kevin.vanzonneveld.net/),
  12721. * Arpad Ray (mailto:arpad@php.net), Breaking Par Consulting Inc
  12722. * (http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CFB006C45F7),
  12723. * Nathan, Karol Kowalski, David, Dreamer, Diplom@t (http://difane.com/), Caio
  12724. * Ariede (http://caioariede.com), Robin, Imgen Tata (http://www.myipdf.com/),
  12725. * Pellentesque Malesuada, saulius, Aman Gupta, Sakimori, Tyler Akins
  12726. * (http://rumkin.com), Thunder.m, Public Domain
  12727. * (http://www.json.org/json2.js), Michael White, Kankrelune
  12728. * (http://www.webfaktory.info/), Alfonso Jimenez
  12729. * (http://www.alfonsojimenez.com), Frank Forte, vlado houba, Marco, Billy,
  12730. * David James, madipta, noname, sankai, class_exists, Jalal Berrami, ger,
  12731. * Itsacon (http://www.itsacon.net/), Scott Cariss, nobbler, Arno, Denny
  12732. * Wardhana, ReverseSyntax, Mateusz "loonquawl" Zalega, Slawomir Kaniecki,
  12733. * Francois, Fox, mktime, Douglas Crockford (http://javascript.crockford.com),
  12734. * john (http://www.jd-tech.net), Oskar Larsson Högfeldt
  12735. * (http://oskar-lh.name/), marc andreu, Nick Kolosov (http://sammy.ru), date,
  12736. * Marc Jansen, Steve Clay, Olivier Louvignes (http://mg-crea.com/), Soren
  12737. * Hansen, merabi, Subhasis Deb, josh, T0bsn, Tim Wiel, Brad Touesnard, MeEtc
  12738. * (http://yass.meetcweb.com), Peter-Paul Koch
  12739. * (http://www.quirksmode.org/js/beat.html), Pyerre, Jon Hohle, duncan, Bayron
  12740. * Guevara, Adam Wallner (http://web2.bitbaro.hu/), paulo kuong, Gilbert,
  12741. * Lincoln Ramsay, Thiago Mata (http://thiagomata.blog.com), Linuxworld,
  12742. * lmeyrick (https://sourceforge.net/projects/bcmath-js/this.), djmix, Bryan
  12743. * Elliott, David Randall, Sanjoy Roy, jmweb, Francesco, Stoyan Kyosev
  12744. * (http://www.svest.org/), J A R, kenneth, T. Wild, Ole Vrijenhoek
  12745. * (http://www.nervous.nl/), Raphael (Ao RUDLER), Shingo, LH, JB, nord_ua, jd,
  12746. * JT, Thomas Beaucourt (http://www.webapp.fr), Ozh, XoraX
  12747. * (http://www.xorax.info), EdorFaus, Eugene Bulkin (http://doubleaw.com/),
  12748. * Der Simon (http://innerdom.sourceforge.net/), 0m3r, echo is bad,
  12749. * FremyCompany, stensi, Kristof Coomans (SCK-CEN Belgian Nucleair Research
  12750. * Centre), Devan Penner-Woelk, Pierre-Luc Paour, Martin Pool, Brant Messenger
  12751. * (http://www.brantmessenger.com/), Kirk Strobeck, Saulo Vallory, Christoph,
  12752. * Wagner B. Soares, Artur Tchernychev, Valentina De Rosa, Jason Wong
  12753. * (http://carrot.org/), Daniel Esteban, strftime, Rick Waldron, Mick@el,
  12754. * Anton Ongson, Bjorn Roesbeke (http://www.bjornroesbeke.be/), Simon Willison
  12755. * (http://simonwillison.net), Gabriel Paderni, Philipp Lenssen, Marco van
  12756. * Oort, Bug?, Blues (http://tech.bluesmoon.info/), Tomasz Wesolowski, rezna,
  12757. * Eric Nagel, Evertjan Garretsen, Luke Godfrey, Pul, Bobby Drake, uestla,
  12758. * Alan C, Ulrich, Zahlii, Yves Sucaet, sowberry, Norman "zEh" Fuchs, hitwork,
  12759. * johnrembo, Brian Tafoya (http://www.premasolutions.com/), Nick Callen,
  12760. * Steven Levithan (stevenlevithan.com), ejsanders, Scott Baker, Philippe
  12761. * Jausions (http://pear.php.net/user/jausions), Aidan Lister
  12762. * (http://aidanlister.com/), Rob, e-mike, HKM, ChaosNo1, metjay, strcasecmp,
  12763. * strcmp, Taras Bogach, jpfle, Alexander Ermolaev
  12764. * (http://snippets.dzone.com/user/AlexanderErmolaev), DxGx, kilops, Orlando,
  12765. * dptr1988, Le Torbi, James (http://www.james-bell.co.uk/), Pedro Tainha
  12766. * (http://www.pedrotainha.com), James, penutbutterjelly, Arnout Kazemier
  12767. * (http://www.3rd-Eden.com), 3D-GRAF, daniel airton wermann
  12768. * (http://wermann.com.br), jakes, Yannoo, FGFEmperor, gabriel paderni, Atli
  12769. * Þór, Maximusya, Diogo Resende, Rival, Howard Yeend, Allan Jensen
  12770. * (http://www.winternet.no), davook, Benjamin Lupton, baris ozdil, Greg
  12771. * Frazier, Manish, Matt Bradley, Cord, fearphage
  12772. * (http://http/my.opera.com/fearphage/), Matteo, Victor, taith, Tim de
  12773. * Koning, Ryan W Tenney (http://ryan.10e.us), Tod Gentille, Alexander M
  12774. * Beedie, Riddler (http://www.frontierwebdev.com/), Luis Salazar
  12775. * (http://www.freaky-media.com/), Rafał Kukawski, T.J. Leahy, Luke Smith
  12776. * (http://lucassmith.name), Kheang Hok Chin (http://www.distantia.ca/),
  12777. * Russell Walker (http://www.nbill.co.uk/), Jamie Beck
  12778. * (http://www.terabit.ca/), Garagoth, Andrej Pavlovic, Dino, Le Torbi
  12779. * (http://www.letorbi.de/), Ben (http://benblume.co.uk/), DtTvB
  12780. * (http://dt.in.th/2008-09-16.string-length-in-bytes.html), Michael, Chris
  12781. * McMacken, setcookie, YUI Library:
  12782. * http://developer.yahoo.com/yui/docs/YAHOO.util.DateLocale.html, Andreas,
  12783. * Blues at http://hacks.bluesmoon.info/strftime/strftime.js, rem, Josep Sanz
  12784. * (http://www.ws3.es/), Cagri Ekin, Lorenzo Pisani, incidence, Amirouche, Jay
  12785. * Klehr, Amir Habibi (http://www.residence-mixte.com/), Tony, booeyOH, meo,
  12786. * William, Greenseed, Yen-Wei Liu, Ben Bryan, Leslie Hoare, mk.keck
  12787. *
  12788. * Dual licensed under the MIT (MIT-LICENSE.txt)
  12789. * and GPL (GPL-LICENSE.txt) licenses.
  12790. *
  12791. * Permission is hereby granted, free of charge, to any person obtaining a
  12792. * copy of this software and associated documentation files (the
  12793. * "Software"), to deal in the Software without restriction, including
  12794. * without limitation the rights to use, copy, modify, merge, publish,
  12795. * distribute, sublicense, and/or sell copies of the Software, and to
  12796. * permit persons to whom the Software is furnished to do so, subject to
  12797. * the following conditions:
  12798. *
  12799. * The above copyright notice and this permission notice shall be included
  12800. * in all copies or substantial portions of the Software.
  12801. *
  12802. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  12803. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  12804. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  12805. * IN NO EVENT SHALL KEVIN VAN ZONNEVELD BE LIABLE FOR ANY CLAIM, DAMAGES
  12806. * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  12807. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  12808. * OTHER DEALINGS IN THE SOFTWARE.
  12809. */
  12810. // jslint.com configuration options. See: http://wiki.github.com/kvz/phpjs/jslint-options
  12811. /* global window */
  12812. /* jslint adsafe: false, bitwise: false, browser: false, cap: false, css: false, debug: false, devel: false, eqeqeq: true, evil: false, forin: false, fragment: false, immed: true, indent: 4, laxbreak: false, maxerr: 100, maxlen: 80, newcap: true, nomen: false, on: true, onevar: false, passfail: false, plusplus: false, regexp: false, rhino: false, safe: false, sidebar: false, strict: false, sub: false, undef: true, white: false, widget: false */
  12813. // Our idea with CommonJS is that you can do the following:
  12814. // var php = require('php');
  12815. // php.md5('test');
  12816. var php = {};
  12817. php.ini_set = function (varname, newvalue) {
  12818. // http://kevin.vanzonneveld.net
  12819. // + original by: Brett Zamir (http://brett-zamir.me)
  12820. // % note 1: This will not set a global_value or access level for the ini item
  12821. // * example 1: ini_set('date.timezone', 'America/Chicago');
  12822. // * returns 1: 'Asia/Hong_Kong'
  12823. var oldval = '',
  12824. that = this;
  12825. this.php_js = this.php_js || {};
  12826. this.php_js.ini = this.php_js.ini || {};
  12827. this.php_js.ini[varname] = this.php_js.ini[varname] || {};
  12828. oldval = this.php_js.ini[varname].local_value;
  12829. var _setArr = function (oldval) { // Although these are set individually, they are all accumulated
  12830. if (typeof oldval === 'undefined') {
  12831. that.php_js.ini[varname].local_value = [];
  12832. }
  12833. that.php_js.ini[varname].local_value.push(newvalue);
  12834. };
  12835. switch (varname) {
  12836. case 'extension':
  12837. if (typeof this.dl === 'function') {
  12838. this.dl(newvalue); // This function is only experimental in php.js
  12839. }
  12840. _setArr(oldval, newvalue);
  12841. break;
  12842. default:
  12843. this.php_js.ini[varname].local_value = newvalue;
  12844. break;
  12845. }
  12846. return oldval;
  12847. };
  12848. php.ini_get = function (varname) {
  12849. // http://kevin.vanzonneveld.net
  12850. // + original by: Brett Zamir (http://brett-zamir.me)
  12851. // % note 1: The ini values must be set by ini_set or manually within an ini file
  12852. // * example 1: ini_get('date.timezone');
  12853. // * returns 1: 'Asia/Hong_Kong'
  12854. if (this.php_js && this.php_js.ini && this.php_js.ini[varname] && this.php_js.ini[varname].local_value !== undefined) {
  12855. if (this.php_js.ini[varname].local_value === null) {
  12856. return '';
  12857. }
  12858. return this.php_js.ini[varname].local_value;
  12859. }
  12860. return '';
  12861. }
  12862. php.ctype_digit = function (text) {
  12863. // http://kevin.vanzonneveld.net
  12864. // + original by: Brett Zamir (http://brett-zamir.me)
  12865. // - depends on: setlocale
  12866. // * example 1: ctype_digit('150');
  12867. // * returns 1: true
  12868. if (typeof text !== 'string') {
  12869. return false;
  12870. }
  12871. // BEGIN REDUNDANT
  12872. this.setlocale('LC_ALL', 0); // ensure setup of localization variables takes place
  12873. // END REDUNDANT
  12874. return text.search(this.php_js.locales[this.php_js.localeCategories.LC_CTYPE].LC_CTYPE.dg) !== -1;
  12875. };
  12876. php.gmmktime = function () {
  12877. // http://kevin.vanzonneveld.net
  12878. // + original by: Brett Zamir (http://brett-zamir.me)
  12879. // + derived from: mktime
  12880. // * example 1: gmmktime(14, 10, 2, 2, 1, 2008);
  12881. // * returns 1: 1201875002
  12882. // * example 2: gmmktime(0, 0, -1, 1, 1, 1970);
  12883. // * returns 2: -1
  12884. var d = new Date(),
  12885. r = arguments,
  12886. i = 0,
  12887. e = ['Hours', 'Minutes', 'Seconds', 'Month', 'Date', 'FullYear'];
  12888. for (i = 0; i < e.length; i++) {
  12889. if (typeof r[i] === 'undefined') {
  12890. r[i] = d['getUTC' + e[i]]();
  12891. r[i] += (i === 3); // +1 to fix JS months.
  12892. } else {
  12893. r[i] = parseInt(r[i], 10);
  12894. if (isNaN(r[i])) {
  12895. return false;
  12896. }
  12897. }
  12898. }
  12899. // Map years 0-69 to 2000-2069 and years 70-100 to 1970-2000.
  12900. r[5] += (r[5] >= 0 ? (r[5] <= 69 ? 2e3 : (r[5] <= 100 ? 1900 : 0)) : 0);
  12901. // Set year, month (-1 to fix JS months), and date.
  12902. // !This must come before the call to setHours!
  12903. d.setUTCFullYear(r[5], r[3] - 1, r[4]);
  12904. // Set hours, minutes, and seconds.
  12905. d.setUTCHours(r[0], r[1], r[2]);
  12906. // Divide milliseconds by 1000 to return seconds and drop decimal.
  12907. // Add 1 second if negative or it'll be off from PHP by 1 second.
  12908. return (d.getTime() / 1e3 >> 0) - (d.getTime() < 0);
  12909. };
  12910. php.getdate = function (timestamp) {
  12911. // http://kevin.vanzonneveld.net
  12912. // + original by: Paulo Freitas
  12913. // + input by: Alex
  12914. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  12915. // * example 1: getdate(1055901520);
  12916. // * returns 1: {'seconds': 40, 'minutes': 58, 'hours': 21, 'mday': 17, 'wday': 2, 'mon': 6, 'year': 2003, 'yday': 167, 'weekday': 'Tuesday', 'month': 'June', '0': 1055901520}
  12917. var _w = ['Sun', 'Mon', 'Tues', 'Wednes', 'Thurs', 'Fri', 'Satur'];
  12918. var _m = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
  12919. var d = ((typeof(timestamp) == 'undefined') ? new Date() : // Not provided
  12920. (typeof(timestamp) == 'object') ? new Date(timestamp) : // Javascript Date()
  12921. new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
  12922. );
  12923. var w = d.getDay();
  12924. var m = d.getMonth();
  12925. var y = d.getFullYear();
  12926. var r = {};
  12927. r.seconds = d.getSeconds();
  12928. r.minutes = d.getMinutes();
  12929. r.hours = d.getHours();
  12930. r.mday = d.getDate();
  12931. r.wday = w;
  12932. r.mon = m + 1;
  12933. r.year = y;
  12934. r.yday = Math.floor((d - (new Date(y, 0, 1))) / 86400000);
  12935. r.weekday = _w[w] + 'day';
  12936. r.month = _m[m];
  12937. r['0'] = parseInt(d.getTime() / 1000, 10);
  12938. return r;
  12939. };
  12940. php.checkdate = function (m, d, y) {
  12941. // Returns true(1) if it is a valid date in gregorian calendar
  12942. //
  12943. // version: 1103.1210
  12944. // discuss at: http://phpjs.org/functions/checkdate
  12945. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  12946. // + improved by: Pyerre
  12947. // + improved by: Theriault
  12948. // * example 1: checkdate(12, 31, 2000);
  12949. // * returns 1: true
  12950. // * example 2: checkdate(2, 29, 2001);
  12951. // * returns 2: false
  12952. // * example 3: checkdate(3, 31, 2008);
  12953. // * returns 3: true
  12954. // * example 4: checkdate(1, 390, 2000);
  12955. // * returns 4: false
  12956. return m > 0 && m < 13 && y > 0 && y < 32768 && d > 0 && d <= (new Date(y, m, 0)).getDate();
  12957. };
  12958. php.gmdate = function (format, timestamp) {
  12959. // Format a GMT date/time
  12960. //
  12961. // version: 1103.1210
  12962. // discuss at: http://phpjs.org/functions/gmdate
  12963. // + original by: Brett Zamir (http://brett-zamir.me)
  12964. // + input by: Alex
  12965. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  12966. // - depends on: date
  12967. // * example 1: gmdate('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400); // Return will depend on your timezone
  12968. // * returns 1: '07:09:40 m is month'
  12969. var dt = ((typeof(timestamp) == 'undefined') ? new Date() : // Not provided
  12970. (typeof(timestamp) == 'object') ? new Date(timestamp) : // Javascript Date()
  12971. new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
  12972. );
  12973. timestamp = Date.parse(dt.toUTCString().slice(0, -4)) / 1000;
  12974. return this.date(format, timestamp);
  12975. };
  12976. php.mt_rand = function (min, max) {
  12977. // Returns a random number from Mersenne Twister
  12978. //
  12979. // version: 1103.1210
  12980. // discuss at: http://phpjs.org/functions/mt_rand
  12981. // + original by: Onno Marsman
  12982. // * example 1: mt_rand(1, 1);
  12983. // * returns 1: 1
  12984. var argc = arguments.length;
  12985. if (argc === 0) {
  12986. min = 0;
  12987. max = 2147483647;
  12988. } else if (argc === 1) {
  12989. throw new Error('Warning: mt_rand() expects exactly 2 parameters, 1 given');
  12990. }
  12991. return Math.floor(Math.random() * (max - min + 1)) + min;
  12992. };
  12993. php.abs = function (mixed_number) {
  12994. // Return the absolute value of the number
  12995. //
  12996. // version: 1103.1210
  12997. // discuss at: http://phpjs.org/functions/abs
  12998. // + original by: Waldo Malqui Silva
  12999. // + improved by: Karol Kowalski
  13000. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13001. // + improved by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  13002. // * example 1: \php.abs(4.2);
  13003. // * returns 1: 4.2
  13004. // * example 2: \php.abs(-4.2);
  13005. // * returns 2: 4.2
  13006. // * example 3: \php.abs(-5);
  13007. // * returns 3: 5
  13008. // * example 4: \php.abs('_argos');
  13009. // * returns 4: 0
  13010. return Math.abs(mixed_number) || 0;
  13011. };
  13012. php.addcslashes = function (str, charlist) {
  13013. // Escapes all chars mentioned in charlist with backslash. It creates octal representations if asked to backslash characters with 8th bit set or with ASCII<32 (except '\n', '\r', '\t' etc...)
  13014. //
  13015. // version: 1103.1210
  13016. // discuss at: http://phpjs.org/functions/addcslashes
  13017. // + original by: Brett Zamir (http://brett-zamir.me)
  13018. // % note 1: We show double backslashes in the return value example code below because a JavaScript string will not
  13019. // % note 1: render them as backslashes otherwise
  13020. // * example 1: \php.addcslashes('foo[ ]', 'A..z'); // Escape all ASCII within capital A to lower z range, including square brackets
  13021. // * returns 1: "\\f\\o\\o\\[ \\]"
  13022. // * example 2: \php.addcslashes("zoo['.']", 'z..A'); // Only escape z, period, and A here since not a lower-to-higher range
  13023. // * returns 2: "\\zoo['\\.']"
  13024. // * example 3: \php.addcslashes("@a\u0000\u0010\u00A9", "\0..\37!@\177..\377") == '\\@a\\000\\020\\302\\251'); // Escape as octals those specified and less than 32 (0x20) or greater than 126 (0x7E), but not otherwise
  13025. // * returns 3: true
  13026. // * example 4: \php.addcslashes("\u0020\u007E", "\40..\175") == '\\ ~'); // Those between 32 (0x20 or 040) and 126 (0x7E or 0176) decimal value will be backslashed if specified (not octalized)
  13027. // * returns 4: true
  13028. // * example 5: \php.addcslashes("\r\u0007\n", '\0..\37'); // Recognize C escape sequences if specified
  13029. // * returns 5: "\\r\\a\\n"
  13030. // * example 6: \php.addcslashes("\r\u0007\n", '\0'); // Do not recognize C escape sequences if not specified
  13031. // * returns 7: "\r\u0007\n"
  13032. var target = '',
  13033. chrs = [],
  13034. i = 0,
  13035. j = 0,
  13036. c = '',
  13037. next = '',
  13038. rangeBegin = '',
  13039. rangeEnd = '',
  13040. chr = '',
  13041. begin = 0,
  13042. end = 0,
  13043. octalLength = 0,
  13044. postOctalPos = 0,
  13045. cca = 0,
  13046. escHexGrp = [],
  13047. encoded = '',
  13048. percentHex = /%([\dA-Fa-f]+)/g;
  13049. var _pad = function (n, c) {
  13050. if ((n = n + "").length < c) {
  13051. return new Array(++c - n.length).join("0") + n;
  13052. } else {
  13053. return n;
  13054. }
  13055. };
  13056. for (i = 0; i < charlist.length; i++) {
  13057. c = charlist.charAt(i);
  13058. next = charlist.charAt(i + 1);
  13059. if (c === '\\' && next && (/\d/).test(next)) { // Octal
  13060. rangeBegin = charlist.slice(i + 1).match(/^\d+/)[0];
  13061. octalLength = rangeBegin.length;
  13062. postOctalPos = i + octalLength + 1;
  13063. if (charlist.charAt(postOctalPos) + charlist.charAt(postOctalPos + 1) === '..') { // Octal begins range
  13064. begin = rangeBegin.charCodeAt(0);
  13065. if ((/\\\d/).test(charlist.charAt(postOctalPos + 2) + charlist.charAt(postOctalPos + 3))) { // Range ends with octal
  13066. rangeEnd = charlist.slice(postOctalPos + 3).match(/^\d+/)[0];
  13067. i += 1; // Skip range end backslash
  13068. } else if (charlist.charAt(postOctalPos + 2)) { // Range ends with character
  13069. rangeEnd = charlist.charAt(postOctalPos + 2);
  13070. } else {
  13071. throw 'Range with no end point';
  13072. }
  13073. end = rangeEnd.charCodeAt(0);
  13074. if (end > begin) { // Treat as a range
  13075. for (j = begin; j <= end; j++) {
  13076. chrs.push(String.fromCharCode(j));
  13077. }
  13078. } else { // Supposed to treat period, begin and end as individual characters only, not a range
  13079. chrs.push('.', rangeBegin, rangeEnd);
  13080. }
  13081. i += rangeEnd.length + 2; // Skip dots and range end (already skipped range end backslash if present)
  13082. } else { // Octal is by itself
  13083. chr = String.fromCharCode(parseInt(rangeBegin, 8));
  13084. chrs.push(chr);
  13085. }
  13086. i += octalLength; // Skip range begin
  13087. } else if (next + charlist.charAt(i + 2) === '..') { // Character begins range
  13088. rangeBegin = c;
  13089. begin = rangeBegin.charCodeAt(0);
  13090. if ((/\\\d/).test(charlist.charAt(i + 3) + charlist.charAt(i + 4))) { // Range ends with octal
  13091. rangeEnd = charlist.slice(i + 4).match(/^\d+/)[0];
  13092. i += 1; // Skip range end backslash
  13093. } else if (charlist.charAt(i + 3)) { // Range ends with character
  13094. rangeEnd = charlist.charAt(i + 3);
  13095. } else {
  13096. throw 'Range with no end point';
  13097. }
  13098. end = rangeEnd.charCodeAt(0);
  13099. if (end > begin) { // Treat as a range
  13100. for (j = begin; j <= end; j++) {
  13101. chrs.push(String.fromCharCode(j));
  13102. }
  13103. } else { // Supposed to treat period, begin and end as individual characters only, not a range
  13104. chrs.push('.', rangeBegin, rangeEnd);
  13105. }
  13106. i += rangeEnd.length + 2; // Skip dots and range end (already skipped range end backslash if present)
  13107. } else { // Character is by itself
  13108. chrs.push(c);
  13109. }
  13110. }
  13111. for (i = 0; i < str.length; i++) {
  13112. c = str.charAt(i);
  13113. if (chrs.indexOf(c) !== -1) {
  13114. target += '\\';
  13115. cca = c.charCodeAt(0);
  13116. if (cca < 32 || cca > 126) { // Needs special escaping
  13117. switch (c) {
  13118. case '\n':
  13119. target += 'n';
  13120. break;
  13121. case '\t':
  13122. target += 't';
  13123. break;
  13124. case '\u000D':
  13125. target += 'r';
  13126. break;
  13127. case '\u0007':
  13128. target += 'a';
  13129. break;
  13130. case '\v':
  13131. target += 'v';
  13132. break;
  13133. case '\b':
  13134. target += 'b';
  13135. break;
  13136. case '\f':
  13137. target += 'f';
  13138. break;
  13139. default:
  13140. //target += _pad(cca.toString(8), 3);break; // Sufficient for UTF-16
  13141. encoded = encodeURIComponent(c);
  13142. // 3-length-padded UTF-8 octets
  13143. if ((escHexGrp = percentHex.exec(encoded)) !== null) {
  13144. target += _pad(parseInt(escHexGrp[1], 16).toString(8), 3); // already added a slash above
  13145. }
  13146. while ((escHexGrp = percentHex.exec(encoded)) !== null) {
  13147. target += '\\' + _pad(parseInt(escHexGrp[1], 16).toString(8), 3);
  13148. }
  13149. break;
  13150. }
  13151. } else { // Perform regular backslashed escaping
  13152. target += c;
  13153. }
  13154. } else { // Just add the character unescaped
  13155. target += c;
  13156. }
  13157. }
  13158. return target;
  13159. };
  13160. php.addslashes = function (str) {
  13161. // Escapes single quote, double quotes and backslash characters in a string with backslashes
  13162. //
  13163. // version: 1103.1210
  13164. // discuss at: http://phpjs.org/functions/addslashes
  13165. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13166. // + improved by: Ates Goral (http://magnetiq.com)
  13167. // + improved by: marrtins
  13168. // + improved by: Nate
  13169. // + improved by: Onno Marsman
  13170. // + input by: Denny Wardhana
  13171. // + improved by: Brett Zamir (http://brett-zamir.me)
  13172. // + improved by: Oskar Larsson Högfeldt (http://oskar-lh.name/)
  13173. // * example 1: \php.addslashes("kevin's birthday");
  13174. // * returns 1: 'kevin\'s birthday'
  13175. return (str + '').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0');
  13176. };
  13177. php.array_chunk = function (input, size) {
  13178. // Split array into chunks
  13179. //
  13180. // version: 1103.1210
  13181. // discuss at: http://phpjs.org/functions/array_chunk
  13182. // + original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
  13183. // * example 1: \php.array_chunk(['Kevin', 'van', 'Zonneveld'], 2);
  13184. // * returns 1: {0 : {0: 'Kevin', 1: 'van'} , 1 : {0: 'Zonneveld'}}
  13185. for (var x, i = 0, c = -1, l = input.length, n = []; i < l; i++) {
  13186. (x = i % size) ? n[c][x] = input[i] : n[++c] = [input[i]];
  13187. }
  13188. return n;
  13189. };
  13190. php.array_combine = function (keys, values) {
  13191. // Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values
  13192. //
  13193. // version: 1103.1210
  13194. // discuss at: http://phpjs.org/functions/array_combine
  13195. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13196. // + improved by: Brett Zamir (http://brett-zamir.me)
  13197. // * example 1: \php.array_combine([0,1,2], ['kevin','van','zonneveld']);
  13198. // * returns 1: {0: 'kevin', 1: 'van', 2: 'zonneveld'}
  13199. var new_array = {},
  13200. keycount = keys && keys.length,
  13201. i = 0;
  13202. // input sanitation
  13203. if (typeof keys !== 'object' || typeof values !== 'object' || // Only accept arrays or array-like objects
  13204. typeof keycount !== 'number' || typeof values.length !== 'number' || !keycount) { // Require arrays to have a count
  13205. return false;
  13206. }
  13207. // number of elements does not match
  13208. if (keycount != values.length) {
  13209. return false;
  13210. }
  13211. for (i = 0; i < keycount; i++) {
  13212. new_array[keys[i]] = values[i];
  13213. }
  13214. return new_array;
  13215. };
  13216. php.array_diff = function () {
  13217. // Returns the entries of arr1 that have values which are not present in any of the others arguments.
  13218. //
  13219. // version: 1103.1210
  13220. // discuss at: http://phpjs.org/functions/array_diff
  13221. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13222. // + improved by: Sanjoy Roy
  13223. // + revised by: Brett Zamir (http://brett-zamir.me)
  13224. // * example 1: \php.array_diff(['Kevin', 'van', 'Zonneveld'], ['van', 'Zonneveld']);
  13225. // * returns 1: {0:'Kevin'}
  13226. var arr1 = arguments[0],
  13227. retArr = {};
  13228. var k1 = '',
  13229. i = 1,
  13230. k = '',
  13231. arr = {};
  13232. arr1keys: for (k1 in arr1) {
  13233. for (i = 1; i < arguments.length; i++) {
  13234. arr = arguments[i];
  13235. for (k in arr) {
  13236. if (arr[k] === arr1[k1]) {
  13237. // If it reaches here, it was found in at least one array, so try next value
  13238. continue arr1keys;
  13239. }
  13240. }
  13241. retArr[k1] = arr1[k1];
  13242. }
  13243. }
  13244. return retArr;
  13245. };
  13246. php.array_fill = function (start_index, num, mixed_val) {
  13247. // Create an array containing num elements starting with index start_key each initialized to val
  13248. //
  13249. // version: 1103.1210
  13250. // discuss at: http://phpjs.org/functions/array_fill
  13251. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13252. // + improved by: Waldo Malqui Silva
  13253. // * example 1: \php.array_fill(5, 6, 'banana');
  13254. // * returns 1: { 5: 'banana', 6: 'banana', 7: 'banana', 8: 'banana', 9: 'banana', 10: 'banana' }
  13255. var key, tmp_arr = {};
  13256. if (!isNaN(start_index) && !isNaN(num)) {
  13257. for (key = 0; key < num; key++) {
  13258. tmp_arr[(key + start_index)] = mixed_val;
  13259. }
  13260. }
  13261. return tmp_arr;
  13262. };
  13263. php.array_fill_keys = function (keys, value) {
  13264. // Create an array using the elements of the first parameter as keys each initialized to val
  13265. //
  13266. // version: 1103.1210
  13267. // discuss at: http://phpjs.org/functions/array_fill_keys
  13268. // + original by: Brett Zamir (http://brett-zamir.me)
  13269. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  13270. // * example 1: \php.keys = {'a': 'foo', 2: 5, 3: 10, 4: 'bar'}
  13271. // * example 1: \php.array_fill_keys(keys, 'banana')
  13272. // * returns 1: {"foo": "banana", 5: "banana", 10: "banana", "bar": "banana"}
  13273. var retObj = {},
  13274. key = '';
  13275. for (key in keys) {
  13276. retObj[keys[key]] = value;
  13277. }
  13278. return retObj;
  13279. };
  13280. php.array_filter = function (arr, func) {
  13281. // Filters elements from the array via the callback.
  13282. //
  13283. // version: 1103.1210
  13284. // discuss at: http://phpjs.org/functions/array_filter
  13285. // + original by: Brett Zamir (http://brett-zamir.me)
  13286. // % note 1: Takes a function as an argument, not a function's name
  13287. // * example 1: \php.var odd = function (num) {return (num & 1);};
  13288. // * example 1: \php.array_filter({"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, odd);
  13289. // * returns 1: {"a": 1, "c": 3, "e": 5}
  13290. // * example 2: \php.var even = function (num) {return (!(num & 1));}
  13291. // * example 2: \php.array_filter([6, 7, 8, 9, 10, 11, 12], even);
  13292. // * returns 2: {0: 6, 2: 8, 4: 10, 6: 12}
  13293. var retObj = {},
  13294. k;
  13295. for (k in arr) {
  13296. if (func(arr[k])) {
  13297. retObj[k] = arr[k];
  13298. }
  13299. }
  13300. return retObj;
  13301. };
  13302. php.array_flip = function (trans) {
  13303. // Return array with key <-> value flipped
  13304. //
  13305. // version: 1103.1210
  13306. // discuss at: http://phpjs.org/functions/array_flip
  13307. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13308. // * example 1: \php.array_flip( {a: 1, b: 1, c: 2} );
  13309. // * returns 1: {1: 'b', 2: 'c'}
  13310. var key, tmp_ar = {};
  13311. for (key in trans) {
  13312. tmp_ar[trans[key]] = key;
  13313. }
  13314. return tmp_ar;
  13315. };
  13316. php.array_intersect = function () {
  13317. // Returns the entries of arr1 that have values which are present in all the other arguments
  13318. //
  13319. // version: 1103.1210
  13320. // discuss at: http://phpjs.org/functions/array_intersect
  13321. // + original by: Brett Zamir (http://brett-zamir.me)
  13322. // % note 1: These only output associative arrays (would need to be
  13323. // % note 1: all numeric and counting from zero to be numeric)
  13324. // * example 1: $array1 = {'a' : 'green', 0:'red', 1: 'blue'};
  13325. // * example 1: $array2 = {'b' : 'green', 0:'yellow', 1:'red'};
  13326. // * example 1: $array3 = ['green', 'red'];
  13327. // * example 1: $result = array_intersect($array1, $array2, $array3);
  13328. // * returns 1: {0: 'red', a: 'green'}
  13329. var arr1 = arguments[0],
  13330. retArr = {};
  13331. var k1 = '',
  13332. arr = {},
  13333. i = 0,
  13334. k = '';
  13335. arr1keys: for (k1 in arr1) {
  13336. arrs: for (i = 1; i < arguments.length; i++) {
  13337. arr = arguments[i];
  13338. for (k in arr) {
  13339. if (arr[k] === arr1[k1]) {
  13340. if (i === arguments.length - 1) {
  13341. retArr[k1] = arr1[k1];
  13342. }
  13343. // If the innermost loop always leads at least once to an equal value, continue the loop until done
  13344. continue arrs;
  13345. }
  13346. }
  13347. // If it reaches here, it wasn't found in at least one array, so try next value
  13348. continue arr1keys;
  13349. }
  13350. }
  13351. return retArr;
  13352. };
  13353. php.array_key_exists = function (key, search) {
  13354. // Checks if the given key or index exists in the array
  13355. //
  13356. // version: 1103.1210
  13357. // discuss at: http://phpjs.org/functions/array_key_exists
  13358. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13359. // + improved by: Felix Geisendoerfer (http://www.debuggable.com/felix)
  13360. // * example 1: \php.array_key_exists('kevin', {'kevin': 'van Zonneveld'});
  13361. // * returns 1: true
  13362. // input sanitation
  13363. if (!search || (search.constructor !== Array && search.constructor !== Object)) {
  13364. return false;
  13365. }
  13366. return key in search;
  13367. };
  13368. php.array_keys = function (input, search_value, argStrict) {
  13369. // Return just the keys from the input array, optionally only for the specified search_value
  13370. //
  13371. // version: 1103.1210
  13372. // discuss at: http://phpjs.org/functions/array_keys
  13373. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13374. // + input by: Brett Zamir (http://brett-zamir.me)
  13375. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13376. // + improved by: jd
  13377. // + improved by: Brett Zamir (http://brett-zamir.me)
  13378. // * example 1: \php.array_keys( {firstname: 'Kevin', surname: 'van Zonneveld'} );
  13379. // * returns 1: {0: 'firstname', 1: 'surname'}
  13380. var search = typeof search_value !== 'undefined',
  13381. tmp_arr = [],
  13382. strict = !!argStrict,
  13383. include = true,
  13384. key = '';
  13385. for (key in input) {
  13386. if (input.hasOwnProperty(key)) {
  13387. include = true;
  13388. if (search) {
  13389. if (strict && input[key] !== search_value) {
  13390. include = false;
  13391. }
  13392. else if (input[key] != search_value) {
  13393. include = false;
  13394. }
  13395. }
  13396. if (include) {
  13397. tmp_arr[tmp_arr.length] = key;
  13398. }
  13399. }
  13400. }
  13401. return tmp_arr;
  13402. };
  13403. php.array_map = function (callback) {
  13404. // Applies the callback to the elements in given arrays.
  13405. //
  13406. // version: 1103.1210
  13407. // discuss at: http://phpjs.org/functions/array_map
  13408. // + original by: Andrea Giammarchi (http://webreflection.blogspot.com)
  13409. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13410. // + improved by: Brett Zamir (http://brett-zamir.me)
  13411. // % note 1: Takes a function as an argument, not a function's name
  13412. // % note 2: If the callback is a string, it can only work if the function name is in the global context
  13413. // * example 1: \php.array_map( function (a){return (a * a * a)}, [1, 2, 3, 4, 5] );
  13414. // * returns 1: [ 1, 8, 27, 64, 125 ]
  13415. var argc = arguments.length,
  13416. argv = arguments;
  13417. var j = argv[1].length,
  13418. i = 0,
  13419. k = 1,
  13420. m = 0;
  13421. var tmp = [],
  13422. tmp_ar = [];
  13423. while (i < j) {
  13424. while (k < argc) {
  13425. tmp[m++] = argv[k++][i];
  13426. }
  13427. m = 0;
  13428. k = 1;
  13429. if (callback) {
  13430. if (typeof callback === 'string') {
  13431. callback = this.window[callback];
  13432. }
  13433. tmp_ar[i++] = callback.apply(null, tmp);
  13434. } else {
  13435. tmp_ar[i++] = tmp;
  13436. }
  13437. tmp = [];
  13438. }
  13439. return tmp_ar;
  13440. };
  13441. php.array_merge = function () {
  13442. // Merges elements from passed arrays into one array
  13443. //
  13444. // version: 1103.1210
  13445. // discuss at: http://phpjs.org/functions/array_merge
  13446. // + original by: Brett Zamir (http://brett-zamir.me)
  13447. // + bugfixed by: Nate
  13448. // + input by: josh
  13449. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  13450. // * example 1: \php.arr1 = {"color": "red", 0: 2, 1: 4}
  13451. // * example 1: \php.arr2 = {0: "a", 1: "b", "color": "green", "shape": "trapezoid", 2: 4}
  13452. // * example 1: \php.array_merge(arr1, arr2)
  13453. // * returns 1: {"color": "green", 0: 2, 1: 4, 2: "a", 3: "b", "shape": "trapezoid", 4: 4}
  13454. // * example 2: \php.arr1 = []
  13455. // * example 2: \php.arr2 = {1: "data"}
  13456. // * example 2: \php.array_merge(arr1, arr2)
  13457. // * returns 2: {0: "data"}
  13458. var args = Array.prototype.slice.call(arguments),
  13459. retObj = {},
  13460. k, j = 0,
  13461. i = 0,
  13462. retArr = true;
  13463. for (i = 0; i < args.length; i++) {
  13464. if (!(args[i] instanceof Array)) {
  13465. retArr = false;
  13466. break;
  13467. }
  13468. }
  13469. if (retArr) {
  13470. retArr = [];
  13471. for (i = 0; i < args.length; i++) {
  13472. retArr = retArr.concat(args[i]);
  13473. }
  13474. return retArr;
  13475. }
  13476. var ct = 0;
  13477. for (i = 0, ct = 0; i < args.length; i++) {
  13478. if (args[i] instanceof Array) {
  13479. for (j = 0; j < args[i].length; j++) {
  13480. retObj[ct++] = args[i][j];
  13481. }
  13482. } else {
  13483. for (k in args[i]) {
  13484. if (args[i].hasOwnProperty(k)) {
  13485. if (parseInt(k, 10) + '' === k) {
  13486. retObj[ct++] = args[i][k];
  13487. } else {
  13488. retObj[k] = args[i][k];
  13489. }
  13490. }
  13491. }
  13492. }
  13493. }
  13494. return retObj;
  13495. };
  13496. php.array_merge_recursive = function (arr1, arr2) {
  13497. // Recursively merges elements from passed arrays into one array
  13498. //
  13499. // version: 1103.1210
  13500. // discuss at: http://phpjs.org/functions/array_merge_recursive
  13501. // + original by: Subhasis Deb
  13502. // + input by: Brett Zamir (http://brett-zamir.me)
  13503. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13504. // - depends on: array_merge
  13505. // * example 1: \php.arr1 = {'color': {'favourite': 'read'}, 0: 5}
  13506. // * example 1: \php.arr2 = {0: 10, 'color': {'favorite': 'green', 0: 'blue'}}
  13507. // * example 1: \php.array_merge_recursive(arr1, arr2)
  13508. // * returns 1: {'color': {'favorite': {0: 'red', 1: 'green'}, 0: 'blue'}, 1: 5, 1: 10}
  13509. var idx = '';
  13510. if ((arr1 && (arr1 instanceof Array)) && (arr2 && (arr2 instanceof Array))) {
  13511. for (idx in arr2) {
  13512. arr1.push(arr2[idx]);
  13513. }
  13514. } else if ((arr1 && (arr1 instanceof Object)) && (arr2 && (arr2 instanceof Object))) {
  13515. for (idx in arr2) {
  13516. if (idx in arr1) {
  13517. if (typeof arr1[idx] == 'object' && typeof arr2 == 'object') {
  13518. arr1[idx] = this.array_merge(arr1[idx], arr2[idx]);
  13519. } else {
  13520. arr1[idx] = arr2[idx];
  13521. }
  13522. } else {
  13523. arr1[idx] = arr2[idx];
  13524. }
  13525. }
  13526. }
  13527. return arr1;
  13528. };
  13529. php.array_pop = function (inputArr) {
  13530. // Pops an element off the end of the array
  13531. //
  13532. // version: 1103.1210
  13533. // discuss at: http://phpjs.org/functions/array_pop
  13534. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13535. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13536. // + input by: Brett Zamir (http://brett-zamir.me)
  13537. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13538. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  13539. // + input by: Theriault
  13540. // % note 1: While IE (and other browsers) support iterating an object's
  13541. // % note 1: own properties in order, if one attempts to add back properties
  13542. // % note 1: in IE, they may end up in their former position due to their position
  13543. // % note 1: being retained. So use of this function with "associative arrays"
  13544. // % note 1: (objects) may lead to unexpected behavior in an IE environment if
  13545. // % note 1: you add back properties with the same keys that you removed