/protected/test.txt

http://github.com/phpnode/YiiJS · Plain Text · 26755 lines · 25815 code · 940 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
  13546. // * example 1: \php.array_pop([0,1,2]);
  13547. // * returns 1: 2
  13548. // * example 2: \php.data = {firstName: 'Kevin', surName: 'van Zonneveld'};
  13549. // * example 2: \php.lastElem = array_pop(data);
  13550. // * returns 2: 'van Zonneveld'
  13551. // * results 2: data == {firstName: 'Kevin'}
  13552. var key = '',
  13553. lastKey = '';
  13554. if (inputArr.hasOwnProperty('length')) {
  13555. // Indexed
  13556. if (!inputArr.length) {
  13557. // Done popping, are we?
  13558. return null;
  13559. }
  13560. return inputArr.pop();
  13561. } else {
  13562. // Associative
  13563. for (key in inputArr) {
  13564. if (inputArr.hasOwnProperty(key)) {
  13565. lastKey = key;
  13566. }
  13567. }
  13568. if (lastKey) {
  13569. var tmp = inputArr[lastKey];
  13570. delete(inputArr[lastKey]);
  13571. return tmp;
  13572. } else {
  13573. return null;
  13574. }
  13575. }
  13576. };
  13577. php.array_push = function (inputArr) {
  13578. // Pushes elements onto the end of the array
  13579. //
  13580. // version: 1103.1210
  13581. // discuss at: http://phpjs.org/functions/array_push
  13582. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13583. // + improved by: Brett Zamir (http://brett-zamir.me)
  13584. // % note 1: Note also that IE retains information about property position even
  13585. // % note 1: after being supposedly deleted, so if you delete properties and then
  13586. // % note 1: add back properties with the same keys (including numeric) that had
  13587. // % note 1: been deleted, the order will be as before; thus, this function is not
  13588. // % note 1: really recommended with associative arrays (objects) in IE environments
  13589. // * example 1: \php.array_push(['kevin','van'], 'zonneveld');
  13590. // * returns 1: 3
  13591. var i = 0,
  13592. pr = '',
  13593. argv = arguments,
  13594. argc = argv.length,
  13595. allDigits = /^\d$/,
  13596. size = 0,
  13597. highestIdx = 0,
  13598. len = 0;
  13599. if (inputArr.hasOwnProperty('length')) {
  13600. for (i = 1; i < argc; i++) {
  13601. inputArr[inputArr.length] = argv[i];
  13602. }
  13603. return inputArr.length;
  13604. }
  13605. // Associative (object)
  13606. for (pr in inputArr) {
  13607. if (inputArr.hasOwnProperty(pr)) {
  13608. ++len;
  13609. if (pr.search(allDigits) !== -1) {
  13610. size = parseInt(pr, 10);
  13611. highestIdx = size > highestIdx ? size : highestIdx;
  13612. }
  13613. }
  13614. }
  13615. for (i = 1; i < argc; i++) {
  13616. inputArr[++highestIdx] = argv[i];
  13617. }
  13618. return len + i - 1;
  13619. };
  13620. php.array_reduce = function (a_input, callback) {
  13621. // Iteratively reduce the array to a single value via the callback.
  13622. //
  13623. // version: 1103.1210
  13624. // discuss at: http://phpjs.org/functions/array_reduce
  13625. // + original by: Alfonso Jimenez (http://www.alfonsojimenez.com)
  13626. // % note 1: Takes a function as an argument, not a function's name
  13627. // * example 1: \php.array_reduce([1, 2, 3, 4, 5], function (v, w){v += w;return v;});
  13628. // * returns 1: 15
  13629. var lon = a_input.length;
  13630. var res = 0,
  13631. i = 0;
  13632. var tmp = [];
  13633. for (i = 0; i < lon; i += 2) {
  13634. tmp[0] = a_input[i];
  13635. if (a_input[(i + 1)]) {
  13636. tmp[1] = a_input[(i + 1)];
  13637. } else {
  13638. tmp[1] = 0;
  13639. }
  13640. res += callback.apply(null, tmp);
  13641. tmp = [];
  13642. }
  13643. return res;
  13644. };
  13645. php.array_reverse = function (array, preserve_keys) {
  13646. // Return input as a new array with the order of the entries reversed
  13647. //
  13648. // version: 1103.1210
  13649. // discuss at: http://phpjs.org/functions/array_reverse
  13650. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13651. // + improved by: Karol Kowalski
  13652. // * example 1: \php.array_reverse( [ 'php', '4.0', ['green', 'red'] ], true);
  13653. // * returns 1: { 2: ['green', 'red'], 1: 4, 0: 'php'}
  13654. var arr_len = array.length,
  13655. newkey = 0,
  13656. tmp_arr = {},
  13657. key = '';
  13658. preserve_keys = !! preserve_keys;
  13659. for (key in array) {
  13660. newkey = arr_len - key - 1;
  13661. tmp_arr[preserve_keys ? key : newkey] = array[key];
  13662. }
  13663. return tmp_arr;
  13664. };
  13665. php.array_shift = function (inputArr) {
  13666. // Pops an element off the beginning of the array
  13667. //
  13668. // version: 1103.1210
  13669. // discuss at: http://phpjs.org/functions/array_shift
  13670. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13671. // + improved by: Martijn Wieringa
  13672. // % note 1: Currently does not handle objects
  13673. // * example 1: \php.array_shift(['Kevin', 'van', 'Zonneveld']);
  13674. // * returns 1: 'Kevin'
  13675. var props = false,
  13676. shift = undefined,
  13677. pr = '',
  13678. allDigits = /^\d$/,
  13679. int_ct = -1,
  13680. _checkToUpIndices = function (arr, ct, key) {
  13681. // Deal with situation, e.g., if encounter index 4 and try to set it to 0, but 0 exists later in loop (need to
  13682. // increment all subsequent (skipping current key, since we need its value below) until find unused)
  13683. if (arr[ct] !== undefined) {
  13684. var tmp = ct;
  13685. ct += 1;
  13686. if (ct === key) {
  13687. ct += 1;
  13688. }
  13689. ct = _checkToUpIndices(arr, ct, key);
  13690. arr[ct] = arr[tmp];
  13691. delete arr[tmp];
  13692. }
  13693. return ct;
  13694. };
  13695. if (inputArr.length === 0) {
  13696. return null;
  13697. }
  13698. if (inputArr.length > 0) {
  13699. return inputArr.shift();
  13700. }
  13701. /*
  13702. UNFINISHED FOR HANDLING OBJECTS
  13703. for (pr in inputArr) {
  13704. if (inputArr.hasOwnProperty(pr)) {
  13705. props = true;
  13706. shift = inputArr[pr];
  13707. delete inputArr[pr];
  13708. break;
  13709. }
  13710. }
  13711. for (pr in inputArr) {
  13712. if (inputArr.hasOwnProperty(pr)) {
  13713. if (pr.search(allDigits) !== -1) {
  13714. int_ct += 1;
  13715. if (parseInt(pr, 10) === int_ct) { // Key is already numbered ok, so don't need to change key for value
  13716. continue;
  13717. }
  13718. _checkToUpIndices(inputArr, int_ct, pr);
  13719. arr[int_ct] = arr[pr];
  13720. delete arr[pr];
  13721. }
  13722. }
  13723. }
  13724. if (!props) {
  13725. return null;
  13726. }
  13727. return shift;
  13728. */
  13729. };
  13730. php.array_slice = function (arr, offst, lgth, preserve_keys) {
  13731. // Returns elements specified by offset and length
  13732. //
  13733. // version: 1103.1210
  13734. // discuss at: http://phpjs.org/functions/array_slice
  13735. // + original by: Brett Zamir (http://brett-zamir.me)
  13736. // - depends on: is_int
  13737. // + input by: Brett Zamir (http://brett-zamir.me)
  13738. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13739. // % note: Relies on is_int because !isNaN accepts floats
  13740. // * example 1: \php.array_slice(["a", "b", "c", "d", "e"], 2, -1);
  13741. // * returns 1: {0: 'c', 1: 'd'}
  13742. // * example 2: \php.array_slice(["a", "b", "c", "d", "e"], 2, -1, true);
  13743. // * returns 2: {2: 'c', 3: 'd'}
  13744. /*
  13745. if ('callee' in arr && 'length' in arr) {
  13746. arr = Array.prototype.slice.call(arr);
  13747. }
  13748. */
  13749. var key = '';
  13750. if (!(arr instanceof Array) || (preserve_keys && offst !== 0)) { // Assoc. array as input or if required as output
  13751. var lgt = 0,
  13752. newAssoc = {};
  13753. for (key in arr) {
  13754. //if (key !== 'length') {
  13755. lgt += 1;
  13756. newAssoc[key] = arr[key];
  13757. //}
  13758. }
  13759. arr = newAssoc;
  13760. offst = (offst < 0) ? lgt + offst : offst;
  13761. lgth = lgth === undefined ? lgt : (lgth < 0) ? lgt + lgth - offst : lgth;
  13762. var assoc = {};
  13763. var start = false,
  13764. it = -1,
  13765. arrlgth = 0,
  13766. no_pk_idx = 0;
  13767. for (key in arr) {
  13768. ++it;
  13769. if (arrlgth >= lgth) {
  13770. break;
  13771. }
  13772. if (it == offst) {
  13773. start = true;
  13774. }
  13775. if (!start) {
  13776. continue;
  13777. }++arrlgth;
  13778. if (this.is_int(key) && !preserve_keys) {
  13779. assoc[no_pk_idx++] = arr[key];
  13780. } else {
  13781. assoc[key] = arr[key];
  13782. }
  13783. }
  13784. //assoc.length = arrlgth; // Make as array-like object (though length will not be dynamic)
  13785. return assoc;
  13786. }
  13787. if (lgth === undefined) {
  13788. return arr.slice(offst);
  13789. } else if (lgth >= 0) {
  13790. return arr.slice(offst, offst + lgth);
  13791. } else {
  13792. return arr.slice(offst, lgth);
  13793. }
  13794. };
  13795. php.array_splice = function (arr, offst, lgth, replacement) {
  13796. // Removes the elements designated by offset and length and replace them with supplied array
  13797. //
  13798. // version: 1103.1210
  13799. // discuss at: http://phpjs.org/functions/array_splice
  13800. // + original by: Brett Zamir (http://brett-zamir.me)
  13801. // + input by: Theriault
  13802. // % note 1: Order does get shifted in associative array input with numeric indices,
  13803. // % note 1: since PHP behavior doesn't preserve keys, but I understand order is
  13804. // % note 1: not reliable anyways
  13805. // % note 2: Note also that IE retains information about property position even
  13806. // % note 2: after being supposedly deleted, so use of this function may produce
  13807. // % note 2: unexpected results in IE if you later attempt to add back properties
  13808. // % note 2: with the same keys that had been deleted
  13809. // - depends on: is_int
  13810. // * example 1: \php.input = {4: "red", 'abc': "green", 2: "blue", 'dud': "yellow"};
  13811. // * example 1: \php.array_splice(input, 2);
  13812. // * returns 1: {0: "blue", 'dud': "yellow"}
  13813. // * results 1: input == {'abc':"green", 0:"red"}
  13814. // * example 2: \php.input = ["red", "green", "blue", "yellow"];
  13815. // * example 2: \php.array_splice(input, 3, 0, "purple");
  13816. // * returns 2: []
  13817. // * results 2: input == ["red", "green", "blue", "purple", "yellow"]
  13818. // * example 3: \php.input = ["red", "green", "blue", "yellow"]
  13819. // * example 3: \php.array_splice(input, -1, 1, ["black", "maroon"]);
  13820. // * returns 3: ["yellow"]
  13821. // * results 3: input == ["red", "green", "blue", "black", "maroon"]
  13822. var _checkToUpIndices = function (arr, ct, key) {
  13823. // Deal with situation, e.g., if encounter index 4 and try to set it to 0, but 0 exists later in loop (need to
  13824. // increment all subsequent (skipping current key, since we need its value below) until find unused)
  13825. if (arr[ct] !== undefined) {
  13826. var tmp = ct;
  13827. ct += 1;
  13828. if (ct === key) {
  13829. ct += 1;
  13830. }
  13831. ct = _checkToUpIndices(arr, ct, key);
  13832. arr[ct] = arr[tmp];
  13833. delete arr[tmp];
  13834. }
  13835. return ct;
  13836. };
  13837. if (replacement && typeof replacement !== 'object') {
  13838. replacement = [replacement];
  13839. }
  13840. if (lgth === undefined) {
  13841. lgth = offst >= 0 ? arr.length - offst : -offst;
  13842. } else if (lgth < 0) {
  13843. lgth = (offst >= 0 ? arr.length - offst : -offst) + lgth;
  13844. }
  13845. if (!(arr instanceof Array)) {
  13846. /*if (arr.length !== undefined) { // Deal with array-like objects as input
  13847. delete arr.length;
  13848. }*/
  13849. var lgt = 0,
  13850. ct = -1,
  13851. rmvd = [],
  13852. rmvdObj = {},
  13853. repl_ct = -1,
  13854. int_ct = -1;
  13855. var returnArr = true,
  13856. rmvd_ct = 0,
  13857. rmvd_lgth = 0,
  13858. key = '';
  13859. // rmvdObj.length = 0;
  13860. for (key in arr) { // Can do arr.__count__ in some browsers
  13861. lgt += 1;
  13862. }
  13863. offst = (offst >= 0) ? offst : lgt + offst;
  13864. for (key in arr) {
  13865. ct += 1;
  13866. if (ct < offst) {
  13867. if (this.is_int(key)) {
  13868. int_ct += 1;
  13869. if (parseInt(key, 10) === int_ct) { // Key is already numbered ok, so don't need to change key for value
  13870. continue;
  13871. }
  13872. _checkToUpIndices(arr, int_ct, key); // Deal with situation, e.g.,
  13873. // if encounter index 4 and try to set it to 0, but 0 exists later in loop
  13874. arr[int_ct] = arr[key];
  13875. delete arr[key];
  13876. }
  13877. continue;
  13878. }
  13879. if (returnArr && this.is_int(key)) {
  13880. rmvd.push(arr[key]);
  13881. rmvdObj[rmvd_ct++] = arr[key]; // PHP starts over here too
  13882. } else {
  13883. rmvdObj[key] = arr[key];
  13884. returnArr = false;
  13885. }
  13886. rmvd_lgth += 1;
  13887. // rmvdObj.length += 1;
  13888. if (replacement && replacement[++repl_ct]) {
  13889. arr[key] = replacement[repl_ct];
  13890. } else {
  13891. delete arr[key];
  13892. }
  13893. }
  13894. // arr.length = lgt - rmvd_lgth + (replacement ? replacement.length : 0); // Make (back) into an array-like object
  13895. return returnArr ? rmvd : rmvdObj;
  13896. }
  13897. if (replacement) {
  13898. replacement.unshift(offst, lgth);
  13899. return Array.prototype.splice.apply(arr, replacement);
  13900. }
  13901. return arr.splice(offst, lgth);
  13902. };
  13903. php.array_sum = function (array) {
  13904. // Returns the sum of the array entries
  13905. //
  13906. // version: 1103.1210
  13907. // discuss at: http://phpjs.org/functions/array_sum
  13908. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13909. // + bugfixed by: Nate
  13910. // + bugfixed by: Gilbert
  13911. // * example 1: \php.array_sum([4, 9, 182.6]);
  13912. // * returns 1: 195.6
  13913. // * example 2: \php.total = []; index = 0.1; for (y=0; y < 12; y++){total[y] = y + index;}
  13914. // * example 2: \php.array_sum(total);
  13915. // * returns 2: 67.2
  13916. var key, sum = 0;
  13917. // input sanitation
  13918. if (typeof array !== 'object') {
  13919. return null;
  13920. }
  13921. for (key in array) {
  13922. //tester_print_r(typeof sum);
  13923. sum += (array[key] * 1);
  13924. }
  13925. return sum;
  13926. };
  13927. php.array_unique = function (inputArr) {
  13928. // Removes duplicate values from array
  13929. //
  13930. // version: 1103.1210
  13931. // discuss at: http://phpjs.org/functions/array_unique
  13932. // + original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
  13933. // + input by: duncan
  13934. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13935. // + bugfixed by: Nate
  13936. // + input by: Brett Zamir (http://brett-zamir.me)
  13937. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13938. // + improved by: Michael Grier
  13939. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  13940. // % note 1: The second argument, sort_flags is not implemented;
  13941. // % note 1: also should be sorted (asort?) first according to docs
  13942. // * example 1: \php.array_unique(['Kevin','Kevin','van','Zonneveld','Kevin']);
  13943. // * returns 1: {0: 'Kevin', 2: 'van', 3: 'Zonneveld'}
  13944. // * example 2: \php.array_unique({'a': 'green', 0: 'red', 'b': 'green', 1: 'blue', 2: 'red'});
  13945. // * returns 2: {a: 'green', 0: 'red', 1: 'blue'}
  13946. var key = '',
  13947. tmp_arr2 = {},
  13948. val = '';
  13949. var __array_search = function (needle, haystack) {
  13950. var fkey = '';
  13951. for (fkey in haystack) {
  13952. if (haystack.hasOwnProperty(fkey)) {
  13953. if ((haystack[fkey] + '') === (needle + '')) {
  13954. return fkey;
  13955. }
  13956. }
  13957. }
  13958. return false;
  13959. };
  13960. for (key in inputArr) {
  13961. if (inputArr.hasOwnProperty(key)) {
  13962. val = inputArr[key];
  13963. if (false === __array_search(val, tmp_arr2)) {
  13964. tmp_arr2[key] = val;
  13965. }
  13966. }
  13967. }
  13968. return tmp_arr2;
  13969. };
  13970. php.array_unshift = function (array) {
  13971. // Pushes elements onto the beginning of the array
  13972. //
  13973. // version: 1103.1210
  13974. // discuss at: http://phpjs.org/functions/array_unshift
  13975. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13976. // + improved by: Martijn Wieringa
  13977. // + improved by: jmweb
  13978. // % note 1: Currently does not handle objects
  13979. // * example 1: \php.array_unshift(['van', 'Zonneveld'], 'Kevin');
  13980. // * returns 1: 3
  13981. var i = arguments.length;
  13982. while (--i !== 0) {
  13983. arguments[0].unshift(arguments[i]);
  13984. }
  13985. return arguments[0].length;
  13986. };
  13987. php.array_values = function (input) {
  13988. // Return just the values from the input array
  13989. //
  13990. // version: 1103.1210
  13991. // discuss at: http://phpjs.org/functions/array_values
  13992. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  13993. // * example 1: \php.array_values( {firstname: 'Kevin', surname: 'van Zonneveld'} );
  13994. // * returns 1: {0: 'Kevin', 1: 'van Zonneveld'}
  13995. var tmp_arr = [],
  13996. cnt = 0;
  13997. var key = '';
  13998. for (key in input) {
  13999. tmp_arr[cnt] = input[key];
  14000. cnt++;
  14001. }
  14002. return tmp_arr;
  14003. };
  14004. php.array_walk = function (array, funcname, userdata) {
  14005. // Apply a user function to every member of an array
  14006. //
  14007. // version: 1103.1210
  14008. // discuss at: http://phpjs.org/functions/array_walk
  14009. // + original by: Johnny Mast (http://www.phpvrouwen.nl)
  14010. // * example 1: \php.array_walk ({'a':'b'}, 'void', 'userdata');
  14011. // * returns 1: true
  14012. // * example 2: \php.array_walk ('a', 'void', 'userdata');
  14013. // * returns 2: false
  14014. var key;
  14015. if (typeof array !== 'object' || array === null) {
  14016. return false;
  14017. }
  14018. for (key in array) {
  14019. if (typeof(userdata) !== 'undefined') {
  14020. eval(funcname + '( array [key] , key , userdata )');
  14021. } else {
  14022. eval(funcname + '( userdata ) ');
  14023. }
  14024. }
  14025. return true;
  14026. };
  14027. php.array_walk_recursive = function (array, funcname, userdata) {
  14028. // Apply a user function recursively to every member of an array
  14029. //
  14030. // version: 1103.1210
  14031. // discuss at: http://phpjs.org/functions/array_walk_recursive
  14032. // + original by: Johnny Mast (http://www.phpvrouwen.nl)
  14033. // * example 1: \php.array_walk_recursive ({'a': 'b', 'c': {'d': 'e'}}, 'void', 'userdata');
  14034. // * returns 1: true
  14035. // * example 2: \php.array_walk_recursive ('a', 'void', 'userdata');
  14036. // * returns 2: false
  14037. var key;
  14038. if (typeof array != 'object') {
  14039. return false;
  14040. }
  14041. for (key in array) {
  14042. if (typeof array[key] == 'object') {
  14043. return this.array_walk_recursive(array[key], funcname, userdata);
  14044. }
  14045. if (typeof(userdata) != 'undefined') {
  14046. eval(funcname + '( array [key] , key , userdata )');
  14047. } else {
  14048. eval(funcname + '( userdata ) ');
  14049. }
  14050. }
  14051. return true;
  14052. };
  14053. php.arsort = function (inputArr, sort_flags) {
  14054. // Sort an array in reverse order and maintain index association
  14055. //
  14056. // version: 1103.1210
  14057. // discuss at: http://phpjs.org/functions/arsort
  14058. // + original by: Brett Zamir (http://brett-zamir.me)
  14059. // + improved by: Brett Zamir (http://brett-zamir.me)
  14060. // % note 1: SORT_STRING (as well as natsort and natcasesort) might also be
  14061. // % note 1: integrated into all of these functions by adapting the code at
  14062. // % note 1: http://sourcefrog.net/projects/natsort/natcompare.js
  14063. // % note 2: The examples are correct, this is a new way
  14064. // % note 2: Credits to: http://javascript.internet.com/math-related/bubble-sort.html
  14065. // % note 3: This function deviates from PHP in returning a copy of the array instead
  14066. // % note 3: of acting by reference and returning true; this was necessary because
  14067. // % note 3: IE does not allow deleting and re-adding of properties without caching
  14068. // % note 3: of property position; you can set the ini of "phpjs.strictForIn" to true to
  14069. // % note 3: get the PHP behavior, but use this only if you are in an environment
  14070. // % note 3: such as Firefox extensions where for-in iteration order is fixed and true
  14071. // % note 3: property deletion is supported. Note that we intend to implement the PHP
  14072. // % note 3: behavior by default if IE ever does allow it; only gives shallow copy since
  14073. // % note 3: is by reference in PHP anyways
  14074. // % note 4: Since JS objects' keys are always strings, and (the
  14075. // % note 4: default) SORT_REGULAR flag distinguishes by key type,
  14076. // % note 4: if the content is a numeric string, we treat the
  14077. // % note 4: "original type" as numeric.
  14078. // - depends on: i18n_loc_get_default
  14079. // * example 1: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  14080. // * example 1: \php.data = arsort(data);
  14081. // * returns 1: data == {a: 'orange', d: 'lemon', b: 'banana', c: 'apple'}
  14082. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  14083. // * example 2: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  14084. // * example 2: \php.arsort(data);
  14085. // * results 2: data == {a: 'orange', d: 'lemon', b: 'banana', c: 'apple'}
  14086. // * returns 2: true
  14087. var valArr = [],
  14088. keyArr = [],
  14089. k, i, ret, sorter, that = this,
  14090. strictForIn = false,
  14091. populateArr = {};
  14092. switch (sort_flags) {
  14093. case 'SORT_STRING':
  14094. // compare items as strings
  14095. sorter = function (a, b) {
  14096. return that.strnatcmp(b, a);
  14097. };
  14098. break;
  14099. case 'SORT_LOCALE_STRING':
  14100. // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
  14101. var loc = this.i18n_loc_get_default();
  14102. sorter = this.php_js.i18nLocales[loc].sorting;
  14103. break;
  14104. case 'SORT_NUMERIC':
  14105. // compare items numerically
  14106. sorter = function (a, b) {
  14107. return (a - b);
  14108. };
  14109. break;
  14110. case 'SORT_REGULAR':
  14111. // compare items normally (don't change types)
  14112. default:
  14113. sorter = function (b, a) {
  14114. var aFloat = parseFloat(a),
  14115. bFloat = parseFloat(b),
  14116. aNumeric = aFloat + '' === a,
  14117. bNumeric = bFloat + '' === b;
  14118. if (aNumeric && bNumeric) {
  14119. return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  14120. } else if (aNumeric && !bNumeric) {
  14121. return 1;
  14122. } else if (!aNumeric && bNumeric) {
  14123. return -1;
  14124. }
  14125. return a > b ? 1 : a < b ? -1 : 0;
  14126. };
  14127. break;
  14128. }
  14129. var bubbleSort = function (keyArr, inputArr) {
  14130. var i, j, tempValue, tempKeyVal;
  14131. for (i = inputArr.length - 2; i >= 0; i--) {
  14132. for (j = 0; j <= i; j++) {
  14133. ret = sorter(inputArr[j + 1], inputArr[j]);
  14134. if (ret > 0) {
  14135. tempValue = inputArr[j];
  14136. inputArr[j] = inputArr[j + 1];
  14137. inputArr[j + 1] = tempValue;
  14138. tempKeyVal = keyArr[j];
  14139. keyArr[j] = keyArr[j + 1];
  14140. keyArr[j + 1] = tempKeyVal;
  14141. }
  14142. }
  14143. }
  14144. };
  14145. // BEGIN REDUNDANT
  14146. this.php_js = this.php_js || {};
  14147. this.php_js.ini = this.php_js.ini || {};
  14148. // END REDUNDANT
  14149. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  14150. populateArr = strictForIn ? inputArr : populateArr;
  14151. // Get key and value arrays
  14152. for (k in inputArr) {
  14153. if (inputArr.hasOwnProperty(k)) {
  14154. valArr.push(inputArr[k]);
  14155. keyArr.push(k);
  14156. if (strictForIn) {
  14157. delete inputArr[k];
  14158. }
  14159. }
  14160. }
  14161. try {
  14162. // Sort our new temporary arrays
  14163. bubbleSort(keyArr, valArr);
  14164. } catch (e) {
  14165. return false;
  14166. }
  14167. // Repopulate the old array
  14168. for (i = 0; i < valArr.length; i++) {
  14169. populateArr[keyArr[i]] = valArr[i];
  14170. }
  14171. return strictForIn || populateArr;
  14172. };
  14173. php.asort = function (inputArr, sort_flags) {
  14174. // Sort an array and maintain index association
  14175. //
  14176. // version: 1103.1210
  14177. // discuss at: http://phpjs.org/functions/asort
  14178. // + original by: Brett Zamir (http://brett-zamir.me)
  14179. // + improved by: Brett Zamir (http://brett-zamir.me)
  14180. // + input by: paulo kuong
  14181. // + improved by: Brett Zamir (http://brett-zamir.me)
  14182. // + bugfixed by: Adam Wallner (http://web2.bitbaro.hu/)
  14183. // % note 1: SORT_STRING (as well as natsort and natcasesort) might also be
  14184. // % note 1: integrated into all of these functions by adapting the code at
  14185. // % note 1: http://sourcefrog.net/projects/natsort/natcompare.js
  14186. // % note 2: The examples are correct, this is a new way
  14187. // % note 2: Credits to: http://javascript.internet.com/math-related/bubble-sort.html
  14188. // % note 3: This function deviates from PHP in returning a copy of the array instead
  14189. // % note 3: of acting by reference and returning true; this was necessary because
  14190. // % note 3: IE does not allow deleting and re-adding of properties without caching
  14191. // % note 3: of property position; you can set the ini of "phpjs.strictForIn" to true to
  14192. // % note 3: get the PHP behavior, but use this only if you are in an environment
  14193. // % note 3: such as Firefox extensions where for-in iteration order is fixed and true
  14194. // % note 3: property deletion is supported. Note that we intend to implement the PHP
  14195. // % note 3: behavior by default if IE ever does allow it; only gives shallow copy since
  14196. // % note 3: is by reference in PHP anyways
  14197. // % note 4: Since JS objects' keys are always strings, and (the
  14198. // % note 4: default) SORT_REGULAR flag distinguishes by key type,
  14199. // % note 4: if the content is a numeric string, we treat the
  14200. // % note 4: "original type" as numeric.
  14201. // - depends on: strnatcmp
  14202. // - depends on: i18n_loc_get_default
  14203. // * example 1: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  14204. // * example 1: \php.data = asort(data);
  14205. // * results 1: data == {c: 'apple', b: 'banana', d: 'lemon', a: 'orange'}
  14206. // * returns 1: true
  14207. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  14208. // * example 2: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  14209. // * example 2: \php.asort(data);
  14210. // * results 2: data == {c: 'apple', b: 'banana', d: 'lemon', a: 'orange'}
  14211. // * returns 2: true
  14212. var valArr = [],
  14213. keyArr = [],
  14214. k, i, ret, sorter, that = this,
  14215. strictForIn = false,
  14216. populateArr = {};
  14217. switch (sort_flags) {
  14218. case 'SORT_STRING':
  14219. // compare items as strings
  14220. sorter = function (a, b) {
  14221. return that.strnatcmp(a, b);
  14222. };
  14223. break;
  14224. case 'SORT_LOCALE_STRING':
  14225. // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
  14226. var loc = this.i18n_loc_get_default();
  14227. sorter = this.php_js.i18nLocales[loc].sorting;
  14228. break;
  14229. case 'SORT_NUMERIC':
  14230. // compare items numerically
  14231. sorter = function (a, b) {
  14232. return (a - b);
  14233. };
  14234. break;
  14235. case 'SORT_REGULAR':
  14236. // compare items normally (don't change types)
  14237. default:
  14238. sorter = function (a, b) {
  14239. var aFloat = parseFloat(a),
  14240. bFloat = parseFloat(b),
  14241. aNumeric = aFloat + '' === a,
  14242. bNumeric = bFloat + '' === b;
  14243. if (aNumeric && bNumeric) {
  14244. return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  14245. } else if (aNumeric && !bNumeric) {
  14246. return 1;
  14247. } else if (!aNumeric && bNumeric) {
  14248. return -1;
  14249. }
  14250. return a > b ? 1 : a < b ? -1 : 0;
  14251. };
  14252. break;
  14253. }
  14254. var bubbleSort = function (keyArr, inputArr) {
  14255. var i, j, tempValue, tempKeyVal;
  14256. for (i = inputArr.length - 2; i >= 0; i--) {
  14257. for (j = 0; j <= i; j++) {
  14258. ret = sorter(inputArr[j + 1], inputArr[j]);
  14259. if (ret < 0) {
  14260. tempValue = inputArr[j];
  14261. inputArr[j] = inputArr[j + 1];
  14262. inputArr[j + 1] = tempValue;
  14263. tempKeyVal = keyArr[j];
  14264. keyArr[j] = keyArr[j + 1];
  14265. keyArr[j + 1] = tempKeyVal;
  14266. }
  14267. }
  14268. }
  14269. };
  14270. // BEGIN REDUNDANT
  14271. this.php_js = this.php_js || {};
  14272. this.php_js.ini = this.php_js.ini || {};
  14273. // END REDUNDANT
  14274. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  14275. populateArr = strictForIn ? inputArr : populateArr;
  14276. // Get key and value arrays
  14277. for (k in inputArr) {
  14278. if (inputArr.hasOwnProperty(k)) {
  14279. valArr.push(inputArr[k]);
  14280. keyArr.push(k);
  14281. if (strictForIn) {
  14282. delete inputArr[k];
  14283. }
  14284. }
  14285. }
  14286. try {
  14287. // Sort our new temporary arrays
  14288. bubbleSort(keyArr, valArr);
  14289. } catch (e) {
  14290. return false;
  14291. }
  14292. // Repopulate the old array
  14293. for (i = 0; i < valArr.length; i++) {
  14294. populateArr[keyArr[i]] = valArr[i];
  14295. }
  14296. return strictForIn || populateArr;
  14297. };
  14298. php.base64_decode = function (data) {
  14299. // Decodes string using MIME base64 algorithm
  14300. //
  14301. // version: 1103.1210
  14302. // discuss at: http://phpjs.org/functions/base64_decode
  14303. // + original by: Tyler Akins (http://rumkin.com)
  14304. // + improved by: Thunder.m
  14305. // + input by: Aman Gupta
  14306. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14307. // + bugfixed by: Onno Marsman
  14308. // + bugfixed by: Pellentesque Malesuada
  14309. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14310. // + input by: Brett Zamir (http://brett-zamir.me)
  14311. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14312. // - depends on: utf8_decode
  14313. // * example 1: \php.base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
  14314. // * returns 1: 'Kevin van Zonneveld'
  14315. // mozilla has this native
  14316. // - but breaks in 2.0.0.12!
  14317. //if (typeof this.window['btoa'] == 'function') {
  14318. // return btoa(data);
  14319. //}
  14320. var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  14321. var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
  14322. ac = 0,
  14323. dec = "",
  14324. tmp_arr = [];
  14325. if (!data) {
  14326. return data;
  14327. }
  14328. data += '';
  14329. do { // unpack four hexets into three octets using index points in b64
  14330. h1 = b64.indexOf(data.charAt(i++));
  14331. h2 = b64.indexOf(data.charAt(i++));
  14332. h3 = b64.indexOf(data.charAt(i++));
  14333. h4 = b64.indexOf(data.charAt(i++));
  14334. bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
  14335. o1 = bits >> 16 & 0xff;
  14336. o2 = bits >> 8 & 0xff;
  14337. o3 = bits & 0xff;
  14338. if (h3 == 64) {
  14339. tmp_arr[ac++] = String.fromCharCode(o1);
  14340. } else if (h4 == 64) {
  14341. tmp_arr[ac++] = String.fromCharCode(o1, o2);
  14342. } else {
  14343. tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
  14344. }
  14345. } while (i < data.length);
  14346. dec = tmp_arr.join('');
  14347. dec = this.utf8_decode(dec);
  14348. return dec;
  14349. };
  14350. php.base64_encode = function (data) {
  14351. // Encodes string using MIME base64 algorithm
  14352. //
  14353. // version: 1103.1210
  14354. // discuss at: http://phpjs.org/functions/base64_encode
  14355. // + original by: Tyler Akins (http://rumkin.com)
  14356. // + improved by: Bayron Guevara
  14357. // + improved by: Thunder.m
  14358. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14359. // + bugfixed by: Pellentesque Malesuada
  14360. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14361. // - depends on: utf8_encode
  14362. // * example 1: \php.base64_encode('Kevin van Zonneveld');
  14363. // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
  14364. // mozilla has this native
  14365. // - but breaks in 2.0.0.12!
  14366. //if (typeof this.window['atob'] == 'function') {
  14367. // return atob(data);
  14368. //}
  14369. var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  14370. var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
  14371. ac = 0,
  14372. enc = "",
  14373. tmp_arr = [];
  14374. if (!data) {
  14375. return data;
  14376. }
  14377. data = this.utf8_encode(data + '');
  14378. do { // pack three octets into four hexets
  14379. o1 = data.charCodeAt(i++);
  14380. o2 = data.charCodeAt(i++);
  14381. o3 = data.charCodeAt(i++);
  14382. bits = o1 << 16 | o2 << 8 | o3;
  14383. h1 = bits >> 18 & 0x3f;
  14384. h2 = bits >> 12 & 0x3f;
  14385. h3 = bits >> 6 & 0x3f;
  14386. h4 = bits & 0x3f;
  14387. // use hexets to index into b64, and append result to encoded string
  14388. tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  14389. } while (i < data.length);
  14390. enc = tmp_arr.join('');
  14391. switch (data.length % 3) {
  14392. case 1:
  14393. enc = enc.slice(0, -2) + '==';
  14394. break;
  14395. case 2:
  14396. enc = enc.slice(0, -1) + '=';
  14397. break;
  14398. }
  14399. return enc;
  14400. };
  14401. php.base_convert = function (number, frombase, tobase) {
  14402. // Converts a number in a string from any base <= 36 to any base <= 36
  14403. //
  14404. // version: 1103.1210
  14405. // discuss at: http://phpjs.org/functions/base_convert
  14406. // + original by: Philippe Baumann
  14407. // + improved by: Rafał Kukawski (http://blog.kukawski.pl)
  14408. // * example 1: \php.base_convert('A37334', 16, 2);
  14409. // * returns 1: '101000110111001100110100'
  14410. return parseInt(number + '', frombase | 0).toString(tobase | 0);
  14411. };
  14412. php.basename = function (path, suffix) {
  14413. // Returns the filename component of the path
  14414. //
  14415. // version: 1103.1210
  14416. // discuss at: http://phpjs.org/functions/basename
  14417. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14418. // + improved by: Ash Searle (http://hexmen.com/blog/)
  14419. // + improved by: Lincoln Ramsay
  14420. // + improved by: djmix
  14421. // * example 1: \php.basename('/www/site/home.htm', '.htm');
  14422. // * returns 1: 'home'
  14423. // * example 2: \php.basename('ecra.php?p=1');
  14424. // * returns 2: 'ecra.php?p=1'
  14425. var b = path.replace(/^.*[\/\\]/g, '');
  14426. if (typeof(suffix) == 'string' && b.substr(b.length - suffix.length) == suffix) {
  14427. b = b.substr(0, b.length - suffix.length);
  14428. }
  14429. return b;
  14430. };
  14431. php.call_user_func = function (cb) {
  14432. // Call a user function which is the first parameter
  14433. //
  14434. // version: 1103.1210
  14435. // discuss at: http://phpjs.org/functions/call_user_func
  14436. // + original by: Brett Zamir (http://brett-zamir.me)
  14437. // + improved by: Diplom@t (http://difane.com/)
  14438. // + improved by: Brett Zamir (http://brett-zamir.me)
  14439. // * example 1: \php.call_user_func('isNaN', 'a');
  14440. // * returns 1: true
  14441. var func;
  14442. if (typeof cb === 'string') {
  14443. func = (typeof this[cb] === 'function') ? this[cb] : func = (new Function(null, 'return ' + cb))();
  14444. } else if (cb instanceof Array) {
  14445. func = (typeof cb[0] == 'string') ? eval(cb[0] + "['" + cb[1] + "']") : func = cb[0][cb[1]];
  14446. } else if (typeof cb === 'function') {
  14447. func = cb;
  14448. }
  14449. if (typeof func != 'function') {
  14450. throw new Error(func + ' is not a valid function');
  14451. }
  14452. var parameters = Array.prototype.slice.call(arguments, 1);
  14453. return (typeof cb[0] === 'string') ? func.apply(eval(cb[0]), parameters) : (typeof cb[0] !== 'object') ? func.apply(null, parameters) : func.apply(cb[0], parameters);
  14454. };
  14455. php.call_user_func_array = function (cb, parameters) {
  14456. // Call a user function which is the first parameter with the arguments contained in array
  14457. //
  14458. // version: 1103.1210
  14459. // discuss at: http://phpjs.org/functions/call_user_func_array
  14460. // + original by: Thiago Mata (http://thiagomata.blog.com)
  14461. // + revised by: Jon Hohle
  14462. // + improved by: Brett Zamir (http://brett-zamir.me)
  14463. // + improved by: Diplom@t (http://difane.com/)
  14464. // + improved by: Brett Zamir (http://brett-zamir.me)
  14465. // * example 1: \php.call_user_func_array('isNaN', ['a']);
  14466. // * returns 1: true
  14467. // * example 2: \php.call_user_func_array('isNaN', [1]);
  14468. // * returns 2: false
  14469. var func;
  14470. if (typeof cb === 'string') {
  14471. func = (typeof this[cb] === 'function') ? this[cb] : func = (new Function(null, 'return ' + cb))();
  14472. } else if (cb instanceof Array) {
  14473. func = (typeof cb[0] == 'string') ? eval(cb[0] + "['" + cb[1] + "']") : func = cb[0][cb[1]];
  14474. } else if (typeof cb === 'function') {
  14475. func = cb;
  14476. }
  14477. if (typeof func !== 'function') {
  14478. throw new Error(func + ' is not a valid function');
  14479. }
  14480. return (typeof cb[0] === 'string') ? func.apply(eval(cb[0]), parameters) : (typeof cb[0] !== 'object') ? func.apply(null, parameters) : func.apply(cb[0], parameters);
  14481. };
  14482. php.ceil = function (value) {
  14483. // Returns the next highest integer value of the number
  14484. //
  14485. // version: 1103.1210
  14486. // discuss at: http://phpjs.org/functions/ceil
  14487. // + original by: Onno Marsman
  14488. // * example 1: \php.ceil(8723321.4);
  14489. // * returns 1: 8723322
  14490. return Math.ceil(value);
  14491. };
  14492. php.chr = function (codePt) {
  14493. // Converts a codepoint number to a character
  14494. //
  14495. // version: 1103.1210
  14496. // discuss at: http://phpjs.org/functions/chr
  14497. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14498. // + improved by: Brett Zamir (http://brett-zamir.me)
  14499. // * example 1: \php.chr(75);
  14500. // * returns 1: 'K'
  14501. // * example 1: \php.chr(65536) === '\uD800\uDC00';
  14502. // * returns 1: true
  14503. if (codePt > 0xFFFF) { // Create a four-byte string (length 2) since this code point is high
  14504. // enough for the UTF-16 encoding (JavaScript internal use), to
  14505. // require representation with two surrogates (reserved non-characters
  14506. // used for building other characters; the first is "high" and the next "low")
  14507. codePt -= 0x10000;
  14508. return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
  14509. }
  14510. return String.fromCharCode(codePt);
  14511. };
  14512. php.class_exists = function (cls) {
  14513. // Checks if the class exists
  14514. //
  14515. // version: 1103.1210
  14516. // discuss at: http://phpjs.org/functions/class_exists
  14517. // + original by: Brett Zamir (http://brett-zamir.me)
  14518. // * example 1: \php.function class_a() {this.meth1 = function () {return true;}};
  14519. // * example 1: \php.var instance_a = new class_a();
  14520. // * example 1: \php.class_exists('class_a');
  14521. // * returns 1: true
  14522. var i = '';
  14523. cls = this.window[cls]; // Note: will prevent inner classes
  14524. if (typeof cls !== 'function') {
  14525. return false;
  14526. }
  14527. for (i in cls.prototype) {
  14528. return true;
  14529. }
  14530. for (i in cls) { // If static members exist, then consider a "class"
  14531. if (i !== 'prototype') {
  14532. return true;
  14533. }
  14534. }
  14535. if (cls.toSource && cls.toSource().match(/this\./)) {
  14536. // Hackish and non-standard but can probably detect if setting
  14537. // a property (we don't want to test by instantiating as that
  14538. // may have side-effects)
  14539. return true;
  14540. }
  14541. return false;
  14542. };
  14543. php.compact = function () {
  14544. // Creates a hash containing variables and their values
  14545. //
  14546. // version: 1103.1210
  14547. // discuss at: http://phpjs.org/functions/compact
  14548. // + original by: Waldo Malqui Silva
  14549. // + tweaked by: Jack
  14550. // + input by: Brett Zamir (http://brett-zamir.me)
  14551. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14552. // * example 1: \php.var1 = 'Kevin'; var2 = 'van'; var3 = 'Zonneveld';
  14553. // * example 1: \php.compact('var1', 'var2', 'var3');
  14554. // * returns 1: {'var1': 'Kevin', 'var2': 'van', 'var3': 'Zonneveld'}
  14555. var matrix = {},
  14556. that = this;
  14557. var process = function (value) {
  14558. var i = 0,
  14559. l = value.length,
  14560. key_value = '';
  14561. for (i = 0; i < l; i++) {
  14562. key_value = value[i];
  14563. if (key_value instanceof Array) {
  14564. process(key_value);
  14565. } else {
  14566. if (typeof that.window[key_value] !== 'undefined') {
  14567. matrix[key_value] = that.window[key_value];
  14568. }
  14569. }
  14570. }
  14571. return true;
  14572. };
  14573. process(arguments);
  14574. return matrix;
  14575. };
  14576. php.count = function (mixed_var, mode) {
  14577. // Count the number of elements in a variable (usually an array)
  14578. //
  14579. // version: 1103.1210
  14580. // discuss at: http://phpjs.org/functions/count
  14581. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14582. // + input by: Waldo Malqui Silva
  14583. // + bugfixed by: Soren Hansen
  14584. // + input by: merabi
  14585. // + improved by: Brett Zamir (http://brett-zamir.me)
  14586. // + bugfixed by: Olivier Louvignes (http://mg-crea.com/)
  14587. // * example 1: \php.count([[0,0],[0,-4]], 'COUNT_RECURSIVE');
  14588. // * returns 1: 6
  14589. // * example 2: \php.count({'one' : [1,2,3,4,5]}, 'COUNT_RECURSIVE');
  14590. // * returns 2: 6
  14591. var key, cnt = 0;
  14592. if (mixed_var === null || typeof mixed_var === 'undefined') {
  14593. return 0;
  14594. } else if (mixed_var.constructor !== Array && mixed_var.constructor !== Object) {
  14595. return 1;
  14596. }
  14597. if (mode === 'COUNT_RECURSIVE') {
  14598. mode = 1;
  14599. }
  14600. if (mode != 1) {
  14601. mode = 0;
  14602. }
  14603. for (key in mixed_var) {
  14604. if (mixed_var.hasOwnProperty(key)) {
  14605. cnt++;
  14606. if (mode == 1 && mixed_var[key] && (mixed_var[key].constructor === Array || mixed_var[key].constructor === Object)) {
  14607. cnt += this.count(mixed_var[key], 1);
  14608. }
  14609. }
  14610. }
  14611. return cnt;
  14612. };
  14613. php.crc32 = function (str) {
  14614. // Calculate the crc32 polynomial of a string
  14615. //
  14616. // version: 1103.1210
  14617. // discuss at: http://phpjs.org/functions/crc32
  14618. // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
  14619. // + improved by: T0bsn
  14620. // - depends on: utf8_encode
  14621. // * example 1: \php.crc32('Kevin van Zonneveld');
  14622. // * returns 1: 1249991249
  14623. str = this.utf8_encode(str);
  14624. var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";
  14625. var crc = 0;
  14626. var x = 0;
  14627. var y = 0;
  14628. crc = crc ^ (-1);
  14629. for (var i = 0, iTop = str.length; i < iTop; i++) {
  14630. y = (crc ^ str.charCodeAt(i)) & 0xFF;
  14631. x = "0x" + table.substr(y * 9, 8);
  14632. crc = (crc >>> 8) ^ x;
  14633. }
  14634. return crc ^ (-1);
  14635. };
  14636. php.date = function (format, timestamp) {
  14637. // Format a local date/time
  14638. //
  14639. // version: 1103.1210
  14640. // discuss at: http://phpjs.org/functions/date
  14641. // + original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
  14642. // + parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
  14643. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14644. // + improved by: MeEtc (http://yass.meetcweb.com)
  14645. // + improved by: Brad Touesnard
  14646. // + improved by: Tim Wiel
  14647. // + improved by: Bryan Elliott
  14648. //
  14649. // + improved by: Brett Zamir (http://brett-zamir.me)
  14650. // + improved by: David Randall
  14651. // + input by: Brett Zamir (http://brett-zamir.me)
  14652. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14653. // + improved by: Brett Zamir (http://brett-zamir.me)
  14654. // + improved by: Brett Zamir (http://brett-zamir.me)
  14655. // + improved by: Theriault
  14656. // + derived from: gettimeofday
  14657. // + input by: majak
  14658. // + bugfixed by: majak
  14659. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14660. // + input by: Alex
  14661. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  14662. // + improved by: Theriault
  14663. // + improved by: Brett Zamir (http://brett-zamir.me)
  14664. // + improved by: Theriault
  14665. // + improved by: Thomas Beaucourt (http://www.webapp.fr)
  14666. // + improved by: JT
  14667. // + improved by: Theriault
  14668. // + improved by: Rafał Kukawski (http://blog.kukawski.pl)
  14669. // % note 1: Uses global: php_js to store the default timezone
  14670. // % note 2: Although the function potentially allows timezone info (see notes), it currently does not set
  14671. // % note 2: per a timezone specified by date_default_timezone_set(). Implementers might use
  14672. // % note 2: this.php_js.currentTimezoneOffset and this.php_js.currentTimezoneDST set by that function
  14673. // % note 2: in order to adjust the dates in this function (or our other date functions!) accordingly
  14674. // * example 1: \php.date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
  14675. // * returns 1: '09:09:40 m is month'
  14676. // * example 2: \php.date('F j, Y, g:i a', 1062462400);
  14677. // * returns 2: 'September 2, 2003, 2:26 am'
  14678. // * example 3: \php.date('Y W o', 1062462400);
  14679. // * returns 3: '2003 36 2003'
  14680. // * example 4: x = date('Y m d', (new Date()).getTime()/1000);
  14681. // * example 4: (x+'').length == 10 // 2009 01 09
  14682. // * returns 4: true
  14683. // * example 5: \php.date('W', 1104534000);
  14684. // * returns 5: '53'
  14685. // * example 6: \php.date('B t', 1104534000);
  14686. // * returns 6: '999 31'
  14687. // * example 7: \php.date('W U', 1293750000.82); // 2010-12-31
  14688. // * returns 7: '52 1293750000'
  14689. // * example 8: \php.date('W', 1293836400); // 2011-01-01
  14690. // * returns 8: '52'
  14691. // * example 9: \php.date('W Y-m-d', 1293974054); // 2011-01-02
  14692. // * returns 9: '52 2011-01-02'
  14693. var that = this,
  14694. jsdate, f, formatChr = /\\?([a-z])/gi,
  14695. formatChrCb,
  14696. // Keep this here (works, but for code commented-out
  14697. // below for file size reasons)
  14698. //, tal= [],
  14699. _pad = function (n, c) {
  14700. if ((n = n + "").length < c) {
  14701. return new Array((++c) - n.length).join("0") + n;
  14702. } else {
  14703. return n;
  14704. }
  14705. },
  14706. txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  14707. txt_ordin = {
  14708. 1: "st",
  14709. 2: "nd",
  14710. 3: "rd",
  14711. 21: "st",
  14712. 22: "nd",
  14713. 23: "rd",
  14714. 31: "st"
  14715. };
  14716. formatChrCb = function (t, s) {
  14717. return f[t] ? f[t]() : s;
  14718. };
  14719. f = {
  14720. // Day
  14721. d: function () { // Day of month w/leading 0; 01..31
  14722. return _pad(f.j(), 2);
  14723. },
  14724. D: function () { // Shorthand day name; Mon...Sun
  14725. return f.l().slice(0, 3);
  14726. },
  14727. j: function () { // Day of month; 1..31
  14728. return jsdate.getDate();
  14729. },
  14730. l: function () { // Full day name; Monday...Sunday
  14731. return txt_words[f.w()] + 'day';
  14732. },
  14733. N: function () { // ISO-8601 day of week; 1[Mon]..7[Sun]
  14734. return f.w() || 7;
  14735. },
  14736. S: function () { // Ordinal suffix for day of month; st, nd, rd, th
  14737. return txt_ordin[f.j()] || 'th';
  14738. },
  14739. w: function () { // Day of week; 0[Sun]..6[Sat]
  14740. return jsdate.getDay();
  14741. },
  14742. z: function () { // Day of year; 0..365
  14743. var a = new Date(f.Y(), f.n() - 1, f.j()),
  14744. b = new Date(f.Y(), 0, 1);
  14745. return Math.round((a - b) / 864e5) + 1;
  14746. },
  14747. // Week
  14748. W: function () { // ISO-8601 week number
  14749. var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3),
  14750. b = new Date(a.getFullYear(), 0, 4);
  14751. return 1 + Math.round((a - b) / 864e5 / 7);
  14752. },
  14753. // Month
  14754. F: function () { // Full month name; January...December
  14755. return txt_words[6 + f.n()];
  14756. },
  14757. m: function () { // Month w/leading 0; 01...12
  14758. return _pad(f.n(), 2);
  14759. },
  14760. M: function () { // Shorthand month name; Jan...Dec
  14761. return f.F().slice(0, 3);
  14762. },
  14763. n: function () { // Month; 1...12
  14764. return jsdate.getMonth() + 1;
  14765. },
  14766. t: function () { // Days in month; 28...31
  14767. return (new Date(f.Y(), f.n(), 0)).getDate();
  14768. },
  14769. // Year
  14770. L: function () { // Is leap year?; 0 or 1
  14771. return new Date(f.Y(), 1, 29).getMonth() === 1 | 0;
  14772. },
  14773. o: function () { // ISO-8601 year
  14774. var n = f.n(),
  14775. W = f.W(),
  14776. Y = f.Y();
  14777. return Y + (n === 12 && W < 9 ? -1 : n === 1 && W > 9);
  14778. },
  14779. Y: function () { // Full year; e.g. 1980...2010
  14780. return jsdate.getFullYear();
  14781. },
  14782. y: function () { // Last two digits of year; 00...99
  14783. return (f.Y() + "").slice(-2);
  14784. },
  14785. // Time
  14786. a: function () { // am or pm
  14787. return jsdate.getHours() > 11 ? "pm" : "am";
  14788. },
  14789. A: function () { // AM or PM
  14790. return f.a().toUpperCase();
  14791. },
  14792. B: function () { // Swatch Internet time; 000..999
  14793. var H = jsdate.getUTCHours() * 36e2,
  14794. // Hours
  14795. i = jsdate.getUTCMinutes() * 60,
  14796. // Minutes
  14797. s = jsdate.getUTCSeconds(); // Seconds
  14798. return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3);
  14799. },
  14800. g: function () { // 12-Hours; 1..12
  14801. return f.G() % 12 || 12;
  14802. },
  14803. G: function () { // 24-Hours; 0..23
  14804. return jsdate.getHours();
  14805. },
  14806. h: function () { // 12-Hours w/leading 0; 01..12
  14807. return _pad(f.g(), 2);
  14808. },
  14809. H: function () { // 24-Hours w/leading 0; 00..23
  14810. return _pad(f.G(), 2);
  14811. },
  14812. i: function () { // Minutes w/leading 0; 00..59
  14813. return _pad(jsdate.getMinutes(), 2);
  14814. },
  14815. s: function () { // Seconds w/leading 0; 00..59
  14816. return _pad(jsdate.getSeconds(), 2);
  14817. },
  14818. u: function () { // Microseconds; 000000-999000
  14819. return _pad(jsdate.getMilliseconds() * 1000, 6);
  14820. },
  14821. // Timezone
  14822. e: function () { // Timezone identifier; e.g. Atlantic/Azores, ...
  14823. // The following works, but requires inclusion of the very large
  14824. // timezone_abbreviations_list() function.
  14825. /* return this.date_default_timezone_get();
  14826. */
  14827. throw 'Not supported (see source code of date() for timezone on how to add support)';
  14828. },
  14829. I: function () { // DST observed?; 0 or 1
  14830. // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
  14831. // If they are not equal, then DST is observed.
  14832. var a = new Date(f.Y(), 0),
  14833. // Jan 1
  14834. c = Date.UTC(f.Y(), 0),
  14835. // Jan 1 UTC
  14836. b = new Date(f.Y(), 6),
  14837. // Jul 1
  14838. d = Date.UTC(f.Y(), 6); // Jul 1 UTC
  14839. return 0 + ((a - c) !== (b - d));
  14840. },
  14841. O: function () { // Difference to GMT in hour format; e.g. +0200
  14842. var a = jsdate.getTimezoneOffset();
  14843. return (a > 0 ? "-" : "+") + _pad(Math.abs(a / 60 * 100), 4);
  14844. },
  14845. P: function () { // Difference to GMT w/colon; e.g. +02:00
  14846. var O = f.O();
  14847. return (O.substr(0, 3) + ":" + O.substr(3, 2));
  14848. },
  14849. T: function () { // Timezone abbreviation; e.g. EST, MDT, ...
  14850. // The following works, but requires inclusion of the very
  14851. // large timezone_abbreviations_list() function.
  14852. /* var abbr = '', i = 0, os = 0, default = 0;
  14853. if (!tal.length) {
  14854. tal = that.timezone_abbreviations_list();
  14855. }
  14856. if (that.php_js && that.php_js.default_timezone) {
  14857. default = that.php_js.default_timezone;
  14858. for (abbr in tal) {
  14859. for (i=0; i < tal[abbr].length; i++) {
  14860. if (tal[abbr][i].timezone_id === default) {
  14861. return abbr.toUpperCase();
  14862. }
  14863. }
  14864. }
  14865. }
  14866. for (abbr in tal) {
  14867. for (i = 0; i < tal[abbr].length; i++) {
  14868. os = -jsdate.getTimezoneOffset() * 60;
  14869. if (tal[abbr][i].offset === os) {
  14870. return abbr.toUpperCase();
  14871. }
  14872. }
  14873. }
  14874. */
  14875. return 'UTC';
  14876. },
  14877. Z: function () { // Timezone offset in seconds (-43200...50400)
  14878. return -jsdate.getTimezoneOffset() * 60;
  14879. },
  14880. // Full Date/Time
  14881. c: function () { // ISO-8601 date.
  14882. return 'Y-m-d\\Th:i:sP'.replace(formatChr, formatChrCb);
  14883. },
  14884. r: function () { // RFC 2822
  14885. return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);
  14886. },
  14887. U: function () { // Seconds since UNIX epoch
  14888. return jsdate.getTime() / 1000 | 0;
  14889. }
  14890. };
  14891. this.date = function (format, timestamp) {
  14892. that = this;
  14893. jsdate = ((typeof timestamp === 'undefined') ? new Date() : // Not provided
  14894. (timestamp instanceof Date) ? new Date(timestamp) : // JS Date()
  14895. new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
  14896. );
  14897. return format.replace(formatChr, formatChrCb);
  14898. };
  14899. return this.date(format, timestamp);
  14900. };
  14901. php.dirname = function (path) {
  14902. // Returns the directory name component of the path
  14903. //
  14904. // version: 1103.1210
  14905. // discuss at: http://phpjs.org/functions/dirname
  14906. // + original by: Ozh
  14907. // + improved by: XoraX (http://www.xorax.info)
  14908. // * example 1: \php.dirname('/etc/passwd');
  14909. // * returns 1: '/etc'
  14910. // * example 2: \php.dirname('c:/Temp/x');
  14911. // * returns 2: 'c:/Temp'
  14912. // * example 3: \php.dirname('/dir/test/');
  14913. // * returns 3: '/dir'
  14914. return path.replace(/\\/g, '/').replace(/\/[^\/]*\/?$/, '');
  14915. };
  14916. php.empty = function (mixed_var) {
  14917. // !No description available for empty. @php.js developers: Please update the function summary text file.
  14918. //
  14919. // version: 1103.1210
  14920. // discuss at: http://phpjs.org/functions/empty
  14921. // + original by: Philippe Baumann
  14922. // + input by: Onno Marsman
  14923. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14924. // + input by: LH
  14925. // + improved by: Onno Marsman
  14926. // + improved by: Francesco
  14927. // + improved by: Marc Jansen
  14928. // + input by: Stoyan Kyosev (http://www.svest.org/)
  14929. // * example 1: \php.empty(null);
  14930. // * returns 1: true
  14931. // * example 2: \php.empty(undefined);
  14932. // * returns 2: true
  14933. // * example 3: \php.empty([]);
  14934. // * returns 3: true
  14935. // * example 4: \php.empty({});
  14936. // * returns 4: true
  14937. // * example 5: \php.empty({'aFunc' : function () { alert('humpty'); } });
  14938. // * returns 5: false
  14939. var key;
  14940. if (mixed_var === "" || mixed_var === 0 || mixed_var === "0" || mixed_var === null || mixed_var === false || typeof mixed_var === 'undefined') {
  14941. return true;
  14942. }
  14943. if (typeof mixed_var == 'object') {
  14944. for (key in mixed_var) {
  14945. return false;
  14946. }
  14947. return true;
  14948. }
  14949. return false;
  14950. };
  14951. php.end = function (arr) {
  14952. // Advances array argument's internal pointer to the last element and return it
  14953. //
  14954. // version: 1103.1210
  14955. // discuss at: http://phpjs.org/functions/end
  14956. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14957. // + bugfixed by: Legaev Andrey
  14958. // + revised by: J A R
  14959. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14960. // + restored by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  14961. // + revised by: Brett Zamir (http://brett-zamir.me)
  14962. // % note 1: Uses global: php_js to store the array pointer
  14963. // * example 1: \php.end({0: 'Kevin', 1: 'van', 2: 'Zonneveld'});
  14964. // * returns 1: 'Zonneveld'
  14965. // * example 2: \php.end(['Kevin', 'van', 'Zonneveld']);
  14966. // * returns 2: 'Zonneveld'
  14967. // BEGIN REDUNDANT
  14968. this.php_js = this.php_js || {};
  14969. this.php_js.pointers = this.php_js.pointers || [];
  14970. var indexOf = function (value) {
  14971. for (var i = 0, length = this.length; i < length; i++) {
  14972. if (this[i] === value) {
  14973. return i;
  14974. }
  14975. }
  14976. return -1;
  14977. };
  14978. // END REDUNDANT
  14979. var pointers = this.php_js.pointers;
  14980. if (!pointers.indexOf) {
  14981. pointers.indexOf = indexOf;
  14982. }
  14983. if (pointers.indexOf(arr) === -1) {
  14984. pointers.push(arr, 0);
  14985. }
  14986. var arrpos = pointers.indexOf(arr);
  14987. if (!(arr instanceof Array)) {
  14988. var ct = 0;
  14989. for (var k in arr) {
  14990. ct++;
  14991. var val = arr[k];
  14992. }
  14993. if (ct === 0) {
  14994. return false; // Empty
  14995. }
  14996. pointers[arrpos + 1] = ct - 1;
  14997. return val;
  14998. }
  14999. if (arr.length === 0) {
  15000. return false;
  15001. }
  15002. pointers[arrpos + 1] = arr.length - 1;
  15003. return arr[pointers[arrpos + 1]];
  15004. };
  15005. php.extract = function (arr, type, prefix) {
  15006. // Imports variables into symbol table from an array
  15007. //
  15008. // version: 1103.1210
  15009. // discuss at: http://phpjs.org/functions/extract
  15010. // + original by: Brett Zamir (http://brett-zamir.me)
  15011. // % note 1: Only works by extracting into global context (whether called in the global scope or
  15012. // % note 1: within a function); also, the EXTR_REFS flag I believe can't be made to work
  15013. // * example 1: \php.size = 'large';
  15014. // * example 1: \php.var_array = {'color' : 'blue', 'size' : 'medium', 'shape' : 'sphere'};
  15015. // * example 1: \php.extract(var_array, 'EXTR_PREFIX_SAME', 'wddx');
  15016. // * example 1: \php.color+'-'+size+'-'+shape+'-'+wddx_size;
  15017. // * returns 1: 'blue-large-sphere-medium'
  15018. if (arr instanceof Array && (type !== 'EXTR_PREFIX_ALL' && type !== 'EXTR_PREFIX_INVALID')) {
  15019. return 0;
  15020. }
  15021. var targetObj = this.window;
  15022. if (this.php_js && this.php_js.ini && this.php_js.ini['phpjs.extractTargetObj'] && this.php_js.ini['phpjs.extractTargetObj'].local_value) { // Allow designated object to be used instead of window
  15023. targetObj = this.php_js.ini['phpjs.extractTargetObj'].local_value;
  15024. }
  15025. var chng = 0;
  15026. for (var i in arr) {
  15027. var validIdent = /^[_a-zA-Z$][\w|$]*$/; // TODO: Refine regexp to allow JS 1.5+ Unicode identifiers
  15028. var prefixed = prefix + '_' + i;
  15029. try {
  15030. switch (type) {
  15031. case 'EXTR_PREFIX_SAME' || 2:
  15032. if (targetObj[i] !== undefined) {
  15033. if (prefixed.match(validIdent) !== null) {
  15034. targetObj[prefixed] = arr[i];
  15035. ++chng;
  15036. }
  15037. } else {
  15038. targetObj[i] = arr[i];
  15039. ++chng;
  15040. }
  15041. break;
  15042. case 'EXTR_SKIP' || 1:
  15043. if (targetObj[i] === undefined) {
  15044. targetObj[i] = arr[i];
  15045. ++chng;
  15046. }
  15047. break;
  15048. case 'EXTR_PREFIX_ALL' || 3:
  15049. if (prefixed.match(validIdent) !== null) {
  15050. targetObj[prefixed] = arr[i];
  15051. ++chng;
  15052. }
  15053. break;
  15054. case 'EXTR_PREFIX_INVALID' || 4:
  15055. if (i.match(validIdent) !== null) {
  15056. if (prefixed.match(validIdent) !== null) {
  15057. targetObj[prefixed] = arr[i];
  15058. ++chng;
  15059. }
  15060. } else {
  15061. targetObj[i] = arr[i];
  15062. ++chng;
  15063. }
  15064. break;
  15065. case 'EXTR_IF_EXISTS' || 6:
  15066. if (targetObj[i] !== undefined) {
  15067. targetObj[i] = arr[i];
  15068. ++chng;
  15069. }
  15070. break;
  15071. case 'EXTR_PREFIX_IF_EXISTS' || 5:
  15072. if (targetObj[i] !== undefined && prefixed.match(validIdent) !== null) {
  15073. targetObj[prefixed] = arr[i];
  15074. ++chng;
  15075. }
  15076. break;
  15077. case 'EXTR_REFS' || 256:
  15078. throw 'The EXTR_REFS type will not work in JavaScript';
  15079. case 'EXTR_OVERWRITE' || 0:
  15080. // Fall-through
  15081. default:
  15082. targetObj[i] = arr[i];
  15083. ++chng;
  15084. break;
  15085. }
  15086. } catch (e) { // Just won't increment for problem assignments
  15087. }
  15088. }
  15089. return chng;
  15090. };
  15091. php.floor = function (value) {
  15092. // Returns the next lowest integer value from the number
  15093. //
  15094. // version: 1103.1210
  15095. // discuss at: http://phpjs.org/functions/floor
  15096. // + original by: Onno Marsman
  15097. // * example 1: \php.floor(8723321.4);
  15098. // * returns 1: 8723321
  15099. return Math.floor(value);
  15100. };
  15101. php.get_class = function (obj) {
  15102. // Retrieves the class name
  15103. //
  15104. // version: 1103.1210
  15105. // discuss at: http://phpjs.org/functions/get_class
  15106. // + original by: Ates Goral (http://magnetiq.com)
  15107. // + improved by: David James
  15108. // * example 1: \php.get_class(new (function MyClass() {}));
  15109. // * returns 1: "MyClass"
  15110. // * example 2: \php.get_class({});
  15111. // * returns 2: "Object"
  15112. // * example 3: \php.get_class([]);
  15113. // * returns 3: false
  15114. // * example 4: \php.get_class(42);
  15115. // * returns 4: false
  15116. // * example 5: \php.get_class(window);
  15117. // * returns 5: false
  15118. // * example 6: \php.get_class(function MyFunction() {});
  15119. // * returns 6: false
  15120. if (obj instanceof Object && !(obj instanceof Array) && !(obj instanceof Function) && obj.constructor && obj != this.window) {
  15121. var arr = obj.constructor.toString().match(/function\s*(\w+)/);
  15122. if (arr && arr.length == 2) {
  15123. return arr[1];
  15124. }
  15125. }
  15126. return false;
  15127. };
  15128. php.get_html_translation_table = function (table, quote_style) {
  15129. // Returns the internal translation table used by htmlspecialchars and htmlentities
  15130. //
  15131. // version: 1103.1210
  15132. // discuss at: http://phpjs.org/functions/get_html_translation_table
  15133. // + original by: Philip Peterson
  15134. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15135. // + bugfixed by: noname
  15136. // + bugfixed by: Alex
  15137. // + bugfixed by: Marco
  15138. // + bugfixed by: madipta
  15139. // + improved by: KELAN
  15140. // + improved by: Brett Zamir (http://brett-zamir.me)
  15141. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15142. // + input by: Frank Forte
  15143. // + bugfixed by: T.Wild
  15144. // + input by: Ratheous
  15145. // % note: It has been decided that we're not going to add global
  15146. // % note: dependencies to php.js, meaning the constants are not
  15147. // % note: real constants, but strings instead. Integers are also supported if someone
  15148. // % note: chooses to create the constants themselves.
  15149. // * example 1: \php.get_html_translation_table('HTML_SPECIALCHARS');
  15150. // * returns 1: {'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;'}
  15151. var entities = {},
  15152. hash_map = {},
  15153. decimal = 0,
  15154. symbol = '';
  15155. var constMappingTable = {},
  15156. constMappingQuoteStyle = {};
  15157. var useTable = {},
  15158. useQuoteStyle = {};
  15159. // Translate arguments
  15160. constMappingTable[0] = 'HTML_SPECIALCHARS';
  15161. constMappingTable[1] = 'HTML_ENTITIES';
  15162. constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
  15163. constMappingQuoteStyle[2] = 'ENT_COMPAT';
  15164. constMappingQuoteStyle[3] = 'ENT_QUOTES';
  15165. useTable = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
  15166. useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';
  15167. if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
  15168. throw new Error("Table: " + useTable + ' not supported');
  15169. // return false;
  15170. }
  15171. entities['38'] = '&amp;';
  15172. if (useTable === 'HTML_ENTITIES') {
  15173. entities['160'] = '&nbsp;';
  15174. entities['161'] = '&iexcl;';
  15175. entities['162'] = '&cent;';
  15176. entities['163'] = '&pound;';
  15177. entities['164'] = '&curren;';
  15178. entities['165'] = '&yen;';
  15179. entities['166'] = '&brvbar;';
  15180. entities['167'] = '&sect;';
  15181. entities['168'] = '&uml;';
  15182. entities['169'] = '&copy;';
  15183. entities['170'] = '&ordf;';
  15184. entities['171'] = '&laquo;';
  15185. entities['172'] = '&not;';
  15186. entities['173'] = '&shy;';
  15187. entities['174'] = '&reg;';
  15188. entities['175'] = '&macr;';
  15189. entities['176'] = '&deg;';
  15190. entities['177'] = '&plusmn;';
  15191. entities['178'] = '&sup2;';
  15192. entities['179'] = '&sup3;';
  15193. entities['180'] = '&acute;';
  15194. entities['181'] = '&micro;';
  15195. entities['182'] = '&para;';
  15196. entities['183'] = '&middot;';
  15197. entities['184'] = '&cedil;';
  15198. entities['185'] = '&sup1;';
  15199. entities['186'] = '&ordm;';
  15200. entities['187'] = '&raquo;';
  15201. entities['188'] = '&frac14;';
  15202. entities['189'] = '&frac12;';
  15203. entities['190'] = '&frac34;';
  15204. entities['191'] = '&iquest;';
  15205. entities['192'] = '&Agrave;';
  15206. entities['193'] = '&Aacute;';
  15207. entities['194'] = '&Acirc;';
  15208. entities['195'] = '&Atilde;';
  15209. entities['196'] = '&Auml;';
  15210. entities['197'] = '&Aring;';
  15211. entities['198'] = '&AElig;';
  15212. entities['199'] = '&Ccedil;';
  15213. entities['200'] = '&Egrave;';
  15214. entities['201'] = '&Eacute;';
  15215. entities['202'] = '&Ecirc;';
  15216. entities['203'] = '&Euml;';
  15217. entities['204'] = '&Igrave;';
  15218. entities['205'] = '&Iacute;';
  15219. entities['206'] = '&Icirc;';
  15220. entities['207'] = '&Iuml;';
  15221. entities['208'] = '&ETH;';
  15222. entities['209'] = '&Ntilde;';
  15223. entities['210'] = '&Ograve;';
  15224. entities['211'] = '&Oacute;';
  15225. entities['212'] = '&Ocirc;';
  15226. entities['213'] = '&Otilde;';
  15227. entities['214'] = '&Ouml;';
  15228. entities['215'] = '&times;';
  15229. entities['216'] = '&Oslash;';
  15230. entities['217'] = '&Ugrave;';
  15231. entities['218'] = '&Uacute;';
  15232. entities['219'] = '&Ucirc;';
  15233. entities['220'] = '&Uuml;';
  15234. entities['221'] = '&Yacute;';
  15235. entities['222'] = '&THORN;';
  15236. entities['223'] = '&szlig;';
  15237. entities['224'] = '&agrave;';
  15238. entities['225'] = '&aacute;';
  15239. entities['226'] = '&acirc;';
  15240. entities['227'] = '&atilde;';
  15241. entities['228'] = '&auml;';
  15242. entities['229'] = '&aring;';
  15243. entities['230'] = '&aelig;';
  15244. entities['231'] = '&ccedil;';
  15245. entities['232'] = '&egrave;';
  15246. entities['233'] = '&eacute;';
  15247. entities['234'] = '&ecirc;';
  15248. entities['235'] = '&euml;';
  15249. entities['236'] = '&igrave;';
  15250. entities['237'] = '&iacute;';
  15251. entities['238'] = '&icirc;';
  15252. entities['239'] = '&iuml;';
  15253. entities['240'] = '&eth;';
  15254. entities['241'] = '&ntilde;';
  15255. entities['242'] = '&ograve;';
  15256. entities['243'] = '&oacute;';
  15257. entities['244'] = '&ocirc;';
  15258. entities['245'] = '&otilde;';
  15259. entities['246'] = '&ouml;';
  15260. entities['247'] = '&divide;';
  15261. entities['248'] = '&oslash;';
  15262. entities['249'] = '&ugrave;';
  15263. entities['250'] = '&uacute;';
  15264. entities['251'] = '&ucirc;';
  15265. entities['252'] = '&uuml;';
  15266. entities['253'] = '&yacute;';
  15267. entities['254'] = '&thorn;';
  15268. entities['255'] = '&yuml;';
  15269. }
  15270. if (useQuoteStyle !== 'ENT_NOQUOTES') {
  15271. entities['34'] = '&quot;';
  15272. }
  15273. if (useQuoteStyle === 'ENT_QUOTES') {
  15274. entities['39'] = '&#39;';
  15275. }
  15276. entities['60'] = '&lt;';
  15277. entities['62'] = '&gt;';
  15278. // ascii decimals to real symbols
  15279. for (decimal in entities) {
  15280. symbol = String.fromCharCode(decimal);
  15281. hash_map[symbol] = entities[decimal];
  15282. }
  15283. return hash_map;
  15284. };
  15285. php.gettype = function (mixed_var) {
  15286. // Returns the type of the variable
  15287. //
  15288. // version: 1103.1210
  15289. // discuss at: http://phpjs.org/functions/gettype
  15290. // + original by: Paulo Freitas
  15291. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15292. // + improved by: Douglas Crockford (http://javascript.crockford.com)
  15293. // + input by: KELAN
  15294. // + improved by: Brett Zamir (http://brett-zamir.me)
  15295. // - depends on: is_float
  15296. // % note 1: 1.0 is simplified to 1 before it can be accessed by the function, this makes
  15297. // % note 1: it different from the PHP implementation. We can't fix this unfortunately.
  15298. // * example 1: \php.gettype(1);
  15299. // * returns 1: 'integer'
  15300. // * example 2: \php.gettype(undefined);
  15301. // * returns 2: 'undefined'
  15302. // * example 3: \php.gettype({0: 'Kevin van Zonneveld'});
  15303. // * returns 3: 'array'
  15304. // * example 4: \php.gettype('foo');
  15305. // * returns 4: 'string'
  15306. // * example 5: \php.gettype({0: function () {return false;}});
  15307. // * returns 5: 'array'
  15308. var s = typeof mixed_var,
  15309. name;
  15310. var getFuncName = function (fn) {
  15311. var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
  15312. if (!name) {
  15313. return '(Anonymous)';
  15314. }
  15315. return name[1];
  15316. };
  15317. if (s === 'object') {
  15318. if (mixed_var !== null) { // From: http://javascript.crockford.com/remedial.html
  15319. if (typeof mixed_var.length === 'number' && !(mixed_var.propertyIsEnumerable('length')) && typeof mixed_var.splice === 'function') {
  15320. s = 'array';
  15321. } else if (mixed_var.constructor && getFuncName(mixed_var.constructor)) {
  15322. name = getFuncName(mixed_var.constructor);
  15323. if (name === 'Date') {
  15324. s = 'date'; // not in PHP
  15325. } else if (name === 'RegExp') {
  15326. s = 'regexp'; // not in PHP
  15327. } else if (name === 'PHPJS_Resource') { // Check against our own resource constructor
  15328. s = 'resource';
  15329. }
  15330. }
  15331. } else {
  15332. s = 'null';
  15333. }
  15334. } else if (s === 'number') {
  15335. s = this.is_float(mixed_var) ? 'double' : 'integer';
  15336. }
  15337. return s;
  15338. };
  15339. php.html_entity_decode = function (string, quote_style) {
  15340. // Convert all HTML entities to their applicable characters
  15341. //
  15342. // version: 1103.1210
  15343. // discuss at: http://phpjs.org/functions/html_entity_decode
  15344. // + original by: john (http://www.jd-tech.net)
  15345. // + input by: ger
  15346. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15347. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15348. // + bugfixed by: Onno Marsman
  15349. // + improved by: marc andreu
  15350. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15351. // + input by: Ratheous
  15352. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15353. // + input by: Nick Kolosov (http://sammy.ru)
  15354. // + bugfixed by: Fox
  15355. // - depends on: get_html_translation_table
  15356. // * example 1: \php.html_entity_decode('Kevin &amp; van Zonneveld');
  15357. // * returns 1: 'Kevin & van Zonneveld'
  15358. // * example 2: \php.html_entity_decode('&amp;lt;');
  15359. // * returns 2: '&lt;'
  15360. var hash_map = {},
  15361. symbol = '',
  15362. tmp_str = '',
  15363. entity = '';
  15364. tmp_str = string.toString();
  15365. if (false === (hash_map = this.get_html_translation_table('HTML_ENTITIES', quote_style))) {
  15366. return false;
  15367. }
  15368. // fix &amp; problem
  15369. // http://phpjs.org/functions/get_html_translation_table:416#comment_97660
  15370. delete(hash_map['&']);
  15371. hash_map['&'] = '&amp;';
  15372. for (symbol in hash_map) {
  15373. entity = hash_map[symbol];
  15374. tmp_str = tmp_str.split(entity).join(symbol);
  15375. }
  15376. tmp_str = tmp_str.split('&#039;').join("'");
  15377. return tmp_str;
  15378. };
  15379. php.htmlentities = function (string, quote_style) {
  15380. // Convert all applicable characters to HTML entities
  15381. //
  15382. // version: 1103.1210
  15383. // discuss at: http://phpjs.org/functions/htmlentities
  15384. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15385. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15386. // + improved by: nobbler
  15387. // + tweaked by: Jack
  15388. // + bugfixed by: Onno Marsman
  15389. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15390. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15391. // + input by: Ratheous
  15392. // - depends on: get_html_translation_table
  15393. // * example 1: \php.htmlentities('Kevin & van Zonneveld');
  15394. // * returns 1: 'Kevin &amp; van Zonneveld'
  15395. // * example 2: \php.htmlentities("foo'bar","ENT_QUOTES");
  15396. // * returns 2: 'foo&#039;bar'
  15397. var hash_map = {},
  15398. symbol = '',
  15399. tmp_str = '',
  15400. entity = '';
  15401. tmp_str = string.toString();
  15402. if (false === (hash_map = this.get_html_translation_table('HTML_ENTITIES', quote_style))) {
  15403. return false;
  15404. }
  15405. hash_map["'"] = '&#039;';
  15406. for (symbol in hash_map) {
  15407. entity = hash_map[symbol];
  15408. tmp_str = tmp_str.split(symbol).join(entity);
  15409. }
  15410. return tmp_str;
  15411. };
  15412. php.htmlspecialchars = function (string, quote_style, charset, double_encode) {
  15413. // Convert special characters to HTML entities
  15414. //
  15415. // version: 1103.1210
  15416. // discuss at: http://phpjs.org/functions/htmlspecialchars
  15417. // + original by: Mirek Slugen
  15418. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15419. // + bugfixed by: Nathan
  15420. // + bugfixed by: Arno
  15421. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15422. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15423. // + input by: Ratheous
  15424. // + input by: Mailfaker (http://www.weedem.fr/)
  15425. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  15426. // + input by: felix
  15427. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15428. // % note 1: charset argument not supported
  15429. // * example 1: \php.htmlspecialchars("<a href='test'>Test</a>", 'ENT_QUOTES');
  15430. // * returns 1: '&lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;'
  15431. // * example 2: \php.htmlspecialchars("ab\"c'd", ['ENT_NOQUOTES', 'ENT_QUOTES']);
  15432. // * returns 2: 'ab"c&#039;d'
  15433. // * example 3: \php.htmlspecialchars("my "&entity;" is still here", null, null, false);
  15434. // * returns 3: 'my &quot;&entity;&quot; is still here'
  15435. var optTemp = 0,
  15436. i = 0,
  15437. noquotes = false;
  15438. if (typeof quote_style === 'undefined' || quote_style === null) {
  15439. quote_style = 2;
  15440. }
  15441. if (string === null) {
  15442. string = "";
  15443. }
  15444. string = string.toString();
  15445. if (double_encode !== false) { // Put this first to avoid double-encoding
  15446. string = string.replace(/&/g, '&amp;');
  15447. }
  15448. string = string.replace(/</g, '&lt;').replace(/>/g, '&gt;');
  15449. var OPTS = {
  15450. 'ENT_NOQUOTES': 0,
  15451. 'ENT_HTML_QUOTE_SINGLE': 1,
  15452. 'ENT_HTML_QUOTE_DOUBLE': 2,
  15453. 'ENT_COMPAT': 2,
  15454. 'ENT_QUOTES': 3,
  15455. 'ENT_IGNORE': 4
  15456. };
  15457. if (quote_style === 0) {
  15458. noquotes = true;
  15459. }
  15460. if (typeof quote_style !== 'number') { // Allow for a single string or an array of string flags
  15461. quote_style = [].concat(quote_style);
  15462. for (i = 0; i < quote_style.length; i++) {
  15463. // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
  15464. if (OPTS[quote_style[i]] === 0) {
  15465. noquotes = true;
  15466. } else if (OPTS[quote_style[i]]) {
  15467. optTemp = optTemp | OPTS[quote_style[i]];
  15468. }
  15469. }
  15470. quote_style = optTemp;
  15471. }
  15472. if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) {
  15473. string = string.replace(/'/g, '&#039;');
  15474. }
  15475. if (!noquotes) {
  15476. string = string.replace(/"/g, '&quot;');
  15477. }
  15478. return string;
  15479. };
  15480. php.htmlspecialchars_decode = function (string, quote_style) {
  15481. // Convert special HTML entities back to characters
  15482. //
  15483. // version: 1103.1210
  15484. // discuss at: http://phpjs.org/functions/htmlspecialchars_decode
  15485. // + original by: Mirek Slugen
  15486. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15487. // + bugfixed by: Mateusz "loonquawl" Zalega
  15488. // + input by: ReverseSyntax
  15489. // + input by: Slawomir Kaniecki
  15490. // + input by: Scott Cariss
  15491. // + input by: Francois
  15492. // + bugfixed by: Onno Marsman
  15493. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15494. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15495. // + input by: Ratheous
  15496. // + input by: Mailfaker (http://www.weedem.fr/)
  15497. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  15498. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15499. // * example 1: \php.htmlspecialchars_decode("<p>this -&gt; &quot;</p>", 'ENT_NOQUOTES');
  15500. // * returns 1: '<p>this -> &quot;</p>'
  15501. // * example 2: \php.htmlspecialchars_decode("&amp;quot;");
  15502. // * returns 2: '&quot;'
  15503. var optTemp = 0,
  15504. i = 0,
  15505. noquotes = false;
  15506. if (typeof quote_style === 'undefined') {
  15507. quote_style = 2;
  15508. }
  15509. string = string.toString().replace(/&lt;/g, '<').replace(/&gt;/g, '>');
  15510. var OPTS = {
  15511. 'ENT_NOQUOTES': 0,
  15512. 'ENT_HTML_QUOTE_SINGLE': 1,
  15513. 'ENT_HTML_QUOTE_DOUBLE': 2,
  15514. 'ENT_COMPAT': 2,
  15515. 'ENT_QUOTES': 3,
  15516. 'ENT_IGNORE': 4
  15517. };
  15518. if (quote_style === 0) {
  15519. noquotes = true;
  15520. }
  15521. if (typeof quote_style !== 'number') { // Allow for a single string or an array of string flags
  15522. quote_style = [].concat(quote_style);
  15523. for (i = 0; i < quote_style.length; i++) {
  15524. // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
  15525. if (OPTS[quote_style[i]] === 0) {
  15526. noquotes = true;
  15527. } else if (OPTS[quote_style[i]]) {
  15528. optTemp = optTemp | OPTS[quote_style[i]];
  15529. }
  15530. }
  15531. quote_style = optTemp;
  15532. }
  15533. if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) {
  15534. string = string.replace(/&#0*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should
  15535. // string = string.replace(/&apos;|&#x0*27;/g, "'"); // This would also be useful here, but not a part of PHP
  15536. }
  15537. if (!noquotes) {
  15538. string = string.replace(/&quot;/g, '"');
  15539. }
  15540. // Put this in last place to avoid escape being double-decoded
  15541. string = string.replace(/&amp;/g, '&');
  15542. return string;
  15543. };
  15544. php.http_build_query = function (formdata, numeric_prefix, arg_separator) {
  15545. // Generates a form-encoded query string from an associative array or object.
  15546. //
  15547. // version: 1103.1210
  15548. // discuss at: http://phpjs.org/functions/http_build_query
  15549. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15550. // + improved by: Legaev Andrey
  15551. // + improved by: Michael White (http://getsprink.com)
  15552. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15553. // + improved by: Brett Zamir (http://brett-zamir.me)
  15554. // + revised by: stag019
  15555. // + input by: Dreamer
  15556. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15557. // - depends on: urlencode
  15558. // * example 1: \php.http_build_query({foo: 'bar', php: 'hypertext processor', baz: 'boom', cow: 'milk'}, '', '&amp;');
  15559. // * returns 1: 'foo=bar&amp;php=hypertext+processor&amp;baz=boom&amp;cow=milk'
  15560. // * example 2: \php.http_build_query({'php': 'hypertext processor', 0: 'foo', 1: 'bar', 2: 'baz', 3: 'boom', 'cow': 'milk'}, 'myvar_');
  15561. // * returns 2: 'php=hypertext+processor&myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk'
  15562. var value, key, tmp = [],
  15563. that = this;
  15564. var _http_build_query_helper = function (key, val, arg_separator) {
  15565. var k, tmp = [];
  15566. if (val === true) {
  15567. val = "1";
  15568. } else if (val === false) {
  15569. val = "0";
  15570. }
  15571. if (val !== null && typeof(val) === "object") {
  15572. for (k in val) {
  15573. if (val[k] !== null) {
  15574. tmp.push(_http_build_query_helper(key + "[" + k + "]", val[k], arg_separator));
  15575. }
  15576. }
  15577. return tmp.join(arg_separator);
  15578. } else if (typeof(val) !== "function") {
  15579. return that.urlencode(key) + "=" + that.urlencode(val);
  15580. } else {
  15581. throw new Error('There was an error processing for http_build_query().');
  15582. }
  15583. };
  15584. if (!arg_separator) {
  15585. arg_separator = "&";
  15586. }
  15587. for (key in formdata) {
  15588. value = formdata[key];
  15589. if (numeric_prefix && !isNaN(key)) {
  15590. key = String(numeric_prefix) + key;
  15591. }
  15592. tmp.push(_http_build_query_helper(key, value, arg_separator));
  15593. }
  15594. return tmp.join(arg_separator);
  15595. };
  15596. php.in_array = function (needle, haystack, argStrict) {
  15597. // Checks if the given value exists in the array
  15598. //
  15599. // version: 1103.1210
  15600. // discuss at: http://phpjs.org/functions/in_array
  15601. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15602. // + improved by: vlado houba
  15603. // + input by: Billy
  15604. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15605. // * example 1: \php.in_array('van', ['Kevin', 'van', 'Zonneveld']);
  15606. // * returns 1: true
  15607. // * example 2: \php.in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
  15608. // * returns 2: false
  15609. // * example 3: \php.in_array(1, ['1', '2', '3']);
  15610. // * returns 3: true
  15611. // * example 3: \php.in_array(1, ['1', '2', '3'], false);
  15612. // * returns 3: true
  15613. // * example 4: \php.in_array(1, ['1', '2', '3'], true);
  15614. // * returns 4: false
  15615. var key = '',
  15616. strict = !! argStrict;
  15617. if (strict) {
  15618. for (key in haystack) {
  15619. if (haystack[key] === needle) {
  15620. return true;
  15621. }
  15622. }
  15623. } else {
  15624. for (key in haystack) {
  15625. if (haystack[key] == needle) {
  15626. return true;
  15627. }
  15628. }
  15629. }
  15630. return false;
  15631. };
  15632. php.intval = function (mixed_var, base) {
  15633. // Get the integer value of a variable using the optional base for the conversion
  15634. //
  15635. // version: 1103.1210
  15636. // discuss at: http://phpjs.org/functions/intval
  15637. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15638. // + improved by: stensi
  15639. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15640. // + input by: Matteo
  15641. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15642. // * example 1: \php.intval('Kevin van Zonneveld');
  15643. // * returns 1: 0
  15644. // * example 2: \php.intval(4.2);
  15645. // * returns 2: 4
  15646. // * example 3: \php.intval(42, 8);
  15647. // * returns 3: 42
  15648. // * example 4: \php.intval('09');
  15649. // * returns 4: 9
  15650. // * example 5: \php.intval('1e', 16);
  15651. // * returns 5: 30
  15652. var tmp;
  15653. var type = typeof(mixed_var);
  15654. if (type === 'boolean') {
  15655. return (mixed_var) ? 1 : 0;
  15656. } else if (type === 'string') {
  15657. tmp = parseInt(mixed_var, base || 10);
  15658. return (isNaN(tmp) || !isFinite(tmp)) ? 0 : tmp;
  15659. } else if (type === 'number' && isFinite(mixed_var)) {
  15660. return Math.floor(mixed_var);
  15661. } else {
  15662. return 0;
  15663. }
  15664. };
  15665. php.is_callable = function (v, syntax_only, callable_name) {
  15666. // Returns true if var is callable.
  15667. //
  15668. // version: 1103.1210
  15669. // discuss at: http://phpjs.org/functions/is_callable
  15670. // + original by: Brett Zamir (http://brett-zamir.me)
  15671. // % note 1: The variable callable_name cannot work as a string variable passed by reference as in PHP (since JavaScript does not support passing strings by reference), but instead will take the name of a global variable and set that instead
  15672. // % note 2: When used on an object, depends on a constructor property being kept on the object prototype
  15673. // * example 1: \php.is_callable('is_callable');
  15674. // * returns 1: true
  15675. // * example 2: \php.is_callable('bogusFunction', true);
  15676. // * returns 2:true // gives true because does not do strict checking
  15677. // * example 3: \php.function SomeClass () {}
  15678. // * example 3: SomeClass.prototype.someMethod = function (){};
  15679. // * example 3: \php.var testObj = new SomeClass();
  15680. // * example 3: \php.is_callable([testObj, 'someMethod'], true, 'myVar');
  15681. // * example 3: \php.alert(myVar); // 'SomeClass::someMethod'
  15682. var name = '',
  15683. obj = {},
  15684. method = '';
  15685. var getFuncName = function (fn) {
  15686. var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
  15687. if (!name) {
  15688. return '(Anonymous)';
  15689. }
  15690. return name[1];
  15691. };
  15692. if (typeof v === 'string') {
  15693. obj = this.window;
  15694. method = v;
  15695. name = v;
  15696. } else if (v instanceof Array && v.length === 2 && typeof v[0] === 'object' && typeof v[1] === 'string') {
  15697. obj = v[0];
  15698. method = v[1];
  15699. name = (obj.constructor && getFuncName(obj.constructor)) + '::' + method;
  15700. } else {
  15701. return false;
  15702. }
  15703. if (syntax_only || typeof obj[method] === 'function') {
  15704. if (callable_name) {
  15705. this.window[callable_name] = name;
  15706. }
  15707. return true;
  15708. }
  15709. return false;
  15710. };
  15711. php.is_float = function (mixed_var) {
  15712. // Returns true if variable is float point
  15713. //
  15714. // version: 1103.1210
  15715. // discuss at: http://phpjs.org/functions/is_float
  15716. // + original by: Paulo Freitas
  15717. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15718. // + improved by: WebDevHobo (http://webdevhobo.blogspot.com/)
  15719. // % note 1: 1.0 is simplified to 1 before it can be accessed by the function, this makes
  15720. // % note 1: it different from the PHP implementation. We can't fix this unfortunately.
  15721. // * example 1: \php.is_float(186.31);
  15722. // * returns 1: true
  15723. if (typeof mixed_var !== 'number') {
  15724. return false;
  15725. }
  15726. return !!(mixed_var % 1);
  15727. };
  15728. php.is_int = function (mixed_var) {
  15729. // !No description available for is_int. @php.js developers: Please update the function summary text file.
  15730. //
  15731. // version: 1103.1210
  15732. // discuss at: http://phpjs.org/functions/is_int
  15733. // + original by: Alex
  15734. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15735. // + revised by: Matt Bradley
  15736. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15737. // + improved by: WebDevHobo (http://webdevhobo.blogspot.com/)
  15738. // % note 1: 1.0 is simplified to 1 before it can be accessed by the function, this makes
  15739. // % note 1: it different from the PHP implementation. We can't fix this unfortunately.
  15740. // * example 1: \php.is_int(23)
  15741. // * returns 1: true
  15742. // * example 2: \php.is_int('23')
  15743. // * returns 2: false
  15744. // * example 3: \php.is_int(23.5)
  15745. // * returns 3: false
  15746. // * example 4: \php.is_int(true)
  15747. // * returns 4: false
  15748. if (typeof mixed_var !== 'number') {
  15749. return false;
  15750. }
  15751. return !(mixed_var % 1);
  15752. };
  15753. php.krsort = function (inputArr, sort_flags) {
  15754. // Sort an array by key value in reverse order
  15755. //
  15756. // version: 1103.1210
  15757. // discuss at: http://phpjs.org/functions/krsort
  15758. // + original by: GeekFG (http://geekfg.blogspot.com)
  15759. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15760. // + improved by: Brett Zamir (http://brett-zamir.me)
  15761. // % note 1: The examples are correct, this is a new way
  15762. // % note 2: This function deviates from PHP in returning a copy of the array instead
  15763. // % note 2: of acting by reference and returning true; this was necessary because
  15764. // % note 2: IE does not allow deleting and re-adding of properties without caching
  15765. // % note 2: of property position; you can set the ini of "phpjs.strictForIn" to true to
  15766. // % note 2: get the PHP behavior, but use this only if you are in an environment
  15767. // % note 2: such as Firefox extensions where for-in iteration order is fixed and true
  15768. // % note 2: property deletion is supported. Note that we intend to implement the PHP
  15769. // % note 2: behavior by default if IE ever does allow it; only gives shallow copy since
  15770. // % note 2: is by reference in PHP anyways
  15771. // % note 3: Since JS objects' keys are always strings, and (the
  15772. // % note 3: default) SORT_REGULAR flag distinguishes by key type,
  15773. // % note 3: if the content is a numeric string, we treat the
  15774. // % note 3: "original type" as numeric.
  15775. // - depends on: i18n_loc_get_default
  15776. // * example 1: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  15777. // * example 1: \php.data = krsort(data);
  15778. // * results 1: {d: 'lemon', c: 'apple', b: 'banana', a: 'orange'}
  15779. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  15780. // * example 2: \php.data = {2: 'van', 3: 'Zonneveld', 1: 'Kevin'};
  15781. // * example 2: \php.krsort(data);
  15782. // * results 2: data == {3: 'Kevin', 2: 'van', 1: 'Zonneveld'}
  15783. // * returns 2: true
  15784. var tmp_arr = {},
  15785. keys = [],
  15786. sorter, i, k, that = this,
  15787. strictForIn = false,
  15788. populateArr = {};
  15789. switch (sort_flags) {
  15790. case 'SORT_STRING':
  15791. // compare items as strings
  15792. sorter = function (a, b) {
  15793. return that.strnatcmp(b, a);
  15794. };
  15795. break;
  15796. case 'SORT_LOCALE_STRING':
  15797. // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
  15798. var loc = this.i18n_loc_get_default();
  15799. sorter = this.php_js.i18nLocales[loc].sorting;
  15800. break;
  15801. case 'SORT_NUMERIC':
  15802. // compare items numerically
  15803. sorter = function (a, b) {
  15804. return (b - a);
  15805. };
  15806. break;
  15807. case 'SORT_REGULAR':
  15808. // compare items normally (don't change types)
  15809. default:
  15810. sorter = function (b, a) {
  15811. var aFloat = parseFloat(a),
  15812. bFloat = parseFloat(b),
  15813. aNumeric = aFloat + '' === a,
  15814. bNumeric = bFloat + '' === b;
  15815. if (aNumeric && bNumeric) {
  15816. return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  15817. } else if (aNumeric && !bNumeric) {
  15818. return 1;
  15819. } else if (!aNumeric && bNumeric) {
  15820. return -1;
  15821. }
  15822. return a > b ? 1 : a < b ? -1 : 0;
  15823. };
  15824. break;
  15825. }
  15826. // Make a list of key names
  15827. for (k in inputArr) {
  15828. if (inputArr.hasOwnProperty(k)) {
  15829. keys.push(k);
  15830. }
  15831. }
  15832. keys.sort(sorter);
  15833. // BEGIN REDUNDANT
  15834. this.php_js = this.php_js || {};
  15835. this.php_js.ini = this.php_js.ini || {};
  15836. // END REDUNDANT
  15837. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  15838. populateArr = strictForIn ? inputArr : populateArr;
  15839. // Rebuild array with sorted key names
  15840. for (i = 0; i < keys.length; i++) {
  15841. k = keys[i];
  15842. tmp_arr[k] = inputArr[k];
  15843. if (strictForIn) {
  15844. delete inputArr[k];
  15845. }
  15846. }
  15847. for (i in tmp_arr) {
  15848. if (tmp_arr.hasOwnProperty(i)) {
  15849. populateArr[i] = tmp_arr[i];
  15850. }
  15851. }
  15852. return strictForIn || populateArr;
  15853. };
  15854. php.ksort = function (inputArr, sort_flags) {
  15855. // Sort an array by key
  15856. //
  15857. // version: 1103.1210
  15858. // discuss at: http://phpjs.org/functions/ksort
  15859. // + original by: GeekFG (http://geekfg.blogspot.com)
  15860. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15861. // + improved by: Brett Zamir (http://brett-zamir.me)
  15862. // % note 1: The examples are correct, this is a new way
  15863. // % note 2: This function deviates from PHP in returning a copy of the array instead
  15864. // % note 2: of acting by reference and returning true; this was necessary because
  15865. // % note 2: IE does not allow deleting and re-adding of properties without caching
  15866. // % note 2: of property position; you can set the ini of "phpjs.strictForIn" to true to
  15867. // % note 2: get the PHP behavior, but use this only if you are in an environment
  15868. // % note 2: such as Firefox extensions where for-in iteration order is fixed and true
  15869. // % note 2: property deletion is supported. Note that we intend to implement the PHP
  15870. // % note 2: behavior by default if IE ever does allow it; only gives shallow copy since
  15871. // % note 2: is by reference in PHP anyways
  15872. // % note 3: Since JS objects' keys are always strings, and (the
  15873. // % note 3: default) SORT_REGULAR flag distinguishes by key type,
  15874. // % note 3: if the content is a numeric string, we treat the
  15875. // % note 3: "original type" as numeric.
  15876. // - depends on: i18n_loc_get_default
  15877. // - depends on: strnatcmp
  15878. // * example 1: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  15879. // * example 1: \php.data = ksort(data);
  15880. // * results 1: {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'}
  15881. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  15882. // * example 2: \php.data = {2: 'van', 3: 'Zonneveld', 1: 'Kevin'};
  15883. // * example 2: \php.ksort(data);
  15884. // * results 2: data == {1: 'Kevin', 2: 'van', 3: 'Zonneveld'}
  15885. // * returns 2: true
  15886. var tmp_arr = {},
  15887. keys = [],
  15888. sorter, i, k, that = this,
  15889. strictForIn = false,
  15890. populateArr = {};
  15891. switch (sort_flags) {
  15892. case 'SORT_STRING':
  15893. // compare items as strings
  15894. sorter = function (a, b) {
  15895. return that.strnatcmp(a, b);
  15896. };
  15897. break;
  15898. case 'SORT_LOCALE_STRING':
  15899. // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
  15900. var loc = this.i18n_loc_get_default();
  15901. sorter = this.php_js.i18nLocales[loc].sorting;
  15902. break;
  15903. case 'SORT_NUMERIC':
  15904. // compare items numerically
  15905. sorter = function (a, b) {
  15906. return ((a + 0) - (b + 0));
  15907. };
  15908. break;
  15909. // case 'SORT_REGULAR': // compare items normally (don't change types)
  15910. default:
  15911. sorter = function (a, b) {
  15912. var aFloat = parseFloat(a),
  15913. bFloat = parseFloat(b),
  15914. aNumeric = aFloat + '' === a,
  15915. bNumeric = bFloat + '' === b;
  15916. if (aNumeric && bNumeric) {
  15917. return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  15918. } else if (aNumeric && !bNumeric) {
  15919. return 1;
  15920. } else if (!aNumeric && bNumeric) {
  15921. return -1;
  15922. }
  15923. return a > b ? 1 : a < b ? -1 : 0;
  15924. };
  15925. break;
  15926. }
  15927. // Make a list of key names
  15928. for (k in inputArr) {
  15929. if (inputArr.hasOwnProperty(k)) {
  15930. keys.push(k);
  15931. }
  15932. }
  15933. keys.sort(sorter);
  15934. // BEGIN REDUNDANT
  15935. this.php_js = this.php_js || {};
  15936. this.php_js.ini = this.php_js.ini || {};
  15937. // END REDUNDANT
  15938. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  15939. populateArr = strictForIn ? inputArr : populateArr;
  15940. // Rebuild array with sorted key names
  15941. for (i = 0; i < keys.length; i++) {
  15942. k = keys[i];
  15943. tmp_arr[k] = inputArr[k];
  15944. if (strictForIn) {
  15945. delete inputArr[k];
  15946. }
  15947. }
  15948. for (i in tmp_arr) {
  15949. if (tmp_arr.hasOwnProperty(i)) {
  15950. populateArr[i] = tmp_arr[i];
  15951. }
  15952. }
  15953. return strictForIn || populateArr;
  15954. };
  15955. php.lcfirst = function (str) {
  15956. // !No description available for lcfirst. @php.js developers: Please update the function summary text file.
  15957. //
  15958. // version: 1103.1210
  15959. // discuss at: http://phpjs.org/functions/lcfirst
  15960. // + original by: Brett Zamir (http://brett-zamir.me)
  15961. // * example 1: \php.lcfirst('Kevin Van Zonneveld');
  15962. // * returns 1: 'kevin Van Zonneveld'
  15963. str += '';
  15964. var f = str.charAt(0).toLowerCase();
  15965. return f + str.substr(1);
  15966. };
  15967. php.ltrim = function (str, charlist) {
  15968. // Strips whitespace from the beginning of a string
  15969. //
  15970. // version: 1103.1210
  15971. // discuss at: http://phpjs.org/functions/ltrim
  15972. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15973. // + input by: Erkekjetter
  15974. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15975. // + bugfixed by: Onno Marsman
  15976. // * example 1: \php.ltrim(' Kevin van Zonneveld ');
  15977. // * returns 1: 'Kevin van Zonneveld '
  15978. charlist = !charlist ? ' \\s\u00A0' : (charlist + '').replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
  15979. var re = new RegExp('^[' + charlist + ']+', 'g');
  15980. return (str + '').replace(re, '');
  15981. };
  15982. php.rtrim = function (str, charlist) {
  15983. // Removes trailing whitespace
  15984. //
  15985. // version: 1103.1210
  15986. // discuss at: http://phpjs.org/functions/rtrim
  15987. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15988. // + input by: Erkekjetter
  15989. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  15990. // + bugfixed by: Onno Marsman
  15991. // + input by: rem
  15992. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  15993. // * example 1: rtrim(' Kevin van Zonneveld ');
  15994. // * returns 1: ' Kevin van Zonneveld'
  15995. charlist = !charlist ? ' \\s\u00A0' : (charlist + '').replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\\$1');
  15996. var re = new RegExp('[' + charlist + ']+$', 'g');
  15997. return (str + '').replace(re, '');
  15998. };
  15999. php.max = function () {
  16000. // Return the highest value in an array or a series of arguments
  16001. //
  16002. // version: 1103.1210
  16003. // discuss at: http://phpjs.org/functions/max
  16004. // + original by: Onno Marsman
  16005. // + revised by: Onno Marsman
  16006. // + tweaked by: Jack
  16007. // % note: Long code cause we're aiming for maximum PHP compatibility
  16008. // * example 1: \php.max(1, 3, 5, 6, 7);
  16009. // * returns 1: 7
  16010. // * example 2: \php.max([2, 4, 5]);
  16011. // * returns 2: 5
  16012. // * example 3: \php.max(0, 'hello');
  16013. // * returns 3: 0
  16014. // * example 4: \php.max('hello', 0);
  16015. // * returns 4: 'hello'
  16016. // * example 5: \php.max(-1, 'hello');
  16017. // * returns 5: 'hello'
  16018. // * example 6: \php.max([2, 4, 8], [2, 5, 7]);
  16019. // * returns 6: [2, 5, 7]
  16020. var ar, retVal, i = 0,
  16021. n = 0;
  16022. var argv = arguments,
  16023. argc = argv.length;
  16024. var _obj2Array = function (obj) {
  16025. if (obj instanceof Array) {
  16026. return obj;
  16027. } else {
  16028. var ar = [];
  16029. for (var i in obj) {
  16030. ar.push(obj[i]);
  16031. }
  16032. return ar;
  16033. }
  16034. }; //function _obj2Array
  16035. var _compare = function (current, next) {
  16036. var i = 0,
  16037. n = 0,
  16038. tmp = 0;
  16039. var nl = 0,
  16040. cl = 0;
  16041. if (current === next) {
  16042. return 0;
  16043. } else if (typeof current == 'object') {
  16044. if (typeof next == 'object') {
  16045. current = _obj2Array(current);
  16046. next = _obj2Array(next);
  16047. cl = current.length;
  16048. nl = next.length;
  16049. if (nl > cl) {
  16050. return 1;
  16051. } else if (nl < cl) {
  16052. return -1;
  16053. } else {
  16054. for (i = 0, n = cl; i < n; ++i) {
  16055. tmp = _compare(current[i], next[i]);
  16056. if (tmp == 1) {
  16057. return 1;
  16058. } else if (tmp == -1) {
  16059. return -1;
  16060. }
  16061. }
  16062. return 0;
  16063. }
  16064. } else {
  16065. return -1;
  16066. }
  16067. } else if (typeof next == 'object') {
  16068. return 1;
  16069. } else if (isNaN(next) && !isNaN(current)) {
  16070. if (current == 0) {
  16071. return 0;
  16072. } else {
  16073. return (current < 0 ? 1 : -1);
  16074. }
  16075. } else if (isNaN(current) && !isNaN(next)) {
  16076. if (next == 0) {
  16077. return 0;
  16078. } else {
  16079. return (next > 0 ? 1 : -1);
  16080. }
  16081. } else {
  16082. if (next == current) {
  16083. return 0;
  16084. } else {
  16085. return (next > current ? 1 : -1);
  16086. }
  16087. }
  16088. }; //function _compare
  16089. if (argc === 0) {
  16090. throw new Error('At least one value should be passed to max()');
  16091. } else if (argc === 1) {
  16092. if (typeof argv[0] === 'object') {
  16093. ar = _obj2Array(argv[0]);
  16094. } else {
  16095. throw new Error('Wrong parameter count for max()');
  16096. }
  16097. if (ar.length === 0) {
  16098. throw new Error('Array must contain at least one element for max()');
  16099. }
  16100. } else {
  16101. ar = argv;
  16102. }
  16103. retVal = ar[0];
  16104. for (i = 1, n = ar.length; i < n; ++i) {
  16105. if (_compare(retVal, ar[i]) == 1) {
  16106. retVal = ar[i];
  16107. }
  16108. }
  16109. return retVal;
  16110. };
  16111. php.md5 = function (str) {
  16112. // Calculate the md5 hash of a string
  16113. //
  16114. // version: 1103.1210
  16115. // discuss at: http://phpjs.org/functions/md5
  16116. // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
  16117. // + namespaced by: Michael White (http://getsprink.com)
  16118. // + tweaked by: Jack
  16119. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16120. // + input by: Brett Zamir (http://brett-zamir.me)
  16121. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16122. // - depends on: utf8_encode
  16123. // * example 1: \php.md5('Kevin van Zonneveld');
  16124. // * returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
  16125. var xl;
  16126. var rotateLeft = function (lValue, iShiftBits) {
  16127. return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
  16128. };
  16129. var addUnsigned = function (lX, lY) {
  16130. var lX4, lY4, lX8, lY8, lResult;
  16131. lX8 = (lX & 0x80000000);
  16132. lY8 = (lY & 0x80000000);
  16133. lX4 = (lX & 0x40000000);
  16134. lY4 = (lY & 0x40000000);
  16135. lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
  16136. if (lX4 & lY4) {
  16137. return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
  16138. }
  16139. if (lX4 | lY4) {
  16140. if (lResult & 0x40000000) {
  16141. return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
  16142. } else {
  16143. return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
  16144. }
  16145. } else {
  16146. return (lResult ^ lX8 ^ lY8);
  16147. }
  16148. };
  16149. var _F = function (x, y, z) {
  16150. return (x & y) | ((~x) & z);
  16151. };
  16152. var _G = function (x, y, z) {
  16153. return (x & z) | (y & (~z));
  16154. };
  16155. var _H = function (x, y, z) {
  16156. return (x ^ y ^ z);
  16157. };
  16158. var _I = function (x, y, z) {
  16159. return (y ^ (x | (~z)));
  16160. };
  16161. var _FF = function (a, b, c, d, x, s, ac) {
  16162. a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
  16163. return addUnsigned(rotateLeft(a, s), b);
  16164. };
  16165. var _GG = function (a, b, c, d, x, s, ac) {
  16166. a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
  16167. return addUnsigned(rotateLeft(a, s), b);
  16168. };
  16169. var _HH = function (a, b, c, d, x, s, ac) {
  16170. a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
  16171. return addUnsigned(rotateLeft(a, s), b);
  16172. };
  16173. var _II = function (a, b, c, d, x, s, ac) {
  16174. a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
  16175. return addUnsigned(rotateLeft(a, s), b);
  16176. };
  16177. var convertToWordArray = function (str) {
  16178. var lWordCount;
  16179. var lMessageLength = str.length;
  16180. var lNumberOfWords_temp1 = lMessageLength + 8;
  16181. var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
  16182. var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
  16183. var lWordArray = new Array(lNumberOfWords - 1);
  16184. var lBytePosition = 0;
  16185. var lByteCount = 0;
  16186. while (lByteCount < lMessageLength) {
  16187. lWordCount = (lByteCount - (lByteCount % 4)) / 4;
  16188. lBytePosition = (lByteCount % 4) * 8;
  16189. lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
  16190. lByteCount++;
  16191. }
  16192. lWordCount = (lByteCount - (lByteCount % 4)) / 4;
  16193. lBytePosition = (lByteCount % 4) * 8;
  16194. lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
  16195. lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
  16196. lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
  16197. return lWordArray;
  16198. };
  16199. var wordToHex = function (lValue) {
  16200. var wordToHexValue = "",
  16201. wordToHexValue_temp = "",
  16202. lByte, lCount;
  16203. for (lCount = 0; lCount <= 3; lCount++) {
  16204. lByte = (lValue >>> (lCount * 8)) & 255;
  16205. wordToHexValue_temp = "0" + lByte.toString(16);
  16206. wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
  16207. }
  16208. return wordToHexValue;
  16209. };
  16210. var x = [],
  16211. k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
  16212. S12 = 12,
  16213. S13 = 17,
  16214. S14 = 22,
  16215. S21 = 5,
  16216. S22 = 9,
  16217. S23 = 14,
  16218. S24 = 20,
  16219. S31 = 4,
  16220. S32 = 11,
  16221. S33 = 16,
  16222. S34 = 23,
  16223. S41 = 6,
  16224. S42 = 10,
  16225. S43 = 15,
  16226. S44 = 21;
  16227. str = this.utf8_encode(str);
  16228. x = convertToWordArray(str);
  16229. a = 0x67452301;
  16230. b = 0xEFCDAB89;
  16231. c = 0x98BADCFE;
  16232. d = 0x10325476;
  16233. xl = x.length;
  16234. for (k = 0; k < xl; k += 16) {
  16235. AA = a;
  16236. BB = b;
  16237. CC = c;
  16238. DD = d;
  16239. a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
  16240. d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
  16241. c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
  16242. b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
  16243. a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
  16244. d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
  16245. c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
  16246. b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
  16247. a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
  16248. d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
  16249. c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
  16250. b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
  16251. a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
  16252. d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
  16253. c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
  16254. b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
  16255. a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
  16256. d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
  16257. c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
  16258. b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
  16259. a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
  16260. d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
  16261. c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
  16262. b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
  16263. a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
  16264. d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
  16265. c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
  16266. b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
  16267. a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
  16268. d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
  16269. c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
  16270. b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
  16271. a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
  16272. d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
  16273. c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
  16274. b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
  16275. a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
  16276. d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
  16277. c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
  16278. b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
  16279. a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
  16280. d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
  16281. c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
  16282. b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
  16283. a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
  16284. d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
  16285. c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
  16286. b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
  16287. a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
  16288. d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
  16289. c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
  16290. b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
  16291. a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
  16292. d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
  16293. c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
  16294. b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
  16295. a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
  16296. d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
  16297. c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
  16298. b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
  16299. a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
  16300. d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
  16301. c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
  16302. b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
  16303. a = addUnsigned(a, AA);
  16304. b = addUnsigned(b, BB);
  16305. c = addUnsigned(c, CC);
  16306. d = addUnsigned(d, DD);
  16307. }
  16308. var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
  16309. return temp.toLowerCase();
  16310. };
  16311. php.method_exists = function (obj, method) {
  16312. // Checks if the class method exists
  16313. //
  16314. // version: 1103.1210
  16315. // discuss at: http://phpjs.org/functions/method_exists
  16316. // + original by: Brett Zamir (http://brett-zamir.me)
  16317. // * example 1: \php.function class_a() {this.meth1 = function () {return true;}};
  16318. // * example 1: \php.var instance_a = new class_a();
  16319. // * example 1: \php.method_exists(instance_a, 'meth1');
  16320. // * returns 1: true
  16321. // * example 2: \php.function class_a() {this.meth1 = function () {return true;}};
  16322. // * example 2: \php.var instance_a = new class_a();
  16323. // * example 2: \php.method_exists(instance_a, 'meth2');
  16324. // * returns 2: false
  16325. if (typeof obj === 'string') {
  16326. return this.window[obj] && typeof this.window[obj][method] === 'function';
  16327. }
  16328. return typeof obj[method] === 'function';
  16329. };
  16330. php.microtime = function (get_as_float) {
  16331. // Returns either a string or a float containing the current time in seconds and microseconds
  16332. //
  16333. // version: 1103.1210
  16334. // discuss at: http://phpjs.org/functions/microtime
  16335. // + original by: Paulo Freitas
  16336. // * example 1: \php.timeStamp = microtime(true);
  16337. // * results 1: timeStamp > 1000000000 && timeStamp < 2000000000
  16338. var now = new Date().getTime() / 1000;
  16339. var s = parseInt(now, 10);
  16340. return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
  16341. };
  16342. php.min = function () {
  16343. // Return the lowest value in an array or a series of arguments
  16344. //
  16345. // version: 1103.1210
  16346. // discuss at: http://phpjs.org/functions/min
  16347. // + original by: Onno Marsman
  16348. // + revised by: Onno Marsman
  16349. // + tweaked by: Jack
  16350. // % note: Long code cause we're aiming for maximum PHP compatibility
  16351. // * example 1: \php.min(1, 3, 5, 6, 7);
  16352. // * returns 1: 1
  16353. // * example 2: \php.min([2, 4, 5]);
  16354. // * returns 2: 2
  16355. // * example 3: \php.min(0, 'hello');
  16356. // * returns 3: 0
  16357. // * example 4: \php.min('hello', 0);
  16358. // * returns 4: 'hello'
  16359. // * example 5: \php.min(-1, 'hello');
  16360. // * returns 5: -1
  16361. // * example 6: \php.min([2, 4, 8], [2, 5, 7]);
  16362. // * returns 6: [2, 4, 8]
  16363. var ar, retVal, i = 0,
  16364. n = 0;
  16365. var argv = arguments,
  16366. argc = argv.length;
  16367. var _obj2Array = function (obj) {
  16368. if (obj instanceof Array) {
  16369. return obj;
  16370. } else {
  16371. var ar = [];
  16372. for (var i in obj) {
  16373. ar.push(obj[i]);
  16374. }
  16375. return ar;
  16376. }
  16377. }; //function _obj2Array
  16378. var _compare = function (current, next) {
  16379. var i = 0,
  16380. n = 0,
  16381. tmp = 0;
  16382. var nl = 0,
  16383. cl = 0;
  16384. if (current === next) {
  16385. return 0;
  16386. } else if (typeof current == 'object') {
  16387. if (typeof next == 'object') {
  16388. current = _obj2Array(current);
  16389. next = _obj2Array(next);
  16390. cl = current.length;
  16391. nl = next.length;
  16392. if (nl > cl) {
  16393. return 1;
  16394. } else if (nl < cl) {
  16395. return -1;
  16396. } else {
  16397. for (i = 0, n = cl; i < n; ++i) {
  16398. tmp = _compare(current[i], next[i]);
  16399. if (tmp == 1) {
  16400. return 1;
  16401. } else if (tmp == -1) {
  16402. return -1;
  16403. }
  16404. }
  16405. return 0;
  16406. }
  16407. } else {
  16408. return -1;
  16409. }
  16410. } else if (typeof next == 'object') {
  16411. return 1;
  16412. } else if (isNaN(next) && !isNaN(current)) {
  16413. if (current == 0) {
  16414. return 0;
  16415. } else {
  16416. return (current < 0 ? 1 : -1);
  16417. }
  16418. } else if (isNaN(current) && !isNaN(next)) {
  16419. if (next == 0) {
  16420. return 0;
  16421. } else {
  16422. return (next > 0 ? 1 : -1);
  16423. }
  16424. } else {
  16425. if (next == current) {
  16426. return 0;
  16427. } else {
  16428. return (next > current ? 1 : -1);
  16429. }
  16430. }
  16431. }; //function _compare
  16432. if (argc === 0) {
  16433. throw new Error('At least one value should be passed to min()');
  16434. } else if (argc === 1) {
  16435. if (typeof argv[0] === 'object') {
  16436. ar = _obj2Array(argv[0]);
  16437. } else {
  16438. throw new Error('Wrong parameter count for min()');
  16439. }
  16440. if (ar.length === 0) {
  16441. throw new Error('Array must contain at least one element for min()');
  16442. }
  16443. } else {
  16444. ar = argv;
  16445. }
  16446. retVal = ar[0];
  16447. for (i = 1, n = ar.length; i < n; ++i) {
  16448. if (_compare(retVal, ar[i]) == -1) {
  16449. retVal = ar[i];
  16450. }
  16451. }
  16452. return retVal;
  16453. };
  16454. php.mktime = function () {
  16455. // Get UNIX timestamp for a date
  16456. //
  16457. // version: 1103.1210
  16458. // discuss at: http://phpjs.org/functions/mktime
  16459. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16460. // + improved by: baris ozdil
  16461. // + input by: gabriel paderni
  16462. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16463. // + improved by: FGFEmperor
  16464. // + input by: Yannoo
  16465. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16466. // + input by: jakes
  16467. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16468. // + bugfixed by: Marc Palau
  16469. // + improved by: Brett Zamir (http://brett-zamir.me)
  16470. // + input by: 3D-GRAF
  16471. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  16472. // + input by: Chris
  16473. // + revised by: Theriault
  16474. // % note 1: The return values of the following examples are
  16475. // % note 1: received only if your system's timezone is UTC.
  16476. // * example 1: \php.mktime(14, 10, 2, 2, 1, 2008);
  16477. // * returns 1: 1201875002
  16478. // * example 2: \php.mktime(0, 0, 0, 0, 1, 2008);
  16479. // * returns 2: 1196467200
  16480. // * example 3: \php.make = mktime();
  16481. // * example 3: \php.td = new Date();
  16482. // * example 3: \php.real = Math.floor(td.getTime() / 1000);
  16483. // * example 3: \php.diff = (real - make);
  16484. // * results 3: diff < 5
  16485. // * example 4: \php.mktime(0, 0, 0, 13, 1, 1997)
  16486. // * returns 4: 883612800
  16487. // * example 5: \php.mktime(0, 0, 0, 1, 1, 1998)
  16488. // * returns 5: 883612800
  16489. // * example 6: \php.mktime(0, 0, 0, 1, 1, 98)
  16490. // * returns 6: 883612800
  16491. // * example 7: \php.mktime(23, 59, 59, 13, 0, 2010)
  16492. // * returns 7: 1293839999
  16493. // * example 8: \php.mktime(0, 0, -1, 1, 1, 1970)
  16494. // * returns 8: -1
  16495. var d = new Date(),
  16496. r = arguments,
  16497. i = 0,
  16498. e = ['Hours', 'Minutes', 'Seconds', 'Month', 'Date', 'FullYear'];
  16499. for (i = 0; i < e.length; i++) {
  16500. if (typeof r[i] === 'undefined') {
  16501. r[i] = d['get' + e[i]]();
  16502. r[i] += (i === 3); // +1 to fix JS months.
  16503. } else {
  16504. r[i] = parseInt(r[i], 10);
  16505. if (isNaN(r[i])) {
  16506. return false;
  16507. }
  16508. }
  16509. }
  16510. // Map years 0-69 to 2000-2069 and years 70-100 to 1970-2000.
  16511. r[5] += (r[5] >= 0 ? (r[5] <= 69 ? 2e3 : (r[5] <= 100 ? 1900 : 0)) : 0);
  16512. // Set year, month (-1 to fix JS months), and date.
  16513. // !This must come before the call to setHours!
  16514. d.setFullYear(r[5], r[3] - 1, r[4]);
  16515. // Set hours, minutes, and seconds.
  16516. d.setHours(r[0], r[1], r[2]);
  16517. // Divide milliseconds by 1000 to return seconds and drop decimal.
  16518. // Add 1 second if negative or it'll be off from PHP by 1 second.
  16519. return (d.getTime() / 1e3 >> 0) - (d.getTime() < 0);
  16520. };
  16521. php.natcasesort = function (inputArr) {
  16522. // Sort an array using case-insensitive natural sort
  16523. //
  16524. // version: 1103.1210
  16525. // discuss at: http://phpjs.org/functions/natcasesort
  16526. // + original by: Brett Zamir (http://brett-zamir.me)
  16527. // + improved by: Brett Zamir (http://brett-zamir.me)
  16528. // % note 1: This function deviates from PHP in returning a copy of the array instead
  16529. // % note 1: of acting by reference and returning true; this was necessary because
  16530. // % note 1: IE does not allow deleting and re-adding of properties without caching
  16531. // % note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
  16532. // % note 1: get the PHP behavior, but use this only if you are in an environment
  16533. // % note 1: such as Firefox extensions where for-in iteration order is fixed and true
  16534. // % note 1: property deletion is supported. Note that we intend to implement the PHP
  16535. // % note 1: behavior by default if IE ever does allow it; only gives shallow copy since
  16536. // % note 1: is by reference in PHP anyways
  16537. // % note 2: We cannot use numbers as keys and have them be reordered since they
  16538. // % note 2: adhere to numerical order in some implementations
  16539. // - depends on: strnatcasecmp
  16540. // * example 1: $array1 = {a:'IMG0.png', b:'img12.png', c:'img10.png', d:'img2.png', e:'img1.png', f:'IMG3.png'};
  16541. // * example 1: $array1 = natcasesort($array1);
  16542. // * returns 1: {a: 'IMG0.png', e: 'img1.png', d: 'img2.png', f: 'IMG3.png', c: 'img10.png', b: 'img12.png'}
  16543. var valArr = [],
  16544. keyArr = [],
  16545. k, i, ret, that = this,
  16546. strictForIn = false,
  16547. populateArr = {};
  16548. var bubbleSort = function (keyArr, inputArr) {
  16549. var i, j, tempValue, tempKeyVal;
  16550. for (i = inputArr.length - 2; i >= 0; i--) {
  16551. for (j = 0; j <= i; j++) {
  16552. ret = that.strnatcasecmp(inputArr[j + 1], inputArr[j]);
  16553. if (ret < 0) {
  16554. tempValue = inputArr[j];
  16555. inputArr[j] = inputArr[j + 1];
  16556. inputArr[j + 1] = tempValue;
  16557. tempKeyVal = keyArr[j];
  16558. keyArr[j] = keyArr[j + 1];
  16559. keyArr[j + 1] = tempKeyVal;
  16560. }
  16561. }
  16562. }
  16563. };
  16564. // BEGIN REDUNDANT
  16565. this.php_js = this.php_js || {};
  16566. this.php_js.ini = this.php_js.ini || {};
  16567. // END REDUNDANT
  16568. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  16569. populateArr = strictForIn ? inputArr : populateArr;
  16570. // Get key and value arrays
  16571. for (k in inputArr) {
  16572. if (inputArr.hasOwnProperty(k)) {
  16573. valArr.push(inputArr[k]);
  16574. keyArr.push(k);
  16575. if (strictForIn) {
  16576. delete inputArr[k];
  16577. }
  16578. }
  16579. }
  16580. try {
  16581. // Sort our new temporary arrays
  16582. bubbleSort(keyArr, valArr);
  16583. } catch (e) {
  16584. return false;
  16585. }
  16586. // Repopulate the old array
  16587. for (i = 0; i < valArr.length; i++) {
  16588. populateArr[keyArr[i]] = valArr[i];
  16589. }
  16590. return strictForIn || populateArr;
  16591. };
  16592. php.natsort = function (inputArr) {
  16593. // Sort an array using natural sort
  16594. //
  16595. // version: 1103.1210
  16596. // discuss at: http://phpjs.org/functions/natsort
  16597. // + original by: Brett Zamir (http://brett-zamir.me)
  16598. // + improved by: Brett Zamir (http://brett-zamir.me)
  16599. // % note 1: This function deviates from PHP in returning a copy of the array instead
  16600. // % note 1: of acting by reference and returning true; this was necessary because
  16601. // % note 1: IE does not allow deleting and re-adding of properties without caching
  16602. // % note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
  16603. // % note 1: get the PHP behavior, but use this only if you are in an environment
  16604. // % note 1: such as Firefox extensions where for-in iteration order is fixed and true
  16605. // % note 1: property deletion is supported. Note that we intend to implement the PHP
  16606. // % note 1: behavior by default if IE ever does allow it; only gives shallow copy since
  16607. // % note 1: is by reference in PHP anyways
  16608. // - depends on: strnatcmp
  16609. // * example 1: $array1 = {a:"img12.png", b:"img10.png", c:"img2.png", d:"img1.png"};
  16610. // * example 1: $array1 = natsort($array1);
  16611. // * returns 1: {d: 'img1.png', c: 'img2.png', b: 'img10.png', a: 'img12.png'}
  16612. var valArr = [],
  16613. keyArr = [],
  16614. k, i, ret, that = this,
  16615. strictForIn = false,
  16616. populateArr = {};
  16617. var bubbleSort = function (keyArr, inputArr) {
  16618. var i, j, tempValue, tempKeyVal;
  16619. for (i = inputArr.length - 2; i >= 0; i--) {
  16620. for (j = 0; j <= i; j++) {
  16621. ret = that.strnatcmp(inputArr[j + 1], inputArr[j]);
  16622. if (ret < 0) {
  16623. tempValue = inputArr[j];
  16624. inputArr[j] = inputArr[j + 1];
  16625. inputArr[j + 1] = tempValue;
  16626. tempKeyVal = keyArr[j];
  16627. keyArr[j] = keyArr[j + 1];
  16628. keyArr[j + 1] = tempKeyVal;
  16629. }
  16630. }
  16631. }
  16632. };
  16633. // BEGIN REDUNDANT
  16634. this.php_js = this.php_js || {};
  16635. this.php_js.ini = this.php_js.ini || {};
  16636. // END REDUNDANT
  16637. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  16638. populateArr = strictForIn ? inputArr : populateArr;
  16639. // Get key and value arrays
  16640. for (k in inputArr) {
  16641. if (inputArr.hasOwnProperty(k)) {
  16642. valArr.push(inputArr[k]);
  16643. keyArr.push(k);
  16644. if (strictForIn) {
  16645. delete inputArr[k];
  16646. }
  16647. }
  16648. }
  16649. try {
  16650. // Sort our new temporary arrays
  16651. bubbleSort(keyArr, valArr);
  16652. } catch (e) {
  16653. return false;
  16654. }
  16655. // Repopulate the old array
  16656. for (i = 0; i < valArr.length; i++) {
  16657. populateArr[keyArr[i]] = valArr[i];
  16658. }
  16659. return strictForIn || populateArr;
  16660. };
  16661. php.nl2br = function (str, is_xhtml) {
  16662. // Converts newlines to HTML line breaks
  16663. //
  16664. // version: 1103.1210
  16665. // discuss at: http://phpjs.org/functions/nl2br
  16666. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16667. // + improved by: Philip Peterson
  16668. // + improved by: Onno Marsman
  16669. // + improved by: Atli Þór
  16670. // + bugfixed by: Onno Marsman
  16671. // + input by: Brett Zamir (http://brett-zamir.me)
  16672. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16673. // + improved by: Brett Zamir (http://brett-zamir.me)
  16674. // + improved by: Maximusya
  16675. // * example 1: \php.nl2br('Kevin\nvan\nZonneveld');
  16676. // * returns 1: 'Kevin<br />\nvan<br />\nZonneveld'
  16677. // * example 2: \php.nl2br("\nOne\nTwo\n\nThree\n", false);
  16678. // * returns 2: '<br>\nOne<br>\nTwo<br>\n<br>\nThree<br>\n'
  16679. // * example 3: \php.nl2br("\nOne\nTwo\n\nThree\n", true);
  16680. // * returns 3: '<br />\nOne<br />\nTwo<br />\n<br />\nThree<br />\n'
  16681. var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';
  16682. return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
  16683. };
  16684. php.number_format = function (number, decimals, dec_point, thousands_sep) {
  16685. // Formats a number with grouped thousands
  16686. //
  16687. // version: 1103.1210
  16688. // discuss at: http://phpjs.org/functions/number_format
  16689. // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  16690. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16691. // + bugfix by: Michael White (http://getsprink.com)
  16692. // + bugfix by: Benjamin Lupton
  16693. // + bugfix by: Allan Jensen (http://www.winternet.no)
  16694. // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  16695. // + bugfix by: Howard Yeend
  16696. // + revised by: Luke Smith (http://lucassmith.name)
  16697. // + bugfix by: Diogo Resende
  16698. // + bugfix by: Rival
  16699. // + input by: Kheang Hok Chin (http://www.distantia.ca/)
  16700. // + improved by: davook
  16701. // + improved by: Brett Zamir (http://brett-zamir.me)
  16702. // + input by: Jay Klehr
  16703. // + improved by: Brett Zamir (http://brett-zamir.me)
  16704. // + input by: Amir Habibi (http://www.residence-mixte.com/)
  16705. // + bugfix by: Brett Zamir (http://brett-zamir.me)
  16706. // + improved by: Theriault
  16707. // + input by: Amirouche
  16708. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16709. // * example 1: \php.number_format(1234.56);
  16710. // * returns 1: '1,235'
  16711. // * example 2: \php.number_format(1234.56, 2, ',', ' ');
  16712. // * returns 2: '1 234,56'
  16713. // * example 3: \php.number_format(1234.5678, 2, '.', '');
  16714. // * returns 3: '1234.57'
  16715. // * example 4: \php.number_format(67, 2, ',', '.');
  16716. // * returns 4: '67,00'
  16717. // * example 5: \php.number_format(1000);
  16718. // * returns 5: '1,000'
  16719. // * example 6: \php.number_format(67.311, 2);
  16720. // * returns 6: '67.31'
  16721. // * example 7: \php.number_format(1000.55, 1);
  16722. // * returns 7: '1,000.6'
  16723. // * example 8: \php.number_format(67000, 5, ',', '.');
  16724. // * returns 8: '67.000,00000'
  16725. // * example 9: \php.number_format(0.9, 0);
  16726. // * returns 9: '1'
  16727. // * example 10: \php.number_format('1.20', 2);
  16728. // * returns 10: '1.20'
  16729. // * example 11: \php.number_format('1.20', 4);
  16730. // * returns 11: '1.2000'
  16731. // * example 12: \php.number_format('1.2000', 3);
  16732. // * returns 12: '1.200'
  16733. // * example 13: \php.number_format('1 000,50', 2, '.', ' ');
  16734. // * returns 13: '100 050.00'
  16735. // Strip all characters but numerical ones.
  16736. number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
  16737. var n = !isFinite(+number) ? 0 : +number,
  16738. prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
  16739. sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
  16740. dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
  16741. s = '',
  16742. toFixedFix = function (n, prec) {
  16743. var k = Math.pow(10, prec);
  16744. return '' + Math.round(n * k) / k;
  16745. };
  16746. // Fix for IE parseFloat(0.55).toFixed(0) = 0;
  16747. s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
  16748. if (s[0].length > 3) {
  16749. s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
  16750. }
  16751. if ((s[1] || '').length < prec) {
  16752. s[1] = s[1] || '';
  16753. s[1] += new Array(prec - s[1].length + 1).join('0');
  16754. }
  16755. return s.join(dec);
  16756. };
  16757. php.ord = function (string) {
  16758. // Returns the codepoint value of a character
  16759. //
  16760. // version: 1103.1210
  16761. // discuss at: http://phpjs.org/functions/ord
  16762. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  16763. // + bugfixed by: Onno Marsman
  16764. // + improved by: Brett Zamir (http://brett-zamir.me)
  16765. // + input by: incidence
  16766. // * example 1: \php.ord('K');
  16767. // * returns 1: 75
  16768. // * example 2: \php.ord('\uD800\uDC00'); // surrogate pair to create a single Unicode character
  16769. // * returns 2: 65536
  16770. var str = string + '',
  16771. code = str.charCodeAt(0);
  16772. if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
  16773. var hi = code;
  16774. if (str.length === 1) {
  16775. return code; // This is just a high surrogate with no following low surrogate, so we return its value;
  16776. // we could also throw an error as it is not a complete character, but someone may want to know
  16777. }
  16778. var low = str.charCodeAt(1);
  16779. return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
  16780. }
  16781. if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
  16782. return code; // This is just a low surrogate with no preceding high surrogate, so we return its value;
  16783. // we could also throw an error as it is not a complete character, but someone may want to know
  16784. }
  16785. return code;
  16786. };
  16787. php.parse_str = function (str, array) {
  16788. // Parses GET/POST/COOKIE data and sets global variables
  16789. //
  16790. // version: 1103.1210
  16791. // discuss at: http://phpjs.org/functions/parse_str
  16792. // + original by: Cagri Ekin
  16793. // + improved by: Michael White (http://getsprink.com)
  16794. // + tweaked by: Jack
  16795. // + bugfixed by: Onno Marsman
  16796. // + reimplemented by: stag019
  16797. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  16798. // + bugfixed by: stag019
  16799. // - depends on: urldecode
  16800. // + input by: Dreamer
  16801. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  16802. // % note 1: When no argument is specified, will put variables in global scope.
  16803. // * example 1: \php.var arr = {};
  16804. // * example 1: \php.parse_str('first=foo&second=bar', arr);
  16805. // * results 1: arr == { first: 'foo', second: 'bar' }
  16806. // * example 2: \php.var arr = {};
  16807. // * example 2: \php.parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr);
  16808. // * results 2: arr == { str_a: "Jack and Jill didn't see the well." }
  16809. var glue1 = '=',
  16810. glue2 = '&',
  16811. array2 = String(str).replace(/^&?([\s\S]*?)&?$/, '$1').split(glue2),
  16812. i, j, chr, tmp, key, value, bracket, keys, evalStr, that = this,
  16813. fixStr = function (str) {
  16814. return that.urldecode(str).replace(/([\\"'])/g, '\\$1').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
  16815. };
  16816. if (!array) {
  16817. array = this.window;
  16818. }
  16819. for (i = 0; i < array2.length; i++) {
  16820. tmp = array2[i].split(glue1);
  16821. if (tmp.length < 2) {
  16822. tmp = [tmp, ''];
  16823. }
  16824. key = fixStr(tmp[0]);
  16825. value = fixStr(tmp[1]);
  16826. while (key.charAt(0) === ' ') {
  16827. key = key.substr(1);
  16828. }
  16829. if (key.indexOf('\0') !== -1) {
  16830. key = key.substr(0, key.indexOf('\0'));
  16831. }
  16832. if (key && key.charAt(0) !== '[') {
  16833. keys = [];
  16834. bracket = 0;
  16835. for (j = 0; j < key.length; j++) {
  16836. if (key.charAt(j) === '[' && !bracket) {
  16837. bracket = j + 1;
  16838. } else if (key.charAt(j) === ']') {
  16839. if (bracket) {
  16840. if (!keys.length) {
  16841. keys.push(key.substr(0, bracket - 1));
  16842. }
  16843. keys.push(key.substr(bracket, j - bracket));
  16844. bracket = 0;
  16845. if (key.charAt(j + 1) !== '[') {
  16846. break;
  16847. }
  16848. }
  16849. }
  16850. }
  16851. if (!keys.length) {
  16852. keys = [key];
  16853. }
  16854. for (j = 0; j < keys[0].length; j++) {
  16855. chr = keys[0].charAt(j);
  16856. if (chr === ' ' || chr === '.' || chr === '[') {
  16857. keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1);
  16858. }
  16859. if (chr === '[') {
  16860. break;
  16861. }
  16862. }
  16863. evalStr = 'array';
  16864. for (j = 0; j < keys.length; j++) {
  16865. key = keys[j];
  16866. if ((key !== '' && key !== ' ') || j === 0) {
  16867. key = "'" + key + "'";
  16868. } else {
  16869. key = eval(evalStr + '.push([]);') - 1;
  16870. }
  16871. evalStr += '[' + key + ']';
  16872. if (j !== keys.length - 1 && eval('typeof ' + evalStr) === 'undefined') {
  16873. eval(evalStr + ' = [];');
  16874. }
  16875. }
  16876. evalStr += " = '" + value + "';\n";
  16877. eval(evalStr);
  16878. }
  16879. }
  16880. };
  16881. php.parse_url = function (str, component) {
  16882. // Parse a URL and return its components
  16883. //
  16884. // version: 1103.1210
  16885. // discuss at: http://phpjs.org/functions/parse_url
  16886. // + original by: Steven Levithan (http://blog.stevenlevithan.com)
  16887. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  16888. // + input by: Lorenzo Pisani
  16889. // + input by: Tony
  16890. // + improved by: Brett Zamir (http://brett-zamir.me)
  16891. // % note: Based on http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
  16892. // % note: blog post at http://blog.stevenlevithan.com/archives/parseuri
  16893. // % note: demo at http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
  16894. // % note: Does not replace invalid characters with '_' as in PHP, nor does it return false with
  16895. // % note: a seriously malformed URL.
  16896. // % note: Besides function name, is essentially the same as parseUri as well as our allowing
  16897. // % note: an extra slash after the scheme/protocol (to allow file:/// as in PHP)
  16898. // * example 1: \php.parse_url('http://username:password@hostname/path?arg=value#anchor');
  16899. // * returns 1: {scheme: 'http', host: 'hostname', user: 'username', pass: 'password', path: '/path', query: 'arg=value', fragment: 'anchor'}
  16900. var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port',
  16901. 'relative', 'path', 'directory', 'file', 'query', 'fragment'],
  16902. ini = (this.php_js && this.php_js.ini) || {},
  16903. mode = (ini['phpjs.parse_url.mode'] &&
  16904. ini['phpjs.parse_url.mode'].local_value) || 'php',
  16905. parser = {
  16906. php: /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
  16907. strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
  16908. loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-scheme to catch file:/// (should restrict this)
  16909. };
  16910. var m = parser[mode].exec(str),
  16911. uri = {},
  16912. i = 14;
  16913. while (i--) {
  16914. if (m[i]) {
  16915. uri[key[i]] = m[i];
  16916. }
  16917. }
  16918. if (component) {
  16919. return uri[component.replace('PHP_URL_', '').toLowerCase()];
  16920. }
  16921. if (mode !== 'php') {
  16922. var name = (ini['phpjs.parse_url.queryKey'] &&
  16923. ini['phpjs.parse_url.queryKey'].local_value) || 'queryKey';
  16924. parser = /(?:^|&)([^&=]*)=?([^&]*)/g;
  16925. uri[name] = {};
  16926. uri[key[12]].replace(parser, function ($0, $1, $2) {
  16927. if ($1) {uri[name][$1] = $2;}
  16928. });
  16929. }
  16930. delete uri.source;
  16931. return uri;
  16932. };
  16933. php.printf = function () {
  16934. // Output a formatted string
  16935. //
  16936. // version: 1103.1210
  16937. // discuss at: http://phpjs.org/functions/printf
  16938. // + original by: Ash Searle (http://hexmen.com/blog/)
  16939. // + improved by: Michael White (http://getsprink.com)
  16940. // + improved by: Brett Zamir (http://brett-zamir.me)
  16941. // - depends on: sprintf
  16942. // * example 1: \php.printf("%01.2f", 123.1);
  16943. // * returns 1: 6
  16944. var body, elmt, d = this.window.document;
  16945. var ret = '';
  16946. var HTMLNS = 'http://www.w3.org/1999/xhtml';
  16947. body = d.getElementsByTagNameNS ? (d.getElementsByTagNameNS(HTMLNS, 'body')[0] ? d.getElementsByTagNameNS(HTMLNS, 'body')[0] : d.documentElement.lastChild) : d.getElementsByTagName('body')[0];
  16948. if (!body) {
  16949. return false;
  16950. }
  16951. ret = this.sprintf.apply(this, arguments);
  16952. elmt = d.createTextNode(ret);
  16953. body.appendChild(elmt);
  16954. return ret.length;
  16955. };
  16956. php.property_exists = function (cls, prop) {
  16957. // Checks if the object or class has a property
  16958. //
  16959. // version: 1103.1210
  16960. // discuss at: http://phpjs.org/functions/property_exists
  16961. // + original by: Brett Zamir (http://brett-zamir.me)
  16962. // * example 1: \php.function class_a () {this.prop1 = 'one'};
  16963. // * example 1: \php.var instance_a = new class_a();
  16964. // * example 1: \php.property_exists(instance_a, 'prop1');
  16965. // * returns 1: true
  16966. // * example 2: \php.function class_a () {this.prop1 = 'one'};
  16967. // * example 2: \php.var instance_a = new class_a();
  16968. // * example 2: \php.property_exists(instance_a, 'prop2');
  16969. // * returns 2: false
  16970. cls = (typeof cls === 'string') ? this.window[cls] : cls;
  16971. if (typeof cls === 'function' && cls.toSource && cls.toSource().match(new RegExp('this\\.' + prop + '\\s'))) {
  16972. // Hackish and non-standard but can probably detect if setting
  16973. // the property (we don't want to test by instantiating as that
  16974. // may have side-effects)
  16975. return true;
  16976. }
  16977. return (cls[prop] !== undefined && typeof cls[prop] !== 'function') || (cls.prototype !== undefined && cls.prototype[prop] !== undefined && typeof cls.prototype[prop] !== 'function') || (cls.constructor && cls.constructor[prop] !== undefined && typeof cls.constructor[prop] !== 'function');
  16978. };
  16979. php.quotemeta = function (str) {
  16980. // Quotes meta characters
  16981. //
  16982. // version: 1103.1210
  16983. // discuss at: http://phpjs.org/functions/quotemeta
  16984. // + original by: Paulo Freitas
  16985. // * example 1: \php.quotemeta(". + * ? ^ ( $ )");
  16986. // * returns 1: '\. \+ \* \? \^ \( \$ \)'
  16987. return (str + '').replace(/([\.\\\+\*\?\[\^\]\$\(\)])/g, '\\$1');
  16988. };
  16989. php.rand = function (min, max) {
  16990. // Returns a random number
  16991. //
  16992. // version: 1103.1210
  16993. // discuss at: http://phpjs.org/functions/rand
  16994. // + original by: Leslie Hoare
  16995. // + bugfixed by: Onno Marsman
  16996. // % note 1: See the commented out code below for a version which will work with our experimental (though probably unnecessary) srand() function)
  16997. // * example 1: \php.rand(1, 1);
  16998. // * returns 1: 1
  16999. var argc = arguments.length;
  17000. if (argc === 0) {
  17001. min = 0;
  17002. max = 2147483647;
  17003. } else if (argc === 1) {
  17004. throw new Error('Warning: rand() expects exactly 2 parameters, 1 given');
  17005. }
  17006. return Math.floor(Math.random() * (max - min + 1)) + min;
  17007. /*
  17008. // See note above for an explanation of the following alternative code
  17009. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  17010. // - depends on: srand
  17011. // % note 1: This is a very possibly imperfect adaptation from the PHP source code
  17012. var rand_seed, ctx, PHP_RAND_MAX=2147483647; // 0x7fffffff
  17013. if (!this.php_js || this.php_js.rand_seed === undefined) {
  17014. this.srand();
  17015. }
  17016. rand_seed = this.php_js.rand_seed;
  17017. var argc = arguments.length;
  17018. if (argc === 1) {
  17019. throw new Error('Warning: rand() expects exactly 2 parameters, 1 given');
  17020. }
  17021. var do_rand = function (ctx) {
  17022. return ((ctx * 1103515245 + 12345) % (PHP_RAND_MAX + 1));
  17023. };
  17024. var php_rand = function (ctxArg) { // php_rand_r
  17025. this.php_js.rand_seed = do_rand(ctxArg);
  17026. return parseInt(this.php_js.rand_seed, 10);
  17027. };
  17028. var number = php_rand(rand_seed);
  17029. if (argc === 2) {
  17030. number = min + parseInt(parseFloat(parseFloat(max) - min + 1.0) * (number/(PHP_RAND_MAX + 1.0)), 10);
  17031. }
  17032. return number;
  17033. */
  17034. };
  17035. php.range = function (low, high, step) {
  17036. // Create an array containing the range of integers or characters from low to high (inclusive)
  17037. //
  17038. // version: 1103.1210
  17039. // discuss at: http://phpjs.org/functions/range
  17040. // + original by: Waldo Malqui Silva
  17041. // * example 1: \php.range ( 0, 12 );
  17042. // * returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  17043. // * example 2: \php.range( 0, 100, 10 );
  17044. // * returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
  17045. // * example 3: \php.range( 'a', 'i' );
  17046. // * returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
  17047. // * example 4: \php.range( 'c', 'a' );
  17048. // * returns 4: ['c', 'b', 'a']
  17049. var matrix = [];
  17050. var inival, endval, plus;
  17051. var walker = step || 1;
  17052. var chars = false;
  17053. if (!isNaN(low) && !isNaN(high)) {
  17054. inival = low;
  17055. endval = high;
  17056. } else if (isNaN(low) && isNaN(high)) {
  17057. chars = true;
  17058. inival = low.charCodeAt(0);
  17059. endval = high.charCodeAt(0);
  17060. } else {
  17061. inival = (isNaN(low) ? 0 : low);
  17062. endval = (isNaN(high) ? 0 : high);
  17063. }
  17064. plus = ((inival > endval) ? false : true);
  17065. if (plus) {
  17066. while (inival <= endval) {
  17067. matrix.push(((chars) ? String.fromCharCode(inival) : inival));
  17068. inival += walker;
  17069. }
  17070. } else {
  17071. while (inival >= endval) {
  17072. matrix.push(((chars) ? String.fromCharCode(inival) : inival));
  17073. inival -= walker;
  17074. }
  17075. }
  17076. return matrix;
  17077. };
  17078. php.reset = function (arr) {
  17079. // Set array argument's internal pointer to the first element and return it
  17080. //
  17081. // version: 1103.1210
  17082. // discuss at: http://phpjs.org/functions/reset
  17083. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17084. // + bugfixed by: Legaev Andrey
  17085. // + revised by: Brett Zamir (http://brett-zamir.me)
  17086. // % note 1: Uses global: php_js to store the array pointer
  17087. // * example 1: \php.reset({0: 'Kevin', 1: 'van', 2: 'Zonneveld'});
  17088. // * returns 1: 'Kevin'
  17089. // BEGIN REDUNDANT
  17090. this.php_js = this.php_js || {};
  17091. this.php_js.pointers = this.php_js.pointers || [];
  17092. var indexOf = function (value) {
  17093. for (var i = 0, length = this.length; i < length; i++) {
  17094. if (this[i] === value) {
  17095. return i;
  17096. }
  17097. }
  17098. return -1;
  17099. };
  17100. // END REDUNDANT
  17101. var pointers = this.php_js.pointers;
  17102. if (!pointers.indexOf) {
  17103. pointers.indexOf = indexOf;
  17104. }
  17105. if (pointers.indexOf(arr) === -1) {
  17106. pointers.push(arr, 0);
  17107. }
  17108. var arrpos = pointers.indexOf(arr);
  17109. if (!(arr instanceof Array)) {
  17110. for (var k in arr) {
  17111. if (pointers.indexOf(arr) === -1) {
  17112. pointers.push(arr, 0);
  17113. } else {
  17114. pointers[arrpos + 1] = 0;
  17115. }
  17116. return arr[k];
  17117. }
  17118. return false; // Empty
  17119. }
  17120. if (arr.length === 0) {
  17121. return false;
  17122. }
  17123. pointers[arrpos + 1] = 0;
  17124. return arr[pointers[arrpos + 1]];
  17125. };
  17126. php.round = function (value, precision, mode) {
  17127. // Returns the number rounded to specified precision
  17128. //
  17129. // version: 1103.1210
  17130. // discuss at: http://phpjs.org/functions/round
  17131. // + original by: Philip Peterson
  17132. // + revised by: Onno Marsman
  17133. // + input by: Greenseed
  17134. // + revised by: T.Wild
  17135. // + input by: meo
  17136. // + input by: William
  17137. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  17138. // + input by: Josep Sanz (http://www.ws3.es/)
  17139. // + revised by: Rafał Kukawski (http://blog.kukawski.pl/)
  17140. // % note 1: Great work. Ideas for improvement:
  17141. // % note 1: - code more compliant with developer guidelines
  17142. // % note 1: - for implementing PHP constant arguments look at
  17143. // % note 1: the pathinfo() function, it offers the greatest
  17144. // % note 1: flexibility & compatibility possible
  17145. // * example 1: \php.round(1241757, -3);
  17146. // * returns 1: 1242000
  17147. // * example 2: \php.round(3.6);
  17148. // * returns 2: 4
  17149. // * example 3: \php.round(2.835, 2);
  17150. // * returns 3: 2.84
  17151. // * example 4: \php.round(1.1749999999999, 2);
  17152. // * returns 4: 1.17
  17153. // * example 5: \php.round(58551.799999999996, 2);
  17154. // * returns 5: 58551.8
  17155. var m, f, isHalf, sgn; // helper variables
  17156. precision |= 0; // making sure precision is integer
  17157. m = Math.pow(10, precision);
  17158. value *= m;
  17159. sgn = (value > 0) | -(value < 0); // sign of the number
  17160. isHalf = value % 1 === 0.5 * sgn;
  17161. f = Math.floor(value);
  17162. if (isHalf) {
  17163. switch (mode) {
  17164. case 'PHP_ROUND_HALF_DOWN':
  17165. value = f + (sgn < 0); // rounds .5 toward zero
  17166. break;
  17167. case 'PHP_ROUND_HALF_EVEN':
  17168. value = f + (f % 2 * sgn); // rouds .5 towards the next even integer
  17169. break;
  17170. case 'PHP_ROUND_HALF_ODD':
  17171. value = f + !(f % 2); // rounds .5 towards the next odd integer
  17172. break;
  17173. default:
  17174. value = f + (sgn > 0); // rounds .5 away from zero
  17175. }
  17176. }
  17177. return (isHalf ? value : Math.round(value)) / m;
  17178. };
  17179. php.rsort = function (inputArr, sort_flags) {
  17180. // Sort an array in reverse order
  17181. //
  17182. // version: 1103.1210
  17183. // discuss at: http://phpjs.org/functions/rsort
  17184. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17185. // + revised by: Brett Zamir (http://brett-zamir.me)
  17186. // + improved by: Brett Zamir (http://brett-zamir.me)
  17187. // % note 1: SORT_STRING (as well as natsort and natcasesort) might also be
  17188. // % note 1: integrated into all of these functions by adapting the code at
  17189. // % note 1: http://sourcefrog.net/projects/natsort/natcompare.js
  17190. // % note 2: This function deviates from PHP in returning a copy of the array instead
  17191. // % note 2: of acting by reference and returning true; this was necessary because
  17192. // % note 2: IE does not allow deleting and re-adding of properties without caching
  17193. // % note 2: of property position; you can set the ini of "phpjs.strictForIn" to true to
  17194. // % note 2: get the PHP behavior, but use this only if you are in an environment
  17195. // % note 2: such as Firefox extensions where for-in iteration order is fixed and true
  17196. // % note 2: property deletion is supported. Note that we intend to implement the PHP
  17197. // % note 2: behavior by default if IE ever does allow it; only gives shallow copy since
  17198. // % note 2: is by reference in PHP anyways
  17199. // % note 3: Since JS objects' keys are always strings, and (the
  17200. // % note 3: default) SORT_REGULAR flag distinguishes by key type,
  17201. // % note 3: if the content is a numeric string, we treat the
  17202. // % note 3: "original type" as numeric.
  17203. // - depends on: i18n_loc_get_default
  17204. // * example 1: \php.rsort(['Kevin', 'van', 'Zonneveld']);
  17205. // * returns 1: ['van', 'Zonneveld', 'Kevin']
  17206. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  17207. // * example 2: \php.fruits = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  17208. // * example 2: \php.rsort(fruits);
  17209. // * results 2: fruits == {0: 'orange', 1: 'lemon', 2: 'banana', 3: 'apple'}
  17210. // * returns 2: true
  17211. var valArr = [],
  17212. k = '',
  17213. i = 0,
  17214. sorter = false,
  17215. that = this,
  17216. strictForIn = false,
  17217. populateArr = [];
  17218. switch (sort_flags) {
  17219. case 'SORT_STRING':
  17220. // compare items as strings
  17221. sorter = function (a, b) {
  17222. return that.strnatcmp(b, a);
  17223. };
  17224. break;
  17225. case 'SORT_LOCALE_STRING':
  17226. // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
  17227. var loc = this.i18n_loc_get_default();
  17228. sorter = this.php_js.i18nLocales[loc].sorting;
  17229. break;
  17230. case 'SORT_NUMERIC':
  17231. // compare items numerically
  17232. sorter = function (a, b) {
  17233. return (b - a);
  17234. };
  17235. break;
  17236. case 'SORT_REGULAR':
  17237. // compare items normally (don't change types)
  17238. default:
  17239. sorter = function (b, a) {
  17240. var aFloat = parseFloat(a),
  17241. bFloat = parseFloat(b),
  17242. aNumeric = aFloat + '' === a,
  17243. bNumeric = bFloat + '' === b;
  17244. if (aNumeric && bNumeric) {
  17245. return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  17246. } else if (aNumeric && !bNumeric) {
  17247. return 1;
  17248. } else if (!aNumeric && bNumeric) {
  17249. return -1;
  17250. }
  17251. return a > b ? 1 : a < b ? -1 : 0;
  17252. };
  17253. break;
  17254. }
  17255. // BEGIN REDUNDANT
  17256. this.php_js = this.php_js || {};
  17257. this.php_js.ini = this.php_js.ini || {};
  17258. // END REDUNDANT
  17259. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  17260. populateArr = strictForIn ? inputArr : populateArr;
  17261. for (k in inputArr) { // Get key and value arrays
  17262. if (inputArr.hasOwnProperty(k)) {
  17263. valArr.push(inputArr[k]);
  17264. if (strictForIn) {
  17265. delete inputArr[k];
  17266. }
  17267. }
  17268. }
  17269. valArr.sort(sorter);
  17270. for (i = 0; i < valArr.length; i++) { // Repopulate the old array
  17271. populateArr[i] = valArr[i];
  17272. }
  17273. return strictForIn || populateArr;
  17274. };
  17275. php.setcookie = function (name, value, expires, path, domain, secure) {
  17276. // Send a cookie
  17277. //
  17278. // version: 1103.1210
  17279. // discuss at: http://phpjs.org/functions/setcookie
  17280. // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  17281. // + bugfixed by: Andreas
  17282. // + bugfixed by: Onno Marsman
  17283. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17284. // - depends on: setrawcookie
  17285. // * example 1: \php.setcookie('author_name', 'Kevin van Zonneveld');
  17286. // * returns 1: true
  17287. return this.setrawcookie(name, encodeURIComponent(value), expires, path, domain, secure);
  17288. };
  17289. php.setrawcookie = function (name, value, expires, path, domain, secure) {
  17290. // Send a cookie with no url encoding of the value
  17291. //
  17292. // version: 1103.1210
  17293. // discuss at: http://phpjs.org/functions/setrawcookie
  17294. // + original by: Brett Zamir (http://brett-zamir.me)
  17295. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17296. // + derived from: setcookie
  17297. // + input by: Michael
  17298. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  17299. // * example 1: \php.setcookie('author_name', 'Kevin van Zonneveld');
  17300. // * returns 1: true
  17301. if (typeof expires === 'string' && (/^\d+$/).test(expires)) {
  17302. expires = parseInt(expires, 10);
  17303. }
  17304. if (expires instanceof Date) {
  17305. expires = expires.toGMTString();
  17306. } else if (typeof(expires) === 'number') {
  17307. expires = (new Date(expires * 1e3)).toGMTString();
  17308. }
  17309. var r = [name + '=' + value],
  17310. s = {},
  17311. i = '';
  17312. s = {
  17313. expires: expires,
  17314. path: path,
  17315. domain: domain
  17316. };
  17317. for (i in s) {
  17318. if (s.hasOwnProperty(i)) { // Exclude items on Object.prototype
  17319. s[i] && r.push(i + '=' + s[i]);
  17320. }
  17321. }
  17322. return secure && r.push('secure'), this.window.document.cookie = r.join(";"), true;
  17323. };
  17324. php.sha1 = function (str) {
  17325. // Calculate the sha1 hash of a string
  17326. //
  17327. // version: 1103.1210
  17328. // discuss at: http://phpjs.org/functions/sha1
  17329. // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
  17330. // + namespaced by: Michael White (http://getsprink.com)
  17331. // + input by: Brett Zamir (http://brett-zamir.me)
  17332. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17333. // - depends on: utf8_encode
  17334. // * example 1: \php.sha1('Kevin van Zonneveld');
  17335. // * returns 1: '54916d2e62f65b3afa6e192e6a601cdbe5cb5897'
  17336. var rotate_left = function (n, s) {
  17337. var t4 = (n << s) | (n >>> (32 - s));
  17338. return t4;
  17339. };
  17340. /*var lsb_hex = function (val) { // Not in use; needed?
  17341. var str="";
  17342. var i;
  17343. var vh;
  17344. var vl;
  17345. for ( i=0; i<=6; i+=2 ) {
  17346. vh = (val>>>(i*4+4))&0x0f;
  17347. vl = (val>>>(i*4))&0x0f;
  17348. str += vh.toString(16) + vl.toString(16);
  17349. }
  17350. return str;
  17351. };*/
  17352. var cvt_hex = function (val) {
  17353. var str = "";
  17354. var i;
  17355. var v;
  17356. for (i = 7; i >= 0; i--) {
  17357. v = (val >>> (i * 4)) & 0x0f;
  17358. str += v.toString(16);
  17359. }
  17360. return str;
  17361. };
  17362. var blockstart;
  17363. var i, j;
  17364. var W = new Array(80);
  17365. var H0 = 0x67452301;
  17366. var H1 = 0xEFCDAB89;
  17367. var H2 = 0x98BADCFE;
  17368. var H3 = 0x10325476;
  17369. var H4 = 0xC3D2E1F0;
  17370. var A, B, C, D, E;
  17371. var temp;
  17372. str = this.utf8_encode(str);
  17373. var str_len = str.length;
  17374. var word_array = [];
  17375. for (i = 0; i < str_len - 3; i += 4) {
  17376. j = str.charCodeAt(i) << 24 | str.charCodeAt(i + 1) << 16 | str.charCodeAt(i + 2) << 8 | str.charCodeAt(i + 3);
  17377. word_array.push(j);
  17378. }
  17379. switch (str_len % 4) {
  17380. case 0:
  17381. i = 0x080000000;
  17382. break;
  17383. case 1:
  17384. i = str.charCodeAt(str_len - 1) << 24 | 0x0800000;
  17385. break;
  17386. case 2:
  17387. i = str.charCodeAt(str_len - 2) << 24 | str.charCodeAt(str_len - 1) << 16 | 0x08000;
  17388. break;
  17389. case 3:
  17390. i = str.charCodeAt(str_len - 3) << 24 | str.charCodeAt(str_len - 2) << 16 | str.charCodeAt(str_len - 1) << 8 | 0x80;
  17391. break;
  17392. }
  17393. word_array.push(i);
  17394. while ((word_array.length % 16) != 14) {
  17395. word_array.push(0);
  17396. }
  17397. word_array.push(str_len >>> 29);
  17398. word_array.push((str_len << 3) & 0x0ffffffff);
  17399. for (blockstart = 0; blockstart < word_array.length; blockstart += 16) {
  17400. for (i = 0; i < 16; i++) {
  17401. W[i] = word_array[blockstart + i];
  17402. }
  17403. for (i = 16; i <= 79; i++) {
  17404. W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
  17405. }
  17406. A = H0;
  17407. B = H1;
  17408. C = H2;
  17409. D = H3;
  17410. E = H4;
  17411. for (i = 0; i <= 19; i++) {
  17412. temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
  17413. E = D;
  17414. D = C;
  17415. C = rotate_left(B, 30);
  17416. B = A;
  17417. A = temp;
  17418. }
  17419. for (i = 20; i <= 39; i++) {
  17420. temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
  17421. E = D;
  17422. D = C;
  17423. C = rotate_left(B, 30);
  17424. B = A;
  17425. A = temp;
  17426. }
  17427. for (i = 40; i <= 59; i++) {
  17428. temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
  17429. E = D;
  17430. D = C;
  17431. C = rotate_left(B, 30);
  17432. B = A;
  17433. A = temp;
  17434. }
  17435. for (i = 60; i <= 79; i++) {
  17436. temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
  17437. E = D;
  17438. D = C;
  17439. C = rotate_left(B, 30);
  17440. B = A;
  17441. A = temp;
  17442. }
  17443. H0 = (H0 + A) & 0x0ffffffff;
  17444. H1 = (H1 + B) & 0x0ffffffff;
  17445. H2 = (H2 + C) & 0x0ffffffff;
  17446. H3 = (H3 + D) & 0x0ffffffff;
  17447. H4 = (H4 + E) & 0x0ffffffff;
  17448. }
  17449. temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
  17450. return temp.toLowerCase();
  17451. };
  17452. php.shuffle = function (inputArr) {
  17453. // Randomly shuffle the contents of an array
  17454. //
  17455. // version: 1103.1210
  17456. // discuss at: http://phpjs.org/functions/shuffle
  17457. // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  17458. // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17459. // + revised by: Brett Zamir (http://brett-zamir.me)
  17460. // + improved by: Brett Zamir (http://brett-zamir.me)
  17461. // % note 1: This function deviates from PHP in returning a copy of the array instead
  17462. // % note 1: of acting by reference and returning true; this was necessary because
  17463. // % note 1: IE does not allow deleting and re-adding of properties without caching
  17464. // % note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
  17465. // % note 1: get the PHP behavior, but use this only if you are in an environment
  17466. // % note 1: such as Firefox extensions where for-in iteration order is fixed and true
  17467. // % note 1: property deletion is supported. Note that we intend to implement the PHP
  17468. // % note 1: behavior by default if IE ever does allow it; only gives shallow copy since
  17469. // % note 1: is by reference in PHP anyways
  17470. // * example 1: \php.ini_set('phpjs.strictForIn', true);
  17471. // * example 1: \php.shuffle({5:'a', 2:'3', 3:'c', 4:5, 'q':5});
  17472. // * returns 1: {5:'a', 4:5, 'q':5, 3:'c', 2:'3'}
  17473. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  17474. // * example 2: \php.var data = {5:'a', 2:'3', 3:'c', 4:5, 'q':5};
  17475. // * example 2: \php.shuffle(data);
  17476. // * results 2: {5:'a', 'q':5, 3:'c', 2:'3', 4:5}
  17477. // * returns 2: true
  17478. var valArr = [],
  17479. k = '',
  17480. i = 0,
  17481. strictForIn = false,
  17482. populateArr = [];
  17483. for (k in inputArr) { // Get key and value arrays
  17484. if (inputArr.hasOwnProperty(k)) {
  17485. valArr.push(inputArr[k]);
  17486. if (strictForIn) {
  17487. delete inputArr[k];
  17488. }
  17489. }
  17490. }
  17491. valArr.sort(function () {
  17492. return 0.5 - Math.random();
  17493. });
  17494. // BEGIN REDUNDANT
  17495. this.php_js = this.php_js || {};
  17496. this.php_js.ini = this.php_js.ini || {};
  17497. // END REDUNDANT
  17498. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  17499. populateArr = strictForIn ? inputArr : populateArr;
  17500. for (i = 0; i < valArr.length; i++) { // Repopulate the old array
  17501. populateArr[i] = valArr[i];
  17502. }
  17503. return strictForIn || populateArr;
  17504. };
  17505. php.sizeof = function (mixed_var, mode) {
  17506. // !No description available for sizeof. @php.js developers: Please update the function summary text file.
  17507. //
  17508. // version: 1103.1210
  17509. // discuss at: http://phpjs.org/functions/sizeof
  17510. // + original by: Philip Peterson
  17511. // - depends on: count
  17512. // * example 1: \php.sizeof([[0,0],[0,-4]], 'COUNT_RECURSIVE');
  17513. // * returns 1: 6
  17514. // * example 2: \php.sizeof({'one' : [1,2,3,4,5]}, 'COUNT_RECURSIVE');
  17515. // * returns 2: 6
  17516. return this.count(mixed_var, mode);
  17517. };
  17518. php.sort = function (inputArr, sort_flags) {
  17519. // Sort an array
  17520. //
  17521. // version: 1103.1210
  17522. // discuss at: http://phpjs.org/functions/sort
  17523. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17524. // + revised by: Brett Zamir (http://brett-zamir.me)
  17525. // + improved by: Brett Zamir (http://brett-zamir.me)
  17526. // % note 1: SORT_STRING (as well as natsort and natcasesort) might also be
  17527. // % note 1: integrated into all of these functions by adapting the code at
  17528. // % note 1: http://sourcefrog.net/projects/natsort/natcompare.js
  17529. // % note 2: This function deviates from PHP in returning a copy of the array instead
  17530. // % note 2: of acting by reference and returning true; this was necessary because
  17531. // % note 2: IE does not allow deleting and re-adding of properties without caching
  17532. // % note 2: of property position; you can set the ini of "phpjs.strictForIn" to true to
  17533. // % note 2: get the PHP behavior, but use this only if you are in an environment
  17534. // % note 2: such as Firefox extensions where for-in iteration order is fixed and true
  17535. // % note 2: property deletion is supported. Note that we intend to implement the PHP
  17536. // % note 2: behavior by default if IE ever does allow it; only gives shallow copy since
  17537. // % note 2: is by reference in PHP anyways
  17538. // % note 3: Since JS objects' keys are always strings, and (the
  17539. // % note 3: default) SORT_REGULAR flag distinguishes by key type,
  17540. // % note 3: if the content is a numeric string, we treat the
  17541. // % note 3: "original type" as numeric.
  17542. // - depends on: i18n_loc_get_default
  17543. // * example 1: \php.sort(['Kevin', 'van', 'Zonneveld']);
  17544. // * returns 1: ['Kevin', 'Zonneveld', 'van']
  17545. // * example 2: \php.ini_set('phpjs.strictForIn', true);
  17546. // * example 2: \php.fruits = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  17547. // * example 2: \php.sort(fruits);
  17548. // * results 2: fruits == {0: 'apple', 1: 'banana', 2: 'lemon', 3: 'orange'}
  17549. // * returns 2: true
  17550. var valArr = [],
  17551. keyArr = [],
  17552. k = '',
  17553. i = 0,
  17554. sorter = false,
  17555. that = this,
  17556. strictForIn = false,
  17557. populateArr = [];
  17558. switch (sort_flags) {
  17559. case 'SORT_STRING':
  17560. // compare items as strings
  17561. sorter = function (a, b) {
  17562. return that.strnatcmp(a, b);
  17563. };
  17564. break;
  17565. case 'SORT_LOCALE_STRING':
  17566. // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
  17567. var loc = this.i18n_loc_get_default();
  17568. sorter = this.php_js.i18nLocales[loc].sorting;
  17569. break;
  17570. case 'SORT_NUMERIC':
  17571. // compare items numerically
  17572. sorter = function (a, b) {
  17573. return (a - b);
  17574. };
  17575. break;
  17576. case 'SORT_REGULAR':
  17577. // compare items normally (don't change types)
  17578. default:
  17579. sorter = function (a, b) {
  17580. var aFloat = parseFloat(a),
  17581. bFloat = parseFloat(b),
  17582. aNumeric = aFloat + '' === a,
  17583. bNumeric = bFloat + '' === b;
  17584. if (aNumeric && bNumeric) {
  17585. return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  17586. } else if (aNumeric && !bNumeric) {
  17587. return 1;
  17588. } else if (!aNumeric && bNumeric) {
  17589. return -1;
  17590. }
  17591. return a > b ? 1 : a < b ? -1 : 0;
  17592. };
  17593. break;
  17594. }
  17595. // BEGIN REDUNDANT
  17596. this.php_js = this.php_js || {};
  17597. this.php_js.ini = this.php_js.ini || {};
  17598. // END REDUNDANT
  17599. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  17600. populateArr = strictForIn ? inputArr : populateArr;
  17601. for (k in inputArr) { // Get key and value arrays
  17602. if (inputArr.hasOwnProperty(k)) {
  17603. valArr.push(inputArr[k]);
  17604. if (strictForIn) {
  17605. delete inputArr[k];
  17606. }
  17607. }
  17608. }
  17609. valArr.sort(sorter);
  17610. for (i = 0; i < valArr.length; i++) { // Repopulate the old array
  17611. populateArr[i] = valArr[i];
  17612. }
  17613. return strictForIn || populateArr;
  17614. };
  17615. php.sprintf = function () {
  17616. // Return a formatted string
  17617. //
  17618. // version: 1103.1210
  17619. // discuss at: http://phpjs.org/functions/sprintf
  17620. // + original by: Ash Searle (http://hexmen.com/blog/)
  17621. // + namespaced by: Michael White (http://getsprink.com)
  17622. // + tweaked by: Jack
  17623. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17624. // + input by: Paulo Freitas
  17625. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17626. // + input by: Brett Zamir (http://brett-zamir.me)
  17627. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17628. // * example 1: \php.sprintf("%01.2f", 123.1);
  17629. // * returns 1: 123.10
  17630. // * example 2: \php.sprintf("[%10s]", 'monkey');
  17631. // * returns 2: '[ monkey]'
  17632. // * example 3: \php.sprintf("[%'#10s]", 'monkey');
  17633. // * returns 3: '[####monkey]'
  17634. var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
  17635. var a = arguments,
  17636. i = 0,
  17637. format = a[i++];
  17638. // pad()
  17639. var pad = function (str, len, chr, leftJustify) {
  17640. if (!chr) {
  17641. chr = ' ';
  17642. }
  17643. var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
  17644. return leftJustify ? str + padding : padding + str;
  17645. };
  17646. // justify()
  17647. var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
  17648. var diff = minWidth - value.length;
  17649. if (diff > 0) {
  17650. if (leftJustify || !zeroPad) {
  17651. value = pad(value, minWidth, customPadChar, leftJustify);
  17652. } else {
  17653. value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
  17654. }
  17655. }
  17656. return value;
  17657. };
  17658. // formatBaseX()
  17659. var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
  17660. // Note: casts negative numbers to positive ones
  17661. var number = value >>> 0;
  17662. prefix = prefix && number && {
  17663. '2': '0b',
  17664. '8': '0',
  17665. '16': '0x'
  17666. }[base] || '';
  17667. value = prefix + pad(number.toString(base), precision || 0, '0', false);
  17668. return justify(value, prefix, leftJustify, minWidth, zeroPad);
  17669. };
  17670. // formatString()
  17671. var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
  17672. if (precision != null) {
  17673. value = value.slice(0, precision);
  17674. }
  17675. return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
  17676. };
  17677. // doFormat()
  17678. var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
  17679. var number;
  17680. var prefix;
  17681. var method;
  17682. var textTransform;
  17683. var value;
  17684. if (substring == '%%') {
  17685. return '%';
  17686. }
  17687. // parse flags
  17688. var leftJustify = false,
  17689. positivePrefix = '',
  17690. zeroPad = false,
  17691. prefixBaseX = false,
  17692. customPadChar = ' ';
  17693. var flagsl = flags.length;
  17694. for (var j = 0; flags && j < flagsl; j++) {
  17695. switch (flags.charAt(j)) {
  17696. case ' ':
  17697. positivePrefix = ' ';
  17698. break;
  17699. case '+':
  17700. positivePrefix = '+';
  17701. break;
  17702. case '-':
  17703. leftJustify = true;
  17704. break;
  17705. case "'":
  17706. customPadChar = flags.charAt(j + 1);
  17707. break;
  17708. case '0':
  17709. zeroPad = true;
  17710. break;
  17711. case '#':
  17712. prefixBaseX = true;
  17713. break;
  17714. }
  17715. }
  17716. // parameters may be null, undefined, empty-string or real valued
  17717. // we want to ignore null, undefined and empty-string values
  17718. if (!minWidth) {
  17719. minWidth = 0;
  17720. } else if (minWidth == '*') {
  17721. minWidth = +a[i++];
  17722. } else if (minWidth.charAt(0) == '*') {
  17723. minWidth = +a[minWidth.slice(1, -1)];
  17724. } else {
  17725. minWidth = +minWidth;
  17726. }
  17727. // Note: undocumented perl feature:
  17728. if (minWidth < 0) {
  17729. minWidth = -minWidth;
  17730. leftJustify = true;
  17731. }
  17732. if (!isFinite(minWidth)) {
  17733. throw new Error('sprintf: (minimum-)width must be finite');
  17734. }
  17735. if (!precision) {
  17736. precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined;
  17737. } else if (precision == '*') {
  17738. precision = +a[i++];
  17739. } else if (precision.charAt(0) == '*') {
  17740. precision = +a[precision.slice(1, -1)];
  17741. } else {
  17742. precision = +precision;
  17743. }
  17744. // grab value using valueIndex if required?
  17745. value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];
  17746. switch (type) {
  17747. case 's':
  17748. return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
  17749. case 'c':
  17750. return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
  17751. case 'b':
  17752. return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
  17753. case 'o':
  17754. return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
  17755. case 'x':
  17756. return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
  17757. case 'X':
  17758. return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
  17759. case 'u':
  17760. return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
  17761. case 'i':
  17762. case 'd':
  17763. number = (+value) | 0;
  17764. prefix = number < 0 ? '-' : positivePrefix;
  17765. value = prefix + pad(String(Math.abs(number)), precision, '0', false);
  17766. return justify(value, prefix, leftJustify, minWidth, zeroPad);
  17767. case 'e':
  17768. case 'E':
  17769. case 'f':
  17770. case 'F':
  17771. case 'g':
  17772. case 'G':
  17773. number = +value;
  17774. prefix = number < 0 ? '-' : positivePrefix;
  17775. method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
  17776. textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
  17777. value = prefix + Math.abs(number)[method](precision);
  17778. return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
  17779. default:
  17780. return substring;
  17781. }
  17782. };
  17783. return format.replace(regex, doFormat);
  17784. };
  17785. php.str_ireplace = function (search, replace, subject) {
  17786. // Replaces all occurrences of search in haystack with replace / case-insensitive
  17787. //
  17788. // version: 1103.1210
  17789. // discuss at: http://phpjs.org/functions/str_ireplace
  17790. // + original by: Martijn Wieringa
  17791. // + input by: penutbutterjelly
  17792. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17793. // + tweaked by: Jack
  17794. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17795. // + bugfixed by: Onno Marsman
  17796. // + input by: Brett Zamir (http://brett-zamir.me)
  17797. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17798. // + bugfixed by: Philipp Lenssen
  17799. // * example 1: \php.str_ireplace('l', 'l', 'HeLLo');
  17800. // * returns 1: 'Hello'
  17801. // * example 2: \php.str_ireplace('$', 'foo', '$bar');
  17802. // * returns 2: 'foobar'
  17803. var i, k = '';
  17804. var searchl = 0;
  17805. var reg;
  17806. var escapeRegex = function (s) {
  17807. return s.replace(/([\\\^\$*+\[\]?{}.=!:(|)])/g, '\\$1');
  17808. };
  17809. search += '';
  17810. searchl = search.length;
  17811. if (!(replace instanceof Array)) {
  17812. replace = [replace];
  17813. if (search instanceof Array) {
  17814. // If search is an array and replace is a string,
  17815. // then this replacement string is used for every value of search
  17816. while (searchl > replace.length) {
  17817. replace[replace.length] = replace[0];
  17818. }
  17819. }
  17820. }
  17821. if (!(search instanceof Array)) {
  17822. search = [search];
  17823. }
  17824. while (search.length > replace.length) {
  17825. // If replace has fewer values than search,
  17826. // then an empty string is used for the rest of replacement values
  17827. replace[replace.length] = '';
  17828. }
  17829. if (subject instanceof Array) {
  17830. // If subject is an array, then the search and replace is performed
  17831. // with every entry of subject , and the return value is an array as well.
  17832. for (k in subject) {
  17833. if (subject.hasOwnProperty(k)) {
  17834. subject[k] = str_ireplace(search, replace, subject[k]);
  17835. }
  17836. }
  17837. return subject;
  17838. }
  17839. searchl = search.length;
  17840. for (i = 0; i < searchl; i++) {
  17841. reg = new RegExp(escapeRegex(search[i]), 'gi');
  17842. subject = subject.replace(reg, replace[i]);
  17843. }
  17844. return subject;
  17845. };
  17846. php.str_pad = function (input, pad_length, pad_string, pad_type) {
  17847. // Returns input string padded on the left or right to specified length with pad_string
  17848. //
  17849. // version: 1103.1210
  17850. // discuss at: http://phpjs.org/functions/str_pad
  17851. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17852. // + namespaced by: Michael White (http://getsprink.com)
  17853. // + input by: Marco van Oort
  17854. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  17855. // * example 1: \php.str_pad('Kevin van Zonneveld', 30, '-=', 'STR_PAD_LEFT');
  17856. // * returns 1: '-=-=-=-=-=-Kevin van Zonneveld'
  17857. // * example 2: \php.str_pad('Kevin van Zonneveld', 30, '-', 'STR_PAD_BOTH');
  17858. // * returns 2: '------Kevin van Zonneveld-----'
  17859. var half = '',
  17860. pad_to_go;
  17861. var str_pad_repeater = function (s, len) {
  17862. var collect = '',
  17863. i;
  17864. while (collect.length < len) {
  17865. collect += s;
  17866. }
  17867. collect = collect.substr(0, len);
  17868. return collect;
  17869. };
  17870. input += '';
  17871. pad_string = pad_string !== undefined ? pad_string : ' ';
  17872. if (pad_type != 'STR_PAD_LEFT' && pad_type != 'STR_PAD_RIGHT' && pad_type != 'STR_PAD_BOTH') {
  17873. pad_type = 'STR_PAD_RIGHT';
  17874. }
  17875. if ((pad_to_go = pad_length - input.length) > 0) {
  17876. if (pad_type == 'STR_PAD_LEFT') {
  17877. input = str_pad_repeater(pad_string, pad_to_go) + input;
  17878. } else if (pad_type == 'STR_PAD_RIGHT') {
  17879. input = input + str_pad_repeater(pad_string, pad_to_go);
  17880. } else if (pad_type == 'STR_PAD_BOTH') {
  17881. half = str_pad_repeater(pad_string, Math.ceil(pad_to_go / 2));
  17882. input = half + input + half;
  17883. input = input.substr(0, pad_length);
  17884. }
  17885. }
  17886. return input;
  17887. };
  17888. php.str_repeat = function (input, multiplier) {
  17889. // Returns the input string repeat mult times
  17890. //
  17891. // version: 1103.1210
  17892. // discuss at: http://phpjs.org/functions/str_repeat
  17893. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17894. // + improved by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  17895. // * example 1: \php.str_repeat('-=', 10);
  17896. // * returns 1: '-=-=-=-=-=-=-=-=-=-='
  17897. return new Array(multiplier + 1).join(input);
  17898. };
  17899. php.str_replace = function (search, replace, subject, count) {
  17900. // Replaces all occurrences of search in haystack with replace
  17901. //
  17902. // version: 1103.1210
  17903. // discuss at: http://phpjs.org/functions/str_replace
  17904. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17905. // + improved by: Gabriel Paderni
  17906. // + improved by: Philip Peterson
  17907. // + improved by: Simon Willison (http://simonwillison.net)
  17908. // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  17909. // + bugfixed by: Anton Ongson
  17910. // + input by: Onno Marsman
  17911. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17912. // + tweaked by: Onno Marsman
  17913. // + input by: Brett Zamir (http://brett-zamir.me)
  17914. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17915. // + input by: Oleg Eremeev
  17916. // + improved by: Brett Zamir (http://brett-zamir.me)
  17917. // + bugfixed by: Oleg Eremeev
  17918. // % note 1: The count parameter must be passed as a string in order
  17919. // % note 1: to find a global variable in which the result will be given
  17920. // * example 1: \php.str_replace(' ', '.', 'Kevin van Zonneveld');
  17921. // * returns 1: 'Kevin.van.Zonneveld'
  17922. // * example 2: \php.str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
  17923. // * returns 2: 'hemmo, mars'
  17924. var i = 0,
  17925. j = 0,
  17926. temp = '',
  17927. repl = '',
  17928. sl = 0,
  17929. fl = 0,
  17930. f = [].concat(search),
  17931. r = [].concat(replace),
  17932. s = subject,
  17933. ra = r instanceof Array,
  17934. sa = s instanceof Array;
  17935. s = [].concat(s);
  17936. if (count) {
  17937. this.window[count] = 0;
  17938. }
  17939. for (i = 0, sl = s.length; i < sl; i++) {
  17940. if (s[i] === '') {
  17941. continue;
  17942. }
  17943. for (j = 0, fl = f.length; j < fl; j++) {
  17944. temp = s[i] + '';
  17945. repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
  17946. s[i] = (temp).split(f[j]).join(repl);
  17947. if (count && s[i] !== temp) {
  17948. this.window[count] += (temp.length - s[i].length) / f[j].length;
  17949. }
  17950. }
  17951. }
  17952. return sa ? s : s[0];
  17953. };
  17954. php.str_word_count = function (str, format, charlist) {
  17955. // Counts the number of words inside a string. If format of 1 is specified, then the function will return an array containing all the words found inside the string. If format of 2 is specified, then the function will return an associated array where the position of the word is the key and the word itself is the value. For the purpose of this function, 'word' is defined as a locale dependent string containing alphabetic characters, which also may contain, but not start with "'" and "-" characters.
  17956. //
  17957. // version: 1103.1210
  17958. // discuss at: http://phpjs.org/functions/str_word_count
  17959. // + original by: Ole Vrijenhoek
  17960. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  17961. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  17962. // + input by: Bug?
  17963. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  17964. // + improved by: Brett Zamir (http://brett-zamir.me)
  17965. // - depends on: ctype_alpha
  17966. // * example 1: \php.str_word_count("Hello fri3nd, you're\r\n looking good today!", 1);
  17967. // * returns 1: ['Hello', 'fri', 'nd', "you're", 'looking', 'good', 'today']
  17968. // * example 2: \php.str_word_count("Hello fri3nd, you're\r\n looking good today!", 2);
  17969. // * returns 2: {0: 'Hello', 6: 'fri', 10: 'nd', 14: "you're", 29: 'looking', 46: 'good', 51: 'today'}
  17970. // * example 3: \php.str_word_count("Hello fri3nd, you're\r\n looking good today!", 1, '\u00e0\u00e1\u00e3\u00e73');
  17971. // * returns 3: ['Hello', 'fri3nd', 'youre', 'looking', 'good', 'today']
  17972. var len = str.length,
  17973. cl = charlist && charlist.length,
  17974. chr = '',
  17975. tmpStr = '',
  17976. i = 0,
  17977. c = '',
  17978. wArr = [],
  17979. wC = 0,
  17980. assoc = {},
  17981. aC = 0,
  17982. reg = '',
  17983. match = false;
  17984. // BEGIN STATIC
  17985. var _preg_quote = function (str) {
  17986. return (str + '').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!<>\|\:])/g, '\\$1');
  17987. },
  17988. _getWholeChar = function (str, i) { // Use for rare cases of non-BMP characters
  17989. var code = str.charCodeAt(i);
  17990. if (code < 0xD800 || code > 0xDFFF) {
  17991. return str.charAt(i);
  17992. }
  17993. if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
  17994. if (str.length <= (i + 1)) {
  17995. throw 'High surrogate without following low surrogate';
  17996. }
  17997. var next = str.charCodeAt(i + 1);
  17998. if (0xDC00 > next || next > 0xDFFF) {
  17999. throw 'High surrogate without following low surrogate';
  18000. }
  18001. return str.charAt(i) + str.charAt(i + 1);
  18002. }
  18003. // Low surrogate (0xDC00 <= code && code <= 0xDFFF)
  18004. if (i === 0) {
  18005. throw 'Low surrogate without preceding high surrogate';
  18006. }
  18007. var prev = str.charCodeAt(i - 1);
  18008. if (0xD800 > prev || prev > 0xDBFF) { // (could change last hex to 0xDB7F to treat high private surrogates as single characters)
  18009. throw 'Low surrogate without preceding high surrogate';
  18010. }
  18011. return false; // We can pass over low surrogates now as the second component in a pair which we have already processed
  18012. };
  18013. // END STATIC
  18014. if (cl) {
  18015. reg = '^(' + _preg_quote(_getWholeChar(charlist, 0));
  18016. for (i = 1; i < cl; i++) {
  18017. if ((chr = _getWholeChar(charlist, i)) === false) {
  18018. continue;
  18019. }
  18020. reg += '|' + _preg_quote(chr);
  18021. }
  18022. reg += ')$';
  18023. reg = new RegExp(reg);
  18024. }
  18025. for (i = 0; i < len; i++) {
  18026. if ((c = _getWholeChar(str, i)) === false) {
  18027. continue;
  18028. }
  18029. match = this.ctype_alpha(c) || (reg && c.search(reg) !== -1) || ((i !== 0 && i !== len - 1) && c === '-') || // No hyphen at beginning or end unless allowed in charlist (or locale)
  18030. (i !== 0 && c === "'"); // No apostrophe at beginning unless allowed in charlist (or locale)
  18031. if (match) {
  18032. if (tmpStr === '' && format === 2) {
  18033. aC = i;
  18034. }
  18035. tmpStr = tmpStr + c;
  18036. }
  18037. if (i === len - 1 || !match && tmpStr !== '') {
  18038. if (format !== 2) {
  18039. wArr[wArr.length] = tmpStr;
  18040. } else {
  18041. assoc[aC] = tmpStr;
  18042. }
  18043. tmpStr = '';
  18044. wC++;
  18045. }
  18046. }
  18047. if (!format) {
  18048. return wC;
  18049. } else if (format === 1) {
  18050. return wArr;
  18051. } else if (format === 2) {
  18052. return assoc;
  18053. }
  18054. throw 'You have supplied an incorrect format';
  18055. };
  18056. php.strcasecmp = function (f_string1, f_string2) {
  18057. // Binary safe case-insensitive string comparison
  18058. //
  18059. // version: 1103.1210
  18060. // discuss at: http://phpjs.org/functions/strcasecmp
  18061. // + original by: Martijn Wieringa
  18062. // + bugfixed by: Onno Marsman
  18063. // * example 1: \php.strcasecmp('Hello', 'hello');
  18064. // * returns 1: 0
  18065. var string1 = (f_string1 + '').toLowerCase();
  18066. var string2 = (f_string2 + '').toLowerCase();
  18067. if (string1 > string2) {
  18068. return 1;
  18069. } else if (string1 == string2) {
  18070. return 0;
  18071. }
  18072. return -1;
  18073. };
  18074. php.strcmp = function (str1, str2) {
  18075. // Binary safe string comparison
  18076. //
  18077. // version: 1103.1210
  18078. // discuss at: http://phpjs.org/functions/strcmp
  18079. // + original by: Waldo Malqui Silva
  18080. // + input by: Steve Hilder
  18081. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18082. // + revised by: gorthaur
  18083. // * example 1: \php.strcmp( 'waldo', 'owald' );
  18084. // * returns 1: 1
  18085. // * example 2: \php.strcmp( 'owald', 'waldo' );
  18086. // * returns 2: -1
  18087. return ((str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1));
  18088. };
  18089. php.strcspn = function (str, mask, start, length) {
  18090. // Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars)
  18091. //
  18092. // version: 1103.1210
  18093. // discuss at: http://phpjs.org/functions/strcspn
  18094. // + original by: Brett Zamir (http://brett-zamir.me)
  18095. // * example 1: \php.strcspn('abcdefg123', '1234567890');
  18096. // * returns 1: 7
  18097. // * example 2: \php.strcspn('123abc', '1234567890');
  18098. // * returns 2: 3
  18099. start = start ? start : 0;
  18100. var count = (length && ((start + length) < str.length)) ? start + length : str.length;
  18101. strct: for (var i = start, lgth = 0; i < count; i++) {
  18102. for (var j = 0; j < mask.length; j++) {
  18103. if (str.charAt(i).indexOf(mask[j]) !== -1) {
  18104. continue strct;
  18105. }
  18106. }++lgth;
  18107. }
  18108. return lgth;
  18109. };
  18110. php.strip_tags = function (input, allowed) {
  18111. // Strips HTML and PHP tags from a string
  18112. //
  18113. // version: 1103.1210
  18114. // discuss at: http://phpjs.org/functions/strip_tags
  18115. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18116. // + improved by: Luke Godfrey
  18117. // + input by: Pul
  18118. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18119. // + bugfixed by: Onno Marsman
  18120. // + input by: Alex
  18121. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18122. // + input by: Marc Palau
  18123. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18124. // + input by: Brett Zamir (http://brett-zamir.me)
  18125. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18126. // + bugfixed by: Eric Nagel
  18127. // + input by: Bobby Drake
  18128. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18129. // + bugfixed by: Tomasz Wesolowski
  18130. // + input by: Evertjan Garretsen
  18131. // + revised by: Rafał Kukawski (http://blog.kukawski.pl/)
  18132. // * example 1: \php.strip_tags('<p>Kevin</p> <br /><b>van</b> <i>Zonneveld</i>', '<i><b>');
  18133. // * returns 1: 'Kevin <b>van</b> <i>Zonneveld</i>'
  18134. // * example 2: \php.strip_tags('<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>', '<p>');
  18135. // * returns 2: '<p>Kevin van Zonneveld</p>'
  18136. // * example 3: \php.strip_tags("<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>", "<a>");
  18137. // * returns 3: '<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>'
  18138. // * example 4: \php.strip_tags('1 < 5 5 > 1');
  18139. // * returns 4: '1 < 5 5 > 1'
  18140. // * example 5: \php.strip_tags('1 <br/> 1');
  18141. // * returns 5: '1 1'
  18142. // * example 6: \php.strip_tags('1 <br/> 1', '<br>');
  18143. // * returns 6: '1 1'
  18144. // * example 7: \php.strip_tags('1 <br/> 1', '<br><br/>');
  18145. // * returns 7: '1 <br/> 1'
  18146. allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
  18147. var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
  18148. commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
  18149. return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
  18150. return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
  18151. });
  18152. };
  18153. php.stripos = function (f_haystack, f_needle, f_offset) {
  18154. // Finds position of first occurrence of a string within another, case insensitive
  18155. //
  18156. // version: 1103.1210
  18157. // discuss at: http://phpjs.org/functions/stripos
  18158. // + original by: Martijn Wieringa
  18159. // + revised by: Onno Marsman
  18160. // * example 1: \php.stripos('ABC', 'a');
  18161. // * returns 1: 0
  18162. var haystack = (f_haystack + '').toLowerCase();
  18163. var needle = (f_needle + '').toLowerCase();
  18164. var index = 0;
  18165. if ((index = haystack.indexOf(needle, f_offset)) !== -1) {
  18166. return index;
  18167. }
  18168. return false;
  18169. };
  18170. php.stripslashes = function (str) {
  18171. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18172. // + improved by: Ates Goral (http://magnetiq.com)
  18173. // + fixed by: Mick@el
  18174. // + improved by: marrtins
  18175. // + bugfixed by: Onno Marsman
  18176. // + improved by: rezna
  18177. // + input by: Rick Waldron
  18178. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  18179. // + input by: Brant Messenger (http://www.brantmessenger.com/)
  18180. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  18181. // * example 1: \php.stripslashes('Kevin\'s code');
  18182. // * returns 1: "Kevin's code"
  18183. // * example 2: \php.stripslashes('Kevin\\\'s code');
  18184. // * returns 2: "Kevin\'s code"
  18185. return (str + '').replace(/\\(.?)/g, function (s, n1) {
  18186. switch (n1) {
  18187. case '\\':
  18188. return '\\';
  18189. case '0':
  18190. return '\u0000';
  18191. case '':
  18192. return '';
  18193. default:
  18194. return n1;
  18195. }
  18196. });
  18197. };
  18198. php.stristr = function (haystack, needle, bool) {
  18199. // Finds first occurrence of a string within another, case insensitive
  18200. //
  18201. // version: 1103.1210
  18202. // discuss at: http://phpjs.org/functions/stristr
  18203. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18204. // + bugfxied by: Onno Marsman
  18205. // * example 1: \php.stristr('Kevin van Zonneveld', 'Van');
  18206. // * returns 1: 'van Zonneveld'
  18207. // * example 2: \php.stristr('Kevin van Zonneveld', 'VAN', true);
  18208. // * returns 2: 'Kevin '
  18209. var pos = 0;
  18210. haystack += '';
  18211. pos = haystack.toLowerCase().indexOf((needle + '').toLowerCase());
  18212. if (pos == -1) {
  18213. return false;
  18214. } else {
  18215. if (bool) {
  18216. return haystack.substr(0, pos);
  18217. } else {
  18218. return haystack.slice(pos);
  18219. }
  18220. }
  18221. };
  18222. php.strlen = function (string) {
  18223. // Get string length
  18224. //
  18225. // version: 1103.1210
  18226. // discuss at: http://phpjs.org/functions/strlen
  18227. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18228. // + improved by: Sakimori
  18229. // + input by: Kirk Strobeck
  18230. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18231. // + bugfixed by: Onno Marsman
  18232. // + revised by: Brett Zamir (http://brett-zamir.me)
  18233. // % note 1: May look like overkill, but in order to be truly faithful to handling all Unicode
  18234. // % note 1: characters and to this function in PHP which does not count the number of bytes
  18235. // % note 1: but counts the number of characters, something like this is really necessary.
  18236. // * example 1: \php.strlen('Kevin van Zonneveld');
  18237. // * returns 1: 19
  18238. // * example 2: \php.strlen('A\ud87e\udc04Z');
  18239. // * returns 2: 3
  18240. var str = string + '';
  18241. var i = 0,
  18242. chr = '',
  18243. lgth = 0;
  18244. if (!this.php_js || !this.php_js.ini || !this.php_js.ini['unicode.semantics'] || this.php_js.ini['unicode.semantics'].local_value.toLowerCase() !== 'on') {
  18245. return string.length;
  18246. }
  18247. var getWholeChar = function (str, i) {
  18248. var code = str.charCodeAt(i);
  18249. var next = '',
  18250. prev = '';
  18251. if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
  18252. if (str.length <= (i + 1)) {
  18253. throw 'High surrogate without following low surrogate';
  18254. }
  18255. next = str.charCodeAt(i + 1);
  18256. if (0xDC00 > next || next > 0xDFFF) {
  18257. throw 'High surrogate without following low surrogate';
  18258. }
  18259. return str.charAt(i) + str.charAt(i + 1);
  18260. } else if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
  18261. if (i === 0) {
  18262. throw 'Low surrogate without preceding high surrogate';
  18263. }
  18264. prev = str.charCodeAt(i - 1);
  18265. if (0xD800 > prev || prev > 0xDBFF) { //(could change last hex to 0xDB7F to treat high private surrogates as single characters)
  18266. throw 'Low surrogate without preceding high surrogate';
  18267. }
  18268. return false; // We can pass over low surrogates now as the second component in a pair which we have already processed
  18269. }
  18270. return str.charAt(i);
  18271. };
  18272. for (i = 0, lgth = 0; i < str.length; i++) {
  18273. if ((chr = getWholeChar(str, i)) === false) {
  18274. continue;
  18275. } // Adapt this line at the top of any loop, passing in the whole string and the current iteration and returning a variable to represent the individual character; purpose is to treat the first part of a surrogate pair as the whole character and then ignore the second part
  18276. lgth++;
  18277. }
  18278. return lgth;
  18279. };
  18280. php.strnatcasecmp = function (str1, str2) {
  18281. // Returns the result of case-insensitive string comparison using 'natural' algorithm
  18282. //
  18283. // version: 1103.1210
  18284. // discuss at: http://phpjs.org/functions/strnatcasecmp
  18285. // + original by: Martin Pool
  18286. // + reimplemented by: Pierre-Luc Paour
  18287. // + reimplemented by: Kristof Coomans (SCK-CEN (Belgian Nucleair Research Centre))
  18288. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  18289. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18290. // + input by: Devan Penner-Woelk
  18291. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18292. // * example 1: \php.strnatcasecmp(10, 1);
  18293. // * returns 1: 1
  18294. // * example 1: \php.strnatcasecmp('1', '10');
  18295. // * returns 1: -1
  18296. var a = (str1 + '').toLowerCase();
  18297. var b = (str2 + '').toLowerCase();
  18298. var isWhitespaceChar = function (a) {
  18299. return a.charCodeAt(0) <= 32;
  18300. };
  18301. var isDigitChar = function (a) {
  18302. var charCode = a.charCodeAt(0);
  18303. return (charCode >= 48 && charCode <= 57);
  18304. };
  18305. var compareRight = function (a, b) {
  18306. var bias = 0;
  18307. var ia = 0;
  18308. var ib = 0;
  18309. var ca;
  18310. var cb;
  18311. // The longest run of digits wins. That aside, the greatest
  18312. // value wins, but we can't know that it will until we've scanned
  18313. // both numbers to know that they have the same magnitude, so we
  18314. // remember it in BIAS.
  18315. for (var cnt = 0; true; ia++, ib++) {
  18316. ca = a.charAt(ia);
  18317. cb = b.charAt(ib);
  18318. if (!isDigitChar(ca) && !isDigitChar(cb)) {
  18319. return bias;
  18320. } else if (!isDigitChar(ca)) {
  18321. return -1;
  18322. } else if (!isDigitChar(cb)) {
  18323. return 1;
  18324. } else if (ca < cb) {
  18325. if (bias === 0) {
  18326. bias = -1;
  18327. }
  18328. } else if (ca > cb) {
  18329. if (bias === 0) {
  18330. bias = 1;
  18331. }
  18332. } else if (ca === '0' && cb === '0') {
  18333. return bias;
  18334. }
  18335. }
  18336. };
  18337. var ia = 0,
  18338. ib = 0;
  18339. var nza = 0,
  18340. nzb = 0;
  18341. var ca, cb;
  18342. var result;
  18343. while (true) {
  18344. // only count the number of zeroes leading the last number compared
  18345. nza = nzb = 0;
  18346. ca = a.charAt(ia);
  18347. cb = b.charAt(ib);
  18348. // skip over leading spaces or zeros
  18349. while (isWhitespaceChar(ca) || ca === '0') {
  18350. if (ca === '0') {
  18351. nza++;
  18352. } else {
  18353. // only count consecutive zeroes
  18354. nza = 0;
  18355. }
  18356. ca = a.charAt(++ia);
  18357. }
  18358. while (isWhitespaceChar(cb) || cb === '0') {
  18359. if (cb === '0') {
  18360. nzb++;
  18361. } else {
  18362. // only count consecutive zeroes
  18363. nzb = 0;
  18364. }
  18365. cb = b.charAt(++ib);
  18366. }
  18367. // process run of digits
  18368. if (isDigitChar(ca) && isDigitChar(cb)) {
  18369. if ((result = compareRight(a.substring(ia), b.substring(ib))) !== 0) {
  18370. return result;
  18371. }
  18372. }
  18373. if (ca === '0' && cb === '0') {
  18374. // The strings compare the same. Perhaps the caller
  18375. // will want to call strcmp to break the tie.
  18376. return nza - nzb;
  18377. }
  18378. if (ca < cb) {
  18379. return -1;
  18380. } else if (ca > cb) {
  18381. return +1;
  18382. }
  18383. ++ia;
  18384. ++ib;
  18385. }
  18386. };
  18387. php.strnatcmp = function (f_string1, f_string2, f_version) {
  18388. // Returns the result of string comparison using 'natural' algorithm
  18389. //
  18390. // version: 1103.1210
  18391. // discuss at: http://phpjs.org/functions/strnatcmp
  18392. // + original by: Martijn Wieringa
  18393. // + namespaced by: Michael White (http://getsprink.com)
  18394. // + tweaked by: Jack
  18395. // + bugfixed by: Onno Marsman
  18396. // - depends on: strcmp
  18397. // % note: Added f_version argument against code guidelines, because it's so neat
  18398. // * example 1: \php.strnatcmp('Price 12.9', 'Price 12.15');
  18399. // * returns 1: 1
  18400. // * example 2: \php.strnatcmp('Price 12.09', 'Price 12.15');
  18401. // * returns 2: -1
  18402. // * example 3: \php.strnatcmp('Price 12.90', 'Price 12.15');
  18403. // * returns 3: 1
  18404. // * example 4: \php.strnatcmp('Version 12.9', 'Version 12.15', true);
  18405. // * returns 4: -6
  18406. // * example 5: \php.strnatcmp('Version 12.15', 'Version 12.9', true);
  18407. // * returns 5: 6
  18408. var i = 0;
  18409. if (f_version == undefined) {
  18410. f_version = false;
  18411. }
  18412. var __strnatcmp_split = function (f_string) {
  18413. var result = [];
  18414. var buffer = '';
  18415. var chr = '';
  18416. var i = 0,
  18417. f_stringl = 0;
  18418. var text = true;
  18419. f_stringl = f_string.length;
  18420. for (i = 0; i < f_stringl; i++) {
  18421. chr = f_string.substring(i, i + 1);
  18422. if (chr.match(/\d/)) {
  18423. if (text) {
  18424. if (buffer.length > 0) {
  18425. result[result.length] = buffer;
  18426. buffer = '';
  18427. }
  18428. text = false;
  18429. }
  18430. buffer += chr;
  18431. } else if ((text == false) && (chr == '.') && (i < (f_string.length - 1)) && (f_string.substring(i + 1, i + 2).match(/\d/))) {
  18432. result[result.length] = buffer;
  18433. buffer = '';
  18434. } else {
  18435. if (text == false) {
  18436. if (buffer.length > 0) {
  18437. result[result.length] = parseInt(buffer, 10);
  18438. buffer = '';
  18439. }
  18440. text = true;
  18441. }
  18442. buffer += chr;
  18443. }
  18444. }
  18445. if (buffer.length > 0) {
  18446. if (text) {
  18447. result[result.length] = buffer;
  18448. } else {
  18449. result[result.length] = parseInt(buffer, 10);
  18450. }
  18451. }
  18452. return result;
  18453. };
  18454. var array1 = __strnatcmp_split(f_string1 + '');
  18455. var array2 = __strnatcmp_split(f_string2 + '');
  18456. var len = array1.length;
  18457. var text = true;
  18458. var result = -1;
  18459. var r = 0;
  18460. if (len > array2.length) {
  18461. len = array2.length;
  18462. result = 1;
  18463. }
  18464. for (i = 0; i < len; i++) {
  18465. if (isNaN(array1[i])) {
  18466. if (isNaN(array2[i])) {
  18467. text = true;
  18468. if ((r = this.strcmp(array1[i], array2[i])) != 0) {
  18469. return r;
  18470. }
  18471. } else if (text) {
  18472. return 1;
  18473. } else {
  18474. return -1;
  18475. }
  18476. } else if (isNaN(array2[i])) {
  18477. if (text) {
  18478. return -1;
  18479. } else {
  18480. return 1;
  18481. }
  18482. } else {
  18483. if (text || f_version) {
  18484. if ((r = (array1[i] - array2[i])) != 0) {
  18485. return r;
  18486. }
  18487. } else {
  18488. if ((r = this.strcmp(array1[i].toString(), array2[i].toString())) != 0) {
  18489. return r;
  18490. }
  18491. }
  18492. text = false;
  18493. }
  18494. }
  18495. return result;
  18496. };
  18497. php.strncasecmp = function (argStr1, argStr2, len) {
  18498. // Binary safe string comparison
  18499. //
  18500. // version: 1103.1210
  18501. // discuss at: http://phpjs.org/functions/strncasecmp
  18502. // + original by: Saulo Vallory
  18503. // + input by: Nate
  18504. // + bugfixed by: Onno Marsman
  18505. // % note: Returns < 0 if str1 is less than str2 ; > 0 if str1 is greater than str2 , and 0 if they are equal.
  18506. // * example 1: \php.strncasecmp('Price 12.9', 'Price 12.15', 2);
  18507. // * returns 1: 0
  18508. // * example 2: \php.strncasecmp('Price 12.09', 'Price 12.15', 10);
  18509. // * returns 2: -1
  18510. // * example 3: \php.strncasecmp('Price 12.90', 'Price 12.15', 30);
  18511. // * returns 3: 8
  18512. // * example 4: \php.strncasecmp('Version 12.9', 'Version 12.15', 20);
  18513. // * returns 4: 8
  18514. // * example 5: \php.strncasecmp('Version 12.15', 'Version 12.9', 20);
  18515. // * returns 5: -8
  18516. var diff, i = 0;
  18517. var str1 = (argStr1 + '').toLowerCase().substr(0, len);
  18518. var str2 = (argStr2 + '').toLowerCase().substr(0, len);
  18519. if (str1.length !== str2.length) {
  18520. if (str1.length < str2.length) {
  18521. len = str1.length;
  18522. if (str2.substr(0, str1.length) == str1) {
  18523. return str1.length - str2.length; // return the difference of chars
  18524. }
  18525. } else {
  18526. len = str2.length;
  18527. // str1 is longer than str2
  18528. if (str1.substr(0, str2.length) == str2) {
  18529. return str1.length - str2.length; // return the difference of chars
  18530. }
  18531. }
  18532. } else {
  18533. // Avoids trying to get a char that does not exist
  18534. len = str1.length;
  18535. }
  18536. for (diff = 0, i = 0; i < len; i++) {
  18537. diff = str1.charCodeAt(i) - str2.charCodeAt(i);
  18538. if (diff !== 0) {
  18539. return diff;
  18540. }
  18541. }
  18542. return 0;
  18543. };
  18544. php.strncmp = function (str1, str2, lgth) {
  18545. // Binary safe string comparison
  18546. //
  18547. // version: 1103.1210
  18548. // discuss at: http://phpjs.org/functions/strncmp
  18549. // + original by: Waldo Malqui Silva
  18550. // + input by: Steve Hilder
  18551. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18552. // + revised by: gorthaur
  18553. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  18554. // * example 1: \php.strncmp('aaa', 'aab', 2);
  18555. // * returns 1: 0
  18556. // * example 2: \php.strncmp('aaa', 'aab', 3 );
  18557. // * returns 2: -1
  18558. var s1 = (str1 + '').substr(0, lgth);
  18559. var s2 = (str2 + '').substr(0, lgth);
  18560. return ((s1 == s2) ? 0 : ((s1 > s2) ? 1 : -1));
  18561. };
  18562. php.strpos = function (haystack, needle, offset) {
  18563. // Finds position of first occurrence of a string within another
  18564. //
  18565. // version: 1103.1210
  18566. // discuss at: http://phpjs.org/functions/strpos
  18567. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18568. // + improved by: Onno Marsman
  18569. // + bugfixed by: Daniel Esteban
  18570. // + improved by: Brett Zamir (http://brett-zamir.me)
  18571. // * example 1: \php.strpos('Kevin van Zonneveld', 'e', 5);
  18572. // * returns 1: 14
  18573. var i = (haystack + '').indexOf(needle, (offset || 0));
  18574. return i === -1 ? false : i;
  18575. };
  18576. php.strtok = function (str, tokens) {
  18577. // Tokenize a string
  18578. //
  18579. // version: 1103.1210
  18580. // discuss at: http://phpjs.org/functions/strtok
  18581. // + original by: Brett Zamir (http://brett-zamir.me)
  18582. // % note 1: Use tab and newline as tokenizing characters as well
  18583. // * example 1: $string = "\t\t\t\nThis is\tan example\nstring\n";
  18584. // * example 1: $tok = strtok($string, " \n\t");
  18585. // * example 1: $b = '';
  18586. // * example 1: \php.while ($tok !== false) {$b += "Word="+$tok+"\n"; $tok = strtok(" \n\t");}
  18587. // * example 1: $b
  18588. // * returns 1: "Word=This\nWord=is\nWord=an\nWord=example\nWord=string\n"
  18589. // BEGIN REDUNDANT
  18590. this.php_js = this.php_js || {};
  18591. // END REDUNDANT
  18592. if (tokens === undefined) {
  18593. tokens = str;
  18594. str = this.php_js.strtokleftOver;
  18595. }
  18596. if (str.length === 0) {
  18597. return false;
  18598. }
  18599. if (tokens.indexOf(str.charAt(0)) !== -1) {
  18600. return this.strtok(str.substr(1), tokens);
  18601. }
  18602. for (var i = 0; i < str.length; i++) {
  18603. if (tokens.indexOf(str.charAt(i)) !== -1) {
  18604. break;
  18605. }
  18606. }
  18607. this.php_js.strtokleftOver = str.substr(i + 1);
  18608. return str.substring(0, i);
  18609. };
  18610. php.strtotime = function (str, now) {
  18611. // Convert string representation of date and time to a timestamp
  18612. //
  18613. // version: 1103.1210
  18614. // discuss at: http://phpjs.org/functions/strtotime
  18615. // + original by: Caio Ariede (http://caioariede.com)
  18616. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18617. // + input by: David
  18618. // + improved by: Caio Ariede (http://caioariede.com)
  18619. // + improved by: Brett Zamir (http://brett-zamir.me)
  18620. // + bugfixed by: Wagner B. Soares
  18621. // + bugfixed by: Artur Tchernychev
  18622. // % note 1: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
  18623. // * example 1: \php.strtotime('+1 day', 1129633200);
  18624. // * returns 1: 1129719600
  18625. // * example 2: \php.strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
  18626. // * returns 2: 1130425202
  18627. // * example 3: \php.strtotime('last month', 1129633200);
  18628. // * returns 3: 1127041200
  18629. // * example 4: \php.strtotime('2009-05-04 08:30:00');
  18630. // * returns 4: 1241418600
  18631. var i, match, s, strTmp = '',
  18632. parse = '';
  18633. strTmp = str;
  18634. strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
  18635. strTmp = strTmp.replace(/[\t\r\n]/g, ''); // unecessary chars
  18636. if (strTmp == 'now') {
  18637. return (new Date()).getTime() / 1000; // Return seconds, not milli-seconds
  18638. } else if (!isNaN(parse = Date.parse(strTmp))) {
  18639. return (parse / 1000);
  18640. } else if (now) {
  18641. now = new Date(now * 1000); // Accept PHP-style seconds
  18642. } else {
  18643. now = new Date();
  18644. }
  18645. strTmp = strTmp.toLowerCase();
  18646. var __is = {
  18647. day: {
  18648. 'sun': 0,
  18649. 'mon': 1,
  18650. 'tue': 2,
  18651. 'wed': 3,
  18652. 'thu': 4,
  18653. 'fri': 5,
  18654. 'sat': 6
  18655. },
  18656. mon: {
  18657. 'jan': 0,
  18658. 'feb': 1,
  18659. 'mar': 2,
  18660. 'apr': 3,
  18661. 'may': 4,
  18662. 'jun': 5,
  18663. 'jul': 6,
  18664. 'aug': 7,
  18665. 'sep': 8,
  18666. 'oct': 9,
  18667. 'nov': 10,
  18668. 'dec': 11
  18669. }
  18670. };
  18671. var process = function (m) {
  18672. var ago = (m[2] && m[2] == 'ago');
  18673. var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);
  18674. switch (m[0]) {
  18675. case 'last':
  18676. case 'next':
  18677. switch (m[1].substring(0, 3)) {
  18678. case 'yea':
  18679. now.setFullYear(now.getFullYear() + num);
  18680. break;
  18681. case 'mon':
  18682. now.setMonth(now.getMonth() + num);
  18683. break;
  18684. case 'wee':
  18685. now.setDate(now.getDate() + (num * 7));
  18686. break;
  18687. case 'day':
  18688. now.setDate(now.getDate() + num);
  18689. break;
  18690. case 'hou':
  18691. now.setHours(now.getHours() + num);
  18692. break;
  18693. case 'min':
  18694. now.setMinutes(now.getMinutes() + num);
  18695. break;
  18696. case 'sec':
  18697. now.setSeconds(now.getSeconds() + num);
  18698. break;
  18699. default:
  18700. var day;
  18701. if (typeof(day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
  18702. var diff = day - now.getDay();
  18703. if (diff == 0) {
  18704. diff = 7 * num;
  18705. } else if (diff > 0) {
  18706. if (m[0] == 'last') {
  18707. diff -= 7;
  18708. }
  18709. } else {
  18710. if (m[0] == 'next') {
  18711. diff += 7;
  18712. }
  18713. }
  18714. now.setDate(now.getDate() + diff);
  18715. }
  18716. }
  18717. break;
  18718. default:
  18719. if (/\d+/.test(m[0])) {
  18720. num *= parseInt(m[0], 10);
  18721. switch (m[1].substring(0, 3)) {
  18722. case 'yea':
  18723. now.setFullYear(now.getFullYear() + num);
  18724. break;
  18725. case 'mon':
  18726. now.setMonth(now.getMonth() + num);
  18727. break;
  18728. case 'wee':
  18729. now.setDate(now.getDate() + (num * 7));
  18730. break;
  18731. case 'day':
  18732. now.setDate(now.getDate() + num);
  18733. break;
  18734. case 'hou':
  18735. now.setHours(now.getHours() + num);
  18736. break;
  18737. case 'min':
  18738. now.setMinutes(now.getMinutes() + num);
  18739. break;
  18740. case 'sec':
  18741. now.setSeconds(now.getSeconds() + num);
  18742. break;
  18743. }
  18744. } else {
  18745. return false;
  18746. }
  18747. break;
  18748. }
  18749. return true;
  18750. };
  18751. match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);
  18752. if (match != null) {
  18753. if (!match[2]) {
  18754. match[2] = '00:00:00';
  18755. } else if (!match[3]) {
  18756. match[2] += ':00';
  18757. }
  18758. s = match[1].split(/-/g);
  18759. for (i in __is.mon) {
  18760. if (__is.mon[i] == s[1] - 1) {
  18761. s[1] = i;
  18762. }
  18763. }
  18764. s[0] = parseInt(s[0], 10);
  18765. s[0] = (s[0] >= 0 && s[0] <= 69) ? '20' + (s[0] < 10 ? '0' + s[0] : s[0] + '') : (s[0] >= 70 && s[0] <= 99) ? '19' + s[0] : s[0] + '';
  18766. return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2]) + (match[4] ? match[4] / 1000 : ''), 10);
  18767. }
  18768. var regex = '([+-]?\\d+\\s' + '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?' + '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday' + '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)' + '|(last|next)\\s' + '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?' + '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday' + '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))' + '(\\sago)?';
  18769. match = strTmp.match(new RegExp(regex, 'gi')); // Brett: seems should be case insensitive per docs, so added 'i'
  18770. if (match == null) {
  18771. return false;
  18772. }
  18773. for (i = 0; i < match.length; i++) {
  18774. if (!process(match[i].split(' '))) {
  18775. return false;
  18776. }
  18777. }
  18778. return (now.getTime() / 1000);
  18779. };
  18780. php.strrpos = function (haystack, needle, offset) {
  18781. // Finds position of last occurrence of a string within another string
  18782. //
  18783. // version: 1103.1210
  18784. // discuss at: http://phpjs.org/functions/strrpos
  18785. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18786. // + bugfixed by: Onno Marsman
  18787. // + input by: saulius
  18788. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  18789. // * example 1: strrpos('Kevin van Zonneveld', 'e');
  18790. // * returns 1: 16
  18791. // * example 2: strrpos('somepage.com', '.', false);
  18792. // * returns 2: 8
  18793. // * example 3: strrpos('baa', 'a', 3);
  18794. // * returns 3: false
  18795. // * example 4: strrpos('baa', 'a', 2);
  18796. // * returns 4: 2
  18797. var i = -1;
  18798. if (offset) {
  18799. i = (haystack + '').slice(offset).lastIndexOf(needle); // strrpos' offset indicates starting point of range till end,
  18800. // while lastIndexOf's optional 2nd argument indicates ending point of range from the beginning
  18801. if (i !== -1) {
  18802. i += offset;
  18803. }
  18804. } else {
  18805. i = (haystack + '').lastIndexOf(needle);
  18806. }
  18807. return i >= 0 ? i : false;
  18808. };
  18809. php.strtr = function (str, from, to) {
  18810. // Translates characters in str using given translation tables
  18811. //
  18812. // version: 1103.1210
  18813. // discuss at: http://phpjs.org/functions/strtr
  18814. // + original by: Brett Zamir (http://brett-zamir.me)
  18815. // + input by: uestla
  18816. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18817. // + input by: Alan C
  18818. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18819. // + input by: Taras Bogach
  18820. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  18821. // + input by: jpfle
  18822. // + bugfixed by: Brett Zamir (http://brett-zamir.me)
  18823. // - depends on: krsort
  18824. // - depends on: ini_set
  18825. // * example 1: $trans = {'hello' : 'hi', 'hi' : 'hello'};
  18826. // * example 1: \php.strtr('hi all, I said hello', $trans)
  18827. // * returns 1: 'hello all, I said hi'
  18828. // * example 2: \php.strtr('äaabaåccasdeöoo', 'äåö','aao');
  18829. // * returns 2: 'aaabaaccasdeooo'
  18830. // * example 3: \php.strtr('ääääääää', 'ä', 'a');
  18831. // * returns 3: 'aaaaaaaa'
  18832. // * example 4: \php.strtr('http', 'pthxyz','xyzpth');
  18833. // * returns 4: 'zyyx'
  18834. // * example 5: \php.strtr('zyyx', 'pthxyz','xyzpth');
  18835. // * returns 5: 'http'
  18836. // * example 6: \php.strtr('aa', {'a':1,'aa':2});
  18837. // * returns 6: '2'
  18838. var fr = '',
  18839. i = 0,
  18840. j = 0,
  18841. lenStr = 0,
  18842. lenFrom = 0,
  18843. tmpStrictForIn = false,
  18844. fromTypeStr = '',
  18845. toTypeStr = '',
  18846. istr = '';
  18847. var tmpFrom = [];
  18848. var tmpTo = [];
  18849. var ret = '';
  18850. var match = false;
  18851. // Received replace_pairs?
  18852. // Convert to normal from->to chars
  18853. if (typeof from === 'object') {
  18854. tmpStrictForIn = this.ini_set('phpjs.strictForIn', false); // Not thread-safe; temporarily set to true
  18855. from = this.krsort(from);
  18856. this.ini_set('phpjs.strictForIn', tmpStrictForIn);
  18857. for (fr in from) {
  18858. if (from.hasOwnProperty(fr)) {
  18859. tmpFrom.push(fr);
  18860. tmpTo.push(from[fr]);
  18861. }
  18862. }
  18863. from = tmpFrom;
  18864. to = tmpTo;
  18865. }
  18866. // Walk through subject and replace chars when needed
  18867. lenStr = str.length;
  18868. lenFrom = from.length;
  18869. fromTypeStr = typeof from === 'string';
  18870. toTypeStr = typeof to === 'string';
  18871. for (i = 0; i < lenStr; i++) {
  18872. match = false;
  18873. if (fromTypeStr) {
  18874. istr = str.charAt(i);
  18875. for (j = 0; j < lenFrom; j++) {
  18876. if (istr == from.charAt(j)) {
  18877. match = true;
  18878. break;
  18879. }
  18880. }
  18881. } else {
  18882. for (j = 0; j < lenFrom; j++) {
  18883. if (str.substr(i, from[j].length) == from[j]) {
  18884. match = true;
  18885. // Fast forward
  18886. i = (i + from[j].length) - 1;
  18887. break;
  18888. }
  18889. }
  18890. }
  18891. if (match) {
  18892. ret += toTypeStr ? to.charAt(j) : to[j];
  18893. } else {
  18894. ret += str.charAt(i);
  18895. }
  18896. }
  18897. return ret;
  18898. };
  18899. php.substr_compare = function (main_str, str, offset, length, case_insensitivity) {
  18900. // Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters
  18901. //
  18902. // version: 1103.1210
  18903. // discuss at: http://phpjs.org/functions/substr_compare
  18904. // + original by: Brett Zamir (http://brett-zamir.me)
  18905. // + derived from: strcasecmp, strcmp
  18906. // * example 1: \php.substr_compare("abcde", "bc", 1, 2);
  18907. // * returns 1: 0
  18908. if (!offset && offset !== 0) {
  18909. throw 'Missing offset for substr_compare()';
  18910. }
  18911. if (offset < 0) {
  18912. offset = main_str.length + offset;
  18913. }
  18914. if (length && length > (main_str.length - offset)) {
  18915. return false;
  18916. }
  18917. length = length || main_str.length - offset;
  18918. main_str = main_str.substr(offset, length);
  18919. str = str.substr(0, length); // Should only compare up to the desired length
  18920. if (case_insensitivity) { // Works as strcasecmp
  18921. main_str = (main_str + '').toLowerCase();
  18922. str = (str + '').toLowerCase();
  18923. if (main_str == str) {
  18924. return 0;
  18925. }
  18926. return (main_str > str) ? 1 : -1;
  18927. }
  18928. // Works as strcmp
  18929. return ((main_str == str) ? 0 : ((main_str > str) ? 1 : -1));
  18930. };
  18931. php.substr_count = function (haystack, needle, offset, length) {
  18932. // Returns the number of times a substring occurs in the string
  18933. //
  18934. // version: 1103.1210
  18935. // discuss at: http://phpjs.org/functions/substr_count
  18936. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18937. // + bugfixed by: Onno Marsman
  18938. // * example 1: \php.substr_count('Kevin van Zonneveld', 'e');
  18939. // * returns 1: 3
  18940. // * example 2: \php.substr_count('Kevin van Zonneveld', 'K', 1);
  18941. // * returns 2: 0
  18942. // * example 3: \php.substr_count('Kevin van Zonneveld', 'Z', 0, 10);
  18943. // * returns 3: false
  18944. var pos = 0,
  18945. cnt = 0;
  18946. haystack += '';
  18947. needle += '';
  18948. if (isNaN(offset)) {
  18949. offset = 0;
  18950. }
  18951. if (isNaN(length)) {
  18952. length = 0;
  18953. }
  18954. offset--;
  18955. while ((offset = haystack.indexOf(needle, offset + 1)) != -1) {
  18956. if (length > 0 && (offset + needle.length) > length) {
  18957. return false;
  18958. } else {
  18959. cnt++;
  18960. }
  18961. }
  18962. return cnt;
  18963. };
  18964. php.substr_replace = function (str, replace, start, length) {
  18965. // Replaces part of a string with another string
  18966. //
  18967. // version: 1103.1210
  18968. // discuss at: http://phpjs.org/functions/substr_replace
  18969. // + original by: Brett Zamir (http://brett-zamir.me)
  18970. // * example 1: \php.substr_replace('ABCDEFGH:/MNRPQR/', 'bob', 0);
  18971. // * returns 1: 'bob'
  18972. // * example 2: $var = 'ABCDEFGH:/MNRPQR/';
  18973. // * example 2: \php.substr_replace($var, 'bob', 0, $var.length);
  18974. // * returns 2: 'bob'
  18975. // * example 3: \php.substr_replace('ABCDEFGH:/MNRPQR/', 'bob', 0, 0);
  18976. // * returns 3: 'bobABCDEFGH:/MNRPQR/'
  18977. // * example 4: \php.substr_replace('ABCDEFGH:/MNRPQR/', 'bob', 10, -1);
  18978. // * returns 4: 'ABCDEFGH:/bob/'
  18979. // * example 5: \php.substr_replace('ABCDEFGH:/MNRPQR/', 'bob', -7, -1);
  18980. // * returns 5: 'ABCDEFGH:/bob/'
  18981. // * example 6: 'substr_replace('ABCDEFGH:/MNRPQR/', '', 10, -1)'
  18982. // * returns 6: 'ABCDEFGH://'
  18983. if (start < 0) { // start position in str
  18984. start = start + str.length;
  18985. }
  18986. length = length !== undefined ? length : str.length;
  18987. if (length < 0) {
  18988. length = length + str.length - start;
  18989. }
  18990. return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length);
  18991. };
  18992. php.time = function () {
  18993. // Return current UNIX timestamp
  18994. //
  18995. // version: 1103.1210
  18996. // discuss at: http://phpjs.org/functions/time
  18997. // + original by: GeekFG (http://geekfg.blogspot.com)
  18998. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  18999. // + improved by: metjay
  19000. // + improved by: HKM
  19001. // * example 1: \php.timeStamp = time();
  19002. // * results 1: timeStamp > 1000000000 && timeStamp < 2000000000
  19003. return Math.floor(new Date().getTime() / 1000);
  19004. };
  19005. php.trim = function (str, charlist) {
  19006. // Strips whitespace from the beginning and end of a string
  19007. //
  19008. // version: 1103.1210
  19009. // discuss at: http://phpjs.org/functions/trim
  19010. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19011. // + improved by: mdsjack (http://www.mdsjack.bo.it)
  19012. // + improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev)
  19013. // + input by: Erkekjetter
  19014. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19015. // + input by: DxGx
  19016. // + improved by: Steven Levithan (http://blog.stevenlevithan.com)
  19017. // + tweaked by: Jack
  19018. // + bugfixed by: Onno Marsman
  19019. // * example 1: \php.trim(' Kevin van Zonneveld ');
  19020. // * returns 1: 'Kevin van Zonneveld'
  19021. // * example 2: \php.trim('Hello World', 'Hdle');
  19022. // * returns 2: 'o Wor'
  19023. // * example 3: \php.trim(16, 1);
  19024. // * returns 3: 6
  19025. var whitespace, l = 0,
  19026. i = 0;
  19027. str += '';
  19028. if (!charlist) {
  19029. // default list
  19030. whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
  19031. } else {
  19032. // preg_quote custom list
  19033. charlist += '';
  19034. whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
  19035. }
  19036. l = str.length;
  19037. for (i = 0; i < l; i++) {
  19038. if (whitespace.indexOf(str.charAt(i)) === -1) {
  19039. str = str.substring(i);
  19040. break;
  19041. }
  19042. }
  19043. l = str.length;
  19044. for (i = l - 1; i >= 0; i--) {
  19045. if (whitespace.indexOf(str.charAt(i)) === -1) {
  19046. str = str.substring(0, i + 1);
  19047. break;
  19048. }
  19049. }
  19050. return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
  19051. };
  19052. php.uasort = function (inputArr, sorter) {
  19053. // Sort an array with a user-defined comparison function and maintain index association
  19054. //
  19055. // version: 1103.1210
  19056. // discuss at: http://phpjs.org/functions/uasort
  19057. // + original by: Brett Zamir (http://brett-zamir.me)
  19058. // + improved by: Brett Zamir (http://brett-zamir.me)
  19059. // % note 1: This function deviates from PHP in returning a copy of the array instead
  19060. // % note 1: of acting by reference and returning true; this was necessary because
  19061. // % note 1: IE does not allow deleting and re-adding of properties without caching
  19062. // % note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
  19063. // % note 1: get the PHP behavior, but use this only if you are in an environment
  19064. // % note 1: such as Firefox extensions where for-in iteration order is fixed and true
  19065. // % note 1: property deletion is supported. Note that we intend to implement the PHP
  19066. // % note 1: behavior by default if IE ever does allow it; only gives shallow copy since
  19067. // % note 1: is by reference in PHP anyways
  19068. // * example 1: \php.fruits = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  19069. // * example 1: \php.fruits = uasort(fruits, function (a, b) { if (a > b) {return 1;}if (a < b) {return -1;} return 0;});
  19070. // * results 1: fruits == {c: 'apple', b: 'banana', d: 'lemon', a: 'orange'}
  19071. var valArr = [],
  19072. keyArr = [],
  19073. tempKeyVal, tempValue, ret, k = '',
  19074. i = 0,
  19075. strictForIn = false,
  19076. populateArr = {};
  19077. if (typeof sorter === 'string') {
  19078. sorter = this[sorter];
  19079. } else if (sorter instanceof Array) {
  19080. sorter = this[sorter[0]][sorter[1]];
  19081. }
  19082. var sorterNew = function (keyArr, valArr) {
  19083. for (var i = valArr.length - 2; i >= 0; i--) {
  19084. for (var j = 0; j <= i; j++) {
  19085. ret = sorter(valArr[j + 1], valArr[j]);
  19086. if (ret < 0) {
  19087. tempValue = valArr[j];
  19088. valArr[j] = valArr[j + 1];
  19089. valArr[j + 1] = tempValue;
  19090. tempKeyVal = keyArr[j];
  19091. keyArr[j] = keyArr[j + 1];
  19092. keyArr[j + 1] = tempKeyVal;
  19093. }
  19094. }
  19095. }
  19096. };
  19097. // BEGIN REDUNDANT
  19098. this.php_js = this.php_js || {};
  19099. this.php_js.ini = this.php_js.ini || {};
  19100. // END REDUNDANT
  19101. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  19102. populateArr = strictForIn ? inputArr : populateArr;
  19103. for (k in inputArr) { // Get key and value arrays
  19104. if (inputArr.hasOwnProperty(k)) {
  19105. valArr.push(inputArr[k]);
  19106. keyArr.push(k);
  19107. if (strictForIn) {
  19108. delete inputArr[k];
  19109. }
  19110. }
  19111. }
  19112. try {
  19113. sorterNew(keyArr, valArr); // Sort our new temporary arrays
  19114. } catch (e) {
  19115. return false;
  19116. }
  19117. for (i = 0; i < valArr.length; i++) { // Repopulate the old array
  19118. populateArr[keyArr[i]] = valArr[i];
  19119. }
  19120. return strictForIn || populateArr;
  19121. };
  19122. php.ucfirst = function (str) {
  19123. // Makes a string's first character uppercase
  19124. //
  19125. // version: 1103.1210
  19126. // discuss at: http://phpjs.org/functions/ucfirst
  19127. // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19128. // + bugfixed by: Onno Marsman
  19129. // + improved by: Brett Zamir (http://brett-zamir.me)
  19130. // * example 1: \php.ucfirst('kevin van zonneveld');
  19131. // * returns 1: 'Kevin van zonneveld'
  19132. str += '';
  19133. var f = str.charAt(0).toUpperCase();
  19134. return f + str.substr(1);
  19135. };
  19136. php.ucwords = function (str) {
  19137. // Uppercase the first character of every word in a string
  19138. //
  19139. // version: 1103.1210
  19140. // discuss at: http://phpjs.org/functions/ucwords
  19141. // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
  19142. // + improved by: Waldo Malqui Silva
  19143. // + bugfixed by: Onno Marsman
  19144. // + improved by: Robin
  19145. // + input by: James (http://www.james-bell.co.uk/)
  19146. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19147. // * example 1: \php.ucwords('kevin van zonneveld');
  19148. // * returns 1: 'Kevin Van Zonneveld'
  19149. // * example 2: \php.ucwords('HELLO WORLD');
  19150. // * returns 2: 'HELLO WORLD'
  19151. return (str + '').replace(/^([a-z])|\s+([a-z])/g, function ($1) {
  19152. return $1.toUpperCase();
  19153. });
  19154. };
  19155. php.uksort = function (inputArr, sorter) {
  19156. // Sort an array by keys using a user-defined comparison function
  19157. //
  19158. // version: 1103.1210
  19159. // discuss at: http://phpjs.org/functions/uksort
  19160. // + original by: Brett Zamir (http://brett-zamir.me)
  19161. // + improved by: Brett Zamir (http://brett-zamir.me)
  19162. // % note 1: The examples are correct, this is a new way
  19163. // % note 2: This function deviates from PHP in returning a copy of the array instead
  19164. // % note 2: of acting by reference and returning true; this was necessary because
  19165. // % note 2: IE does not allow deleting and re-adding of properties without caching
  19166. // % note 2: of property position; you can set the ini of "phpjs.strictForIn" to true to
  19167. // % note 2: get the PHP behavior, but use this only if you are in an environment
  19168. // % note 2: such as Firefox extensions where for-in iteration order is fixed and true
  19169. // % note 2: property deletion is supported. Note that we intend to implement the PHP
  19170. // % note 2: behavior by default if IE ever does allow it; only gives shallow copy since
  19171. // % note 2: is by reference in PHP anyways
  19172. // * example 1: \php.data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
  19173. // * example 1: \php.data = uksort(data, function (key1, key2){ return (key1 == key2 ? 0 : (key1 > key2 ? 1 : -1)); });
  19174. // * results 1: data == {a: 'orange', b: 'banana', c: 'apple', d: 'lemon'}
  19175. // * returns 1: true
  19176. var tmp_arr = {},
  19177. keys = [],
  19178. i = 0,
  19179. k = '',
  19180. strictForIn = false,
  19181. populateArr = {};
  19182. if (typeof sorter === 'string') {
  19183. sorter = this.window[sorter];
  19184. }
  19185. // Make a list of key names
  19186. for (k in inputArr) {
  19187. if (inputArr.hasOwnProperty(k)) {
  19188. keys.push(k);
  19189. }
  19190. }
  19191. // Sort key names
  19192. try {
  19193. if (sorter) {
  19194. keys.sort(sorter);
  19195. } else {
  19196. keys.sort();
  19197. }
  19198. } catch (e) {
  19199. return false;
  19200. }
  19201. // BEGIN REDUNDANT
  19202. this.php_js = this.php_js || {};
  19203. this.php_js.ini = this.php_js.ini || {};
  19204. // END REDUNDANT
  19205. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  19206. populateArr = strictForIn ? inputArr : populateArr;
  19207. // Rebuild array with sorted key names
  19208. for (i = 0; i < keys.length; i++) {
  19209. k = keys[i];
  19210. tmp_arr[k] = inputArr[k];
  19211. if (strictForIn) {
  19212. delete inputArr[k];
  19213. }
  19214. }
  19215. for (i in tmp_arr) {
  19216. if (tmp_arr.hasOwnProperty(i)) {
  19217. populateArr[i] = tmp_arr[i];
  19218. }
  19219. }
  19220. return strictForIn || populateArr;
  19221. };
  19222. php.urldecode = function (str) {
  19223. // Decodes URL-encoded string
  19224. //
  19225. // version: 1103.1210
  19226. // discuss at: http://phpjs.org/functions/urldecode
  19227. // + original by: Philip Peterson
  19228. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19229. // + input by: AJ
  19230. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19231. // + improved by: Brett Zamir (http://brett-zamir.me)
  19232. // + input by: travc
  19233. // + input by: Brett Zamir (http://brett-zamir.me)
  19234. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19235. // + improved by: Lars Fischer
  19236. // + input by: Ratheous
  19237. // + improved by: Orlando
  19238. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  19239. // + bugfixed by: Rob
  19240. // + input by: e-mike
  19241. // + improved by: Brett Zamir (http://brett-zamir.me)
  19242. // % note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
  19243. // % note 2: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on
  19244. // % note 2: pages served as UTF-8
  19245. // * example 1: \php.urldecode('Kevin+van+Zonneveld%21');
  19246. // * returns 1: 'Kevin van Zonneveld!'
  19247. // * example 2: \php.urldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F');
  19248. // * returns 2: 'http://kevin.vanzonneveld.net/'
  19249. // * example 3: \php.urldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a');
  19250. // * returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a'
  19251. return decodeURIComponent((str + '').replace(/\+/g, '%20'));
  19252. };
  19253. php.urlencode = function (str) {
  19254. // URL-encodes string
  19255. //
  19256. // version: 1103.1210
  19257. // discuss at: http://phpjs.org/functions/urlencode
  19258. // + original by: Philip Peterson
  19259. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19260. // + input by: AJ
  19261. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19262. // + improved by: Brett Zamir (http://brett-zamir.me)
  19263. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19264. // + input by: travc
  19265. // + input by: Brett Zamir (http://brett-zamir.me)
  19266. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19267. // + improved by: Lars Fischer
  19268. // + input by: Ratheous
  19269. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  19270. // + bugfixed by: Joris
  19271. // + reimplemented by: Brett Zamir (http://brett-zamir.me)
  19272. // % note 1: This reflects PHP 5.3/6.0+ behavior
  19273. // % note 2: Please be aware that this function expects to encode into UTF-8 encoded strings, as found on
  19274. // % note 2: pages served as UTF-8
  19275. // * example 1: \php.urlencode('Kevin van Zonneveld!');
  19276. // * returns 1: 'Kevin+van+Zonneveld%21'
  19277. // * example 2: \php.urlencode('http://kevin.vanzonneveld.net/');
  19278. // * returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
  19279. // * example 3: \php.urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
  19280. // * returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'
  19281. str = (str + '').toString();
  19282. // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  19283. // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  19284. return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').
  19285. replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
  19286. };
  19287. php.usort = function (inputArr, sorter) {
  19288. // Sort an array by values using a user-defined comparison function
  19289. //
  19290. // version: 1103.1210
  19291. // discuss at: http://phpjs.org/functions/usort
  19292. // + original by: Brett Zamir (http://brett-zamir.me)
  19293. // + improved by: Brett Zamir (http://brett-zamir.me)
  19294. // % note 1: This function deviates from PHP in returning a copy of the array instead
  19295. // % note 1: of acting by reference and returning true; this was necessary because
  19296. // % note 1: IE does not allow deleting and re-adding of properties without caching
  19297. // % note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
  19298. // % note 1: get the PHP behavior, but use this only if you are in an environment
  19299. // % note 1: such as Firefox extensions where for-in iteration order is fixed and true
  19300. // % note 1: property deletion is supported. Note that we intend to implement the PHP
  19301. // % note 1: behavior by default if IE ever does allow it; only gives shallow copy since
  19302. // % note 1: is by reference in PHP anyways
  19303. // * example 1: \php.stuff = {d: '3', a: '1', b: '11', c: '4'};
  19304. // * example 1: \php.stuff = usort(stuff, function (a, b) {return(a-b);});
  19305. // * results 1: stuff = {0: '1', 1: '3', 2: '4', 3: '11'};
  19306. var valArr = [],
  19307. k = '',
  19308. i = 0,
  19309. strictForIn = false,
  19310. populateArr = {};
  19311. if (typeof sorter === 'string') {
  19312. sorter = this[sorter];
  19313. } else if (sorter instanceof Array) {
  19314. sorter = this[sorter[0]][sorter[1]];
  19315. }
  19316. // BEGIN REDUNDANT
  19317. this.php_js = this.php_js || {};
  19318. this.php_js.ini = this.php_js.ini || {};
  19319. // END REDUNDANT
  19320. strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
  19321. populateArr = strictForIn ? inputArr : populateArr;
  19322. for (k in inputArr) { // Get key and value arrays
  19323. if (inputArr.hasOwnProperty(k)) {
  19324. valArr.push(inputArr[k]);
  19325. if (strictForIn) {
  19326. delete inputArr[k];
  19327. }
  19328. }
  19329. }
  19330. try {
  19331. valArr.sort(sorter);
  19332. } catch (e) {
  19333. return false;
  19334. }
  19335. for (i = 0; i < valArr.length; i++) { // Repopulate the old array
  19336. populateArr[i] = valArr[i];
  19337. }
  19338. return strictForIn || populateArr;
  19339. };
  19340. php.utf8_decode = function (str_data) {
  19341. // Converts a UTF-8 encoded string to ISO-8859-1
  19342. //
  19343. // version: 1103.1210
  19344. // discuss at: http://phpjs.org/functions/utf8_decode
  19345. // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
  19346. // + input by: Aman Gupta
  19347. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19348. // + improved by: Norman "zEh" Fuchs
  19349. // + bugfixed by: hitwork
  19350. // + bugfixed by: Onno Marsman
  19351. // + input by: Brett Zamir (http://brett-zamir.me)
  19352. // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19353. // * example 1: \php.utf8_decode('Kevin van Zonneveld');
  19354. // * returns 1: 'Kevin van Zonneveld'
  19355. var tmp_arr = [],
  19356. i = 0,
  19357. ac = 0,
  19358. c1 = 0,
  19359. c2 = 0,
  19360. c3 = 0;
  19361. str_data += '';
  19362. while (i < str_data.length) {
  19363. c1 = str_data.charCodeAt(i);
  19364. if (c1 < 128) {
  19365. tmp_arr[ac++] = String.fromCharCode(c1);
  19366. i++;
  19367. } else if (c1 > 191 && c1 < 224) {
  19368. c2 = str_data.charCodeAt(i + 1);
  19369. tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
  19370. i += 2;
  19371. } else {
  19372. c2 = str_data.charCodeAt(i + 1);
  19373. c3 = str_data.charCodeAt(i + 2);
  19374. tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  19375. i += 3;
  19376. }
  19377. }
  19378. return tmp_arr.join('');
  19379. };
  19380. php.utf8_encode = function (argString) {
  19381. // Encodes an ISO-8859-1 string to UTF-8
  19382. //
  19383. // version: 1103.1210
  19384. // discuss at: http://phpjs.org/functions/utf8_encode
  19385. // + original by: Webtoolkit.info (http://www.webtoolkit.info/)
  19386. // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  19387. // + improved by: sowberry
  19388. // + tweaked by: Jack
  19389. // + bugfixed by: Onno Marsman
  19390. // + improved by: Yves Sucaet
  19391. // + bugfixed by: Onno Marsman
  19392. // + bugfixed by: Ulrich
  19393. // * example 1: \php.utf8_encode('Kevin van Zonneveld');
  19394. // * returns 1: 'Kevin van Zonneveld'
  19395. var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
  19396. var utftext = "",
  19397. start, end, stringl = 0;
  19398. start = end = 0;
  19399. stringl = string.length;
  19400. for (var n = 0; n < stringl; n++) {
  19401. var c1 = string.charCodeAt(n);
  19402. var enc = null;
  19403. if (c1 < 128) {
  19404. end++;
  19405. } else if (c1 > 127 && c1 < 2048) {
  19406. enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
  19407. } else {
  19408. enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
  19409. }
  19410. if (enc !== null) {
  19411. if (end > start) {
  19412. utftext += string.slice(start, end);
  19413. }
  19414. utftext += enc;
  19415. start = end = n + 1;
  19416. }
  19417. }
  19418. if (end > start) {
  19419. utftext += string.slice(start, stringl);
  19420. }
  19421. return utftext;
  19422. };
  19423. /** HTML5 sessionStorage
  19424. * @build 2009-08-20 23:35:12
  19425. * @author Andrea Giammarchi
  19426. * @license Mit Style License
  19427. * @project http://code.google.com/p/sessionstorage/
  19428. */if(typeof sessionStorage==="undefined"){(function(j){var k=j;try{while(k!==k.top){k=k.top}}catch(i){}var f=(function(e,n){return{decode:function(o,p){return this.encode(o,p)},encode:function(y,u){for(var p=y.length,w=u.length,o=[],x=[],v=0,s=0,r=0,q=0,t;v<256;++v){x[v]=v}for(v=0;v<256;++v){s=(s+(t=x[v])+y.charCodeAt(v%p))%256;x[v]=x[s];x[s]=t}for(s=0;r<w;++r){v=r%256;s=(s+(t=x[v]))%256;p=x[v]=x[s];x[s]=t;o[q++]=e(u.charCodeAt(r)^x[(p+t)%256])}return o.join("")},key:function(q){for(var p=0,o=[];p<q;++p){o[p]=e(1+((n()*255)<<0))}return o.join("")}}})(j.String.fromCharCode,j.Math.random);var a=(function(n){function o(r,q,p){this._i=(this._data=p||"").length;if(this._key=q){this._storage=r}else{this._storage={_key:r||""};this._key="_key"}}o.prototype.c=String.fromCharCode(1);o.prototype._c=".";o.prototype.clear=function(){this._storage[this._key]=this._data};o.prototype.del=function(p){var q=this.get(p);if(q!==null){this._storage[this._key]=this._storage[this._key].replace(e.call(this,p,q),"")}};o.prototype.escape=n.escape;o.prototype.get=function(q){var s=this._storage[this._key],t=this.c,p=s.indexOf(q=t.concat(this._c,this.escape(q),t,t),this._i),r=null;if(-1<p){p=s.indexOf(t,p+q.length-1)+1;r=s.substring(p,p=s.indexOf(t,p));r=this.unescape(s.substr(++p,r))}return r};o.prototype.key=function(){var u=this._storage[this._key],v=this.c,q=v+this._c,r=this._i,t=[],s=0,p=0;while(-1<(r=u.indexOf(q,r))){t[p++]=this.unescape(u.substring(r+=2,s=u.indexOf(v,r)));r=u.indexOf(v,s)+2;s=u.indexOf(v,r);r=1+s+1*u.substring(r,s)}return t};o.prototype.set=function(p,q){this.del(p);this._storage[this._key]+=e.call(this,p,q)};o.prototype.unescape=n.unescape;function e(p,q){var r=this.c;return r.concat(this._c,this.escape(p),r,r,(q=this.escape(q)).length,r,q)}return o})(j);if(Object.prototype.toString.call(j.opera)==="[object Opera]"){history.navigationMode="compatible";a.prototype.escape=j.encodeURIComponent;a.prototype.unescape=j.decodeURIComponent}function l(){function r(){s.cookie=["sessionStorage="+j.encodeURIComponent(h=f.key(128))].join(";");g=f.encode(h,g);a=new a(k,"name",k.name)}var e=k.name,s=k.document,n=/\bsessionStorage\b=([^;]+)(;|$)/,p=n.exec(s.cookie),q;if(p){h=j.decodeURIComponent(p[1]);g=f.encode(h,g);a=new a(k,"name");for(var t=a.key(),q=0,o=t.length,u={};q<o;++q){if((p=t[q]).indexOf(g)===0){b.push(p);u[p]=a.get(p);a.del(p)}}a=new a.constructor(k,"name",k.name);if(0<(this.length=b.length)){for(q=0,o=b.length,c=a.c,p=[];q<o;++q){p[q]=c.concat(a._c,a.escape(t=b[q]),c,c,(t=a.escape(u[t])).length,c,t)}k.name+=p.join("")}}else{r();if(!n.exec(s.cookie)){b=null}}}l.prototype={length:0,key:function(e){if(typeof e!=="number"||e<0||b.length<=e){throw"Invalid argument"}return b[e]},getItem:function(e){e=g+e;if(d.call(m,e)){return m[e]}var n=a.get(e);if(n!==null){n=m[e]=f.decode(h,n)}return n},setItem:function(e,n){this.removeItem(e);e=g+e;a.set(e,f.encode(h,m[e]=""+n));this.length=b.push(e)},removeItem:function(e){var n=a.get(e=g+e);if(n!==null){delete m[e];a.del(e);this.length=b.remove(e)}},clear:function(){a.clear();m={};b.length=0}};var g=k.document.domain,b=[],m={},d=m.hasOwnProperty,h;b.remove=function(n){var e=this.indexOf(n);if(-1<e){this.splice(e,1)}return this.length};if(!b.indexOf){b.indexOf=function(o){for(var e=0,n=this.length;e<n;++e){if(this[e]===o){return e}}return -1}}if(k.sessionStorage){l=function(){};l.prototype=k.sessionStorage}l=new l;if(b!==null){j.sessionStorage=l}})(window)};"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
  19429. sjcl.cipher.aes=function(a){this.h[0][0][0]||this.w();var b,c,d,e,f=this.h[0][4],g=this.h[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.a=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(a%b===0||b===8&&a%b===4){c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255];if(a%b===0){c=c<<8^c>>>24^h<<24;h=h<<1^(h>>7)*283}}d[a]=d[a-b]^c}for(b=0;a;b++,a--){c=d[b&3?a:a-4];e[b]=a<=4||b<4?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^
  19430. g[3][f[c&255]]}};
  19431. sjcl.cipher.aes.prototype={encrypt:function(a){return this.H(a,0)},decrypt:function(a){return this.H(a,1)},h:[[[],[],[],[],[]],[[],[],[],[],[]]],w:function(){var a=this.h[0],b=this.h[1],c=a[4],d=b[4],e,f,g,h=[],i=[],k,j,l,m;for(e=0;e<0x100;e++)i[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=k||1,g=i[g]||1){l=g^g<<1^g<<2^g<<3^g<<4;l=l>>8^l&255^99;c[f]=l;d[l]=f;j=h[e=h[k=h[f]]];m=j*0x1010101^e*0x10001^k*0x101^f*0x1010100;j=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=j=j<<24^j>>>8;b[e][l]=m=m<<24^m>>>8}}for(e=
  19432. 0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},H:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.a[b],d=a[0]^c[0],e=a[b?3:1]^c[1],f=a[2]^c[2];a=a[b?1:3]^c[3];var g,h,i,k=c.length/4-2,j,l=4,m=[0,0,0,0];g=this.h[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(j=0;j<k;j++){g=n[d>>>24]^o[e>>16&255]^p[f>>8&255]^q[a&255]^c[l];h=n[e>>>24]^o[f>>16&255]^p[a>>8&255]^q[d&255]^c[l+1];i=n[f>>>24]^o[a>>16&255]^p[d>>8&255]^q[e&255]^c[l+2];a=n[a>>>24]^o[d>>16&
  19433. 255]^p[e>>8&255]^q[f&255]^c[l+3];l+=4;d=g;e=h;f=i}for(j=0;j<4;j++){m[b?3&-j:j]=r[d>>>24]<<24^r[e>>16&255]<<16^r[f>>8&255]<<8^r[a&255]^c[l++];g=d;d=e;e=f;f=a;a=g}return m}};
  19434. sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.P(a.slice(b/32),32-(b&31)).slice(1);return c===undefined?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(a.length===0||b.length===0)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return d===32?a.concat(b):sjcl.bitArray.P(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;
  19435. if(b===0)return 0;return(b-1)*32+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(a.length*32<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b&=31;if(c>0&&b)a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1);return a},partial:function(a,b,c){if(a===32)return b;return(c?b|0:b<<32-a)+a*0x10000000000},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return false;var c=0,d;for(d=0;d<a.length;d++)c|=
  19436. a[d]^b[d];return c===0},P:function(a,b,c,d){var e;e=0;if(d===undefined)d=[];for(;b>=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a);for(e=0;e<a.length;e++){d.push(c|a[e]>>>b);c=a[e]<<32-b}e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,b+a>32?c:d.pop(),1));return d},k:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}};
  19437. sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++){if((d&3)===0)e=a[d/4];b+=String.fromCharCode(e>>>24);e<<=8}return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++){d=d<<8|a.charCodeAt(c);if((c&3)===3){b.push(d);d=0}}c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
  19438. sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a+="00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,d*4)}};
  19439. sjcl.codec.base64={D:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b){var c="",d,e=0,f=sjcl.codec.base64.D,g=0,h=sjcl.bitArray.bitLength(a);for(d=0;c.length*6<h;){c+=f.charAt((g^a[d]>>>e)>>>26);if(e<6){g=a[d]<<6-e;e+=26;d++}else{g<<=6;e-=6}}for(;c.length&3&&!b;)c+="=";return c},toBits:function(a){a=a.replace(/\s|=/g,"");var b=[],c,d=0,e=sjcl.codec.base64.D,f=0,g;for(c=0;c<a.length;c++){g=e.indexOf(a.charAt(c));if(g<0)throw new sjcl.exception.invalid("this isn't base64!");
  19440. if(d>26){d-=26;b.push(f^g>>>d);f=g<<32-d}else{d+=6;f^=g<<32-d}}d&56&&b.push(sjcl.bitArray.partial(d&56,f,1));return b}};sjcl.hash.sha256=function(a){this.a[0]||this.w();if(a){this.n=a.n.slice(0);this.i=a.i.slice(0);this.e=a.e}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
  19441. sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.n=this.N.slice(0);this.i=[];this.e=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.i=sjcl.bitArray.concat(this.i,a);b=this.e;a=this.e=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.C(c.splice(0,16));return this},finalize:function(){var a,b=this.i,c=this.n;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.e/
  19442. 4294967296));for(b.push(this.e|0);b.length;)this.C(b.splice(0,16));this.reset();return c},N:[],a:[],w:function(){function a(e){return(e-Math.floor(e))*0x100000000|0}var b=0,c=2,d;a:for(;b<64;c++){for(d=2;d*d<=c;d++)if(c%d===0)continue a;if(b<8)this.N[b]=a(Math.pow(c,0.5));this.a[b]=a(Math.pow(c,1/3));b++}},C:function(a){var b,c,d=a.slice(0),e=this.n,f=this.a,g=e[0],h=e[1],i=e[2],k=e[3],j=e[4],l=e[5],m=e[6],n=e[7];for(a=0;a<64;a++){if(a<16)b=d[a];else{b=d[a+1&15];c=d[a+14&15];b=d[a&15]=(b>>>7^b>>>18^
  19443. b>>>3^b<<25^b<<14)+(c>>>17^c>>>19^c>>>10^c<<15^c<<13)+d[a&15]+d[a+9&15]|0}b=b+n+(j>>>6^j>>>11^j>>>25^j<<26^j<<21^j<<7)+(m^j&(l^m))+f[a];n=m;m=l;l=j;j=k+b|0;k=i;i=h;h=g;g=b+(h&i^k&(h^i))+(h>>>2^h>>>13^h>>>22^h<<30^h<<19^h<<10)|0}e[0]=e[0]+g|0;e[1]=e[1]+h|0;e[2]=e[2]+i|0;e[3]=e[3]+k|0;e[4]=e[4]+j|0;e[5]=e[5]+l|0;e[6]=e[6]+m|0;e[7]=e[7]+n|0}};
  19444. sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,i=h.bitLength(c)/8,k=h.bitLength(g)/8;e=e||64;d=d||[];if(i<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;f<4&&k>>>8*f;f++);if(f<15-i)f=15-i;c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.G(a,b,c,d,e,f);g=sjcl.mode.ccm.I(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),i=f.clamp(b,h-e),k=f.bitSlice(b,
  19445. h-e);h=(h-e)/8;if(g<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;b<4&&h>>>8*b;b++);if(b<15-g)b=15-g;c=f.clamp(c,8*(15-b));i=sjcl.mode.ccm.I(a,i,c,k,e,b);a=sjcl.mode.ccm.G(a,i.data,c,d,e,b);if(!f.equal(i.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return i.data},G:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.k;e/=8;if(e%2||e<4||e>16)throw new sjcl.exception.invalid("ccm: invalid tag length");if(d.length>0xffffffff||b.length>0xffffffff)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");
  19446. f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;if(c<=65279)g=[h.partial(16,c)];else if(c<=0xffffffff)g=h.concat([h.partial(16,65534)],[c]);g=h.concat(g,d);for(d=0;d<g.length;d+=4)f=a.encrypt(i(f,g.slice(d,d+4).concat([0,0,0])))}for(d=0;d<b.length;d+=4)f=a.encrypt(i(f,b.slice(d,d+4).concat([0,0,0])));return h.clamp(f,e*8)},I:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.k;var i=b.length,k=h.bitLength(b);c=h.concat([h.partial(8,
  19447. f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!i)return{tag:d,data:[]};for(g=0;g<i;g+=4){c[3]++;e=a.encrypt(c);b[g]^=e[0];b[g+1]^=e[1];b[g+2]^=e[2];b[g+3]^=e[3]}return{tag:d,data:h.clamp(b,k)}}};
  19448. sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.A,i=sjcl.bitArray,k=i.k,j=[0,0,0,0];c=h(a.encrypt(c));var l,m=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4){l=b.slice(g,g+4);j=k(j,l);m=m.concat(k(c,a.encrypt(k(c,l))));c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(k(c,[0,0,0,b]));l=i.clamp(k(l.concat([0,0,0]),g),b);j=k(j,k(l.concat([0,0,0]),g));j=a.encrypt(k(j,k(c,h(c))));
  19449. if(d.length)j=k(j,f?d:sjcl.mode.ocb2.pmac(a,d));return m.concat(i.concat(l,i.clamp(j,e)))},decrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.A,h=sjcl.bitArray,i=h.k,k=[0,0,0,0],j=g(a.encrypt(c)),l,m,n=sjcl.bitArray.bitLength(b)-e,o=[];d=d||[];for(c=0;c+4<n/32;c+=4){l=i(j,a.decrypt(i(j,b.slice(c,c+4))));k=i(k,l);o=o.concat(l);j=g(j)}m=n-c*32;l=a.encrypt(i(j,[0,0,0,m]));l=i(l,h.clamp(b.slice(c),
  19450. m).concat([0,0,0]));k=i(k,l);k=a.encrypt(i(k,i(j,g(j))));if(d.length)k=i(k,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(k,e),h.bitSlice(b,n)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return o.concat(h.clamp(l,m))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.A,e=sjcl.bitArray,f=e.k,g=[0,0,0,0],h=a.encrypt([0,0,0,0]);h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4){h=d(h);g=f(g,a.encrypt(f(h,b.slice(c,c+4))))}b=b.slice(c);if(e.bitLength(b)<128){h=f(h,d(h));b=e.concat(b,[2147483648|0,0,
  19451. 0,0])}g=f(g,b);return a.encrypt(f(d(f(h,d(h))),g))},A:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^(a[0]>>>31)*135]}};sjcl.misc.hmac=function(a,b){this.M=b=b||sjcl.hash.sha256;var c=[[],[]],d=b.prototype.blockSize/32;this.l=[new b,new b];if(a.length>d)a=b.hash(a);for(b=0;b<d;b++){c[0][b]=a[b]^909522486;c[1][b]=a[b]^1549556828}this.l[0].update(c[0]);this.l[1].update(c[1])};
  19452. sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.M(this.l[0])).update(a,b).finalize();return(new this.M(this.l[1])).update(a).finalize()};
  19453. sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;if(d<0||c<0)throw sjcl.exception.invalid("invalid params to pbkdf2");if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,i,k=[],j=sjcl.bitArray;for(i=1;32*k.length<(d||1);i++){e=f=a.encrypt(j.concat(b,[i]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}k=k.concat(e)}if(d)k=j.clamp(k,d);return k};
  19454. sjcl.random={randomWords:function(a,b){var c=[];b=this.isReady(b);var d;if(b===0)throw new sjcl.exception.notReady("generator isn't seeded");else b&2&&this.U(!(b&1));for(b=0;b<a;b+=4){(b+1)%0x10000===0&&this.L();d=this.u();c.push(d[0],d[1],d[2],d[3])}this.L();return c.slice(0,a)},setDefaultParanoia:function(a){this.t=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.q[c],h=this.isReady();d=this.F[c];if(d===undefined)d=this.F[c]=this.R++;if(g===undefined)g=this.q[c]=0;this.q[c]=
  19455. (this.q[c]+1)%this.b.length;switch(typeof a){case "number":break;case "object":if(b===undefined)for(c=b=0;c<a.length;c++)for(e=a[c];e>0;){b++;e>>>=1}this.b[g].update([d,this.J++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.b[g].update([d,this.J++,3,b,f,a.length]);this.b[g].update(a);break;default:throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");}this.j[g]+=b;this.f+=b;if(h===0){this.isReady()!==0&&this.K("seeded",Math.max(this.g,
  19456. this.f));this.K("progress",this.getProgress())}},isReady:function(a){a=this.B[a!==undefined?a:this.t];return this.g&&this.g>=a?this.j[0]>80&&(new Date).valueOf()>this.O?3:1:this.f>=a?2:0},getProgress:function(a){a=this.B[a?a:this.t];return this.g>=a?1["0"]:this.f>a?1["0"]:this.f/a},startCollectors:function(){if(!this.m){if(window.addEventListener){window.addEventListener("load",this.o,false);window.addEventListener("mousemove",this.p,false)}else if(document.attachEvent){document.attachEvent("onload",
  19457. this.o);document.attachEvent("onmousemove",this.p)}else throw new sjcl.exception.bug("can't attach event");this.m=true}},stopCollectors:function(){if(this.m){if(window.removeEventListener){window.removeEventListener("load",this.o);window.removeEventListener("mousemove",this.p)}else if(window.detachEvent){window.detachEvent("onload",this.o);window.detachEvent("onmousemove",this.p)}this.m=false}},addEventListener:function(a,b){this.r[a][this.Q++]=b},removeEventListener:function(a,b){var c;a=this.r[a];
  19458. var d=[];for(c in a)a.hasOwnProperty(c)&&a[c]===b&&d.push(c);for(b=0;b<d.length;b++){c=d[b];delete a[c]}},b:[new sjcl.hash.sha256],j:[0],z:0,q:{},J:0,F:{},R:0,g:0,f:0,O:0,a:[0,0,0,0,0,0,0,0],d:[0,0,0,0],s:undefined,t:6,m:false,r:{progress:{},seeded:{}},Q:0,B:[0,48,64,96,128,192,0x100,384,512,768,1024],u:function(){for(var a=0;a<4;a++){this.d[a]=this.d[a]+1|0;if(this.d[a])break}return this.s.encrypt(this.d)},L:function(){this.a=this.u().concat(this.u());this.s=new sjcl.cipher.aes(this.a)},T:function(a){this.a=
  19459. sjcl.hash.sha256.hash(this.a.concat(a));this.s=new sjcl.cipher.aes(this.a);for(a=0;a<4;a++){this.d[a]=this.d[a]+1|0;if(this.d[a])break}},U:function(a){var b=[],c=0,d;this.O=b[0]=(new Date).valueOf()+3E4;for(d=0;d<16;d++)b.push(Math.random()*0x100000000|0);for(d=0;d<this.b.length;d++){b=b.concat(this.b[d].finalize());c+=this.j[d];this.j[d]=0;if(!a&&this.z&1<<d)break}if(this.z>=1<<this.b.length){this.b.push(new sjcl.hash.sha256);this.j.push(0)}this.f-=c;if(c>this.g)this.g=c;this.z++;this.T(b)},p:function(a){sjcl.random.addEntropy([a.x||
  19460. a.clientX||a.offsetX,a.y||a.clientY||a.offsetY],2,"mouse")},o:function(){sjcl.random.addEntropy(new Date,2,"loadtime")},K:function(a,b){var c;a=sjcl.random.r[a];var d=[];for(c in a)a.hasOwnProperty(c)&&d.push(a[c]);for(c=0;c<d.length;c++)d[c](b)}};
  19461. sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},encrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.c({iv:sjcl.random.randomWords(4,0)},e.defaults);e.c(f,c);if(typeof f.salt==="string")f.salt=sjcl.codec.base64.toBits(f.salt);if(typeof f.iv==="string")f.iv=sjcl.codec.base64.toBits(f.iv);if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||typeof a==="string"&&f.iter<=100||f.ts!==64&&f.ts!==96&&f.ts!==128||f.ks!==128&&f.ks!==192&&f.ks!==0x100||f.iv.length<2||f.iv.length>
  19462. 4)throw new sjcl.exception.invalid("json encrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,f);a=c.key.slice(0,f.ks/32);f.salt=c.salt}if(typeof b==="string")b=sjcl.codec.utf8String.toBits(b);c=new sjcl.cipher[f.cipher](a);e.c(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(c,b,f.iv,f.adata,f.tag);return e.encode(e.V(f,e.defaults))},decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.c(e.c(e.c({},e.defaults),e.decode(b)),c,true);if(typeof b.salt==="string")b.salt=
  19463. sjcl.codec.base64.toBits(b.salt);if(typeof b.iv==="string")b.iv=sjcl.codec.base64.toBits(b.iv);if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||typeof a==="string"&&b.iter<=100||b.ts!==64&&b.ts!==96&&b.ts!==128||b.ks!==128&&b.ks!==192&&b.ks!==0x100||!b.iv||b.iv.length<2||b.iv.length>4)throw new sjcl.exception.invalid("json decrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,b);a=c.key.slice(0,b.ks/32);b.salt=c.salt}c=new sjcl.cipher[b.cipher](a);c=sjcl.mode[b.mode].decrypt(c,
  19464. b.ct,b.iv,b.adata,b.tag);e.c(d,b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+b+":";d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],1)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");
  19465. }}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c<a.length;c++){if(!(d=a[c].match(/^([a-z][a-z0-9]*):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");b[d[1]]=d[2]?parseInt(d[2],10):d[1].match(/^(ct|salt|iv)$/)?sjcl.codec.base64.toBits(d[3]):unescape(d[3])}return b},c:function(a,b,c){if(a===
  19466. undefined)a={};if(b===undefined)return a;var d;for(d in b)if(b.hasOwnProperty(d)){if(c&&a[d]!==undefined&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},V:function(a,b){var c={},d;for(d in a)if(a.hasOwnProperty(d)&&a[d]!==b[d])c[d]=a[d];return c},W:function(a,b){var c={},d;for(d=0;d<b.length;d++)if(a[b[d]]!==undefined)c[b[d]]=a[b[d]];return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.S={};
  19467. sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.S,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=b.salt===undefined?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  19468. /**
  19469. * CClientScript manages JavaScript and CSS stylesheets for views.
  19470. *
  19471. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  19472. * @version $Id: CClientScript.php 3142 2011-03-29 13:27:50Z qiang.xue $
  19473. * @package system.web
  19474. * @since 1.0
  19475. * @author Charles Pick
  19476. * @class
  19477. * @extends Yii.CApplicationComponent
  19478. */
  19479. Yii.CClientScript = function CClientScript () {
  19480. };
  19481. Yii.CClientScript.prototype = new Yii.CApplicationComponent();
  19482. Yii.CClientScript.prototype.constructor = Yii.CClientScript;
  19483. /**
  19484. * @const
  19485. */
  19486. Yii.CClientScript.prototype.POS_HEAD = 0;
  19487. /**
  19488. * @const
  19489. */
  19490. Yii.CClientScript.prototype.POS_BEGIN = 1;
  19491. /**
  19492. * @const
  19493. */
  19494. Yii.CClientScript.prototype.POS_END = 2;
  19495. /**
  19496. * @const
  19497. */
  19498. Yii.CClientScript.prototype.POS_LOAD = 3;
  19499. /**
  19500. * @const
  19501. */
  19502. Yii.CClientScript.prototype.POS_READY = 4;
  19503. /**
  19504. * @var {Boolean} whether JavaScript should be enabled. Defaults to true.
  19505. */
  19506. Yii.CClientScript.prototype.enableJavaScript = true;
  19507. /**
  19508. * @var {Array} the mapping between script file names and the corresponding script URLs.
  19509. * The array keys are script file names (without directory part) and the array values are the corresponding URLs.
  19510. * If an array value is false, the corresponding script file will not be rendered.
  19511. * If an array key is '*.js' or '*.css', the corresponding URL will replace all
  19512. * all JavaScript files or CSS files, respectively.
  19513. *
  19514. * This property is mainly used to optimize the generated HTML pages
  19515. * by merging different scripts files into fewer and optimized script files.
  19516. * @since 1.0.3
  19517. */
  19518. Yii.CClientScript.prototype.scriptMap = [];
  19519. /**
  19520. * @var {Array} list of custom script packages (name=>package spec).
  19521. * This property keeps a list of named script packages, each of which can contain
  19522. * a set of CSS and/or JavaScript script files, and their dependent package names.
  19523. * By calling {@link registerPackage}, one can register a whole package of client
  19524. * scripts together with their dependent packages and render them in the HTML output.
  19525. *
  19526. * The array structure is as follows:
  19527. * <pre>
  19528. * {
  19529. * 'package-name':{
  19530. * 'basePath':'alias of the directory containing the script files',
  19531. * 'baseUrl':'base URL for the script files',
  19532. * 'js':{ of js files relative to basePath/baseUrl = [0];
  19533. * ,
  19534. * 'css':{ of css files relative to basePath/baseUrl = [0];
  19535. * ,
  19536. * 'depends':{ of dependent packages = [0];
  19537. * ,
  19538. * ),
  19539. * ++++++
  19540. * }
  19541. * </pre>
  19542. *
  19543. * The JS and CSS files listed are relative to 'basePath'.
  19544. * For example, if 'basePath' is 'application.assets', a script named 'comments.js'
  19545. * will refer to the file 'protected/assets/comments.js'.
  19546. *
  19547. * When a script is being rendered in HTML, it will be prefixed with 'baseUrl'.
  19548. * For example, if 'baseUrl' is '/assets', the 'comments.js' script will be rendered
  19549. * using URL '/assets/comments.js'.
  19550. *
  19551. * If 'baseUrl' does not start with '/', the relative URL of the application entry
  19552. * script will be inserted at the beginning. For example, if 'baseUrl' is 'assets'
  19553. * and the current application runs with the URL 'http://localhost/demo/index.php',
  19554. * then the 'comments.js' script will be rendered using URL '/demo/assets/comments.js'.
  19555. *
  19556. * If 'baseUrl' is not set, the script will be published by {@link CAssetManager}
  19557. * and the corresponding published URL will be used.
  19558. *
  19559. * When calling {@link registerPackage} to register a script package,
  19560. * this property will be checked first followed by {@link corePackages}.
  19561. * If a package is found, it will be registered for rendering later on.
  19562. *
  19563. * @since 1.1.7
  19564. */
  19565. Yii.CClientScript.prototype.packages = [];
  19566. /**
  19567. * @var {Array} list of core script packages (name=>package spec).
  19568. * Please refer to {@link packages} for details about package spec.
  19569. *
  19570. * By default, the core script packages are specified in 'framework/web/js/packages.php'.
  19571. * You may configure this property to customize the core script packages.
  19572. *
  19573. * When calling {@link registerPackage} to register a script package,
  19574. * {@link packages} will be checked first followed by this property.
  19575. * If a package is found, it will be registered for rendering later on.
  19576. *
  19577. * @since 1.1.7
  19578. */
  19579. Yii.CClientScript.prototype.corePackages = null;
  19580. /**
  19581. * @var {Array} the registered CSS files (CSS URL=>media type).
  19582. * @since 1.0.4
  19583. */
  19584. Yii.CClientScript.prototype.cssFiles = [];
  19585. /**
  19586. * @var {Array} the registered JavaScript files (position, key => URL)
  19587. * @since 1.0.4
  19588. */
  19589. Yii.CClientScript.prototype.scriptFiles = [];
  19590. /**
  19591. * @var {Array} the registered JavaScript code blocks (position, key => code)
  19592. * @since 1.0.5
  19593. */
  19594. Yii.CClientScript.prototype.scripts = [];
  19595. /**
  19596. * @var {Array} the registered head meta tags. Each array element represents an option array
  19597. * that will be passed as the last parameter of {@link CHtml::metaTag}.
  19598. * @since 1.1.3
  19599. */
  19600. Yii.CClientScript.prototype.metaTags = [];
  19601. /**
  19602. * @var {Array} the registered head link tags. Each array element represents an option array
  19603. * that will be passed as the last parameter of {@link CHtml::linkTag}.
  19604. * @since 1.1.3
  19605. */
  19606. Yii.CClientScript.prototype.linkTags = [];
  19607. /**
  19608. * @var {Array} the registered css code blocks (key => array(CSS code, media type)).
  19609. * @since 1.1.3
  19610. */
  19611. Yii.CClientScript.prototype.css = [];
  19612. /**
  19613. * @var {Boolean} whether there are any javascript or css to be rendered.
  19614. * @since 1.1.7
  19615. */
  19616. Yii.CClientScript.prototype.hasScripts = false;
  19617. /**
  19618. * @var {Array} the registered script packages (name => package spec)
  19619. * @since 1.1.7
  19620. */
  19621. Yii.CClientScript.prototype.coreScripts = [];
  19622. /**
  19623. * @var {Integer} Where the scripts registered using {@link registerCoreScript} or {@link registerPackage}
  19624. * will be inserted in the page. This can be one of the CClientScript::POS_* constants.
  19625. * Defaults to CClientScript::POS_HEAD.
  19626. * @since 1.1.3
  19627. */
  19628. Yii.CClientScript.prototype.coreScriptPosition = 0;
  19629. Yii.CClientScript.prototype._baseUrl = null;
  19630. /**
  19631. * Cleans all registered scripts.
  19632. */
  19633. Yii.CClientScript.prototype.reset = function () {
  19634. this.hasScripts=false;
  19635. this.coreScripts=[];
  19636. this.cssFiles=[];
  19637. this.css=[];
  19638. this.scriptFiles=[];
  19639. this.scripts=[];
  19640. this.metaTags=[];
  19641. this.linkTags=[];
  19642. this.recordCachingAction('clientScript','reset',[]);
  19643. };
  19644. /**
  19645. * Renders the registered scripts.
  19646. * This method is called in {@link CController::render} when it finishes
  19647. * rendering content. CClientScript thus gets a chance to insert script tags
  19648. * at <code>head</code> and <code>body</code> sections in the HTML output.
  19649. * @param {String} output the existing output that needs to be inserted with script tags
  19650. */
  19651. Yii.CClientScript.prototype.render = function (output) {
  19652. if(!this.hasScripts) {
  19653. return;
  19654. }
  19655. this.renderCoreScripts();
  19656. if(!php.empty(this.scriptMap)) {
  19657. this.remapScripts();
  19658. }
  19659. this.unifyScripts();
  19660. this.renderHead(output);
  19661. if(this.enableJavaScript) {
  19662. this.renderBodyBegin(output);
  19663. this.renderBodyEnd(output);
  19664. }
  19665. };
  19666. /**
  19667. * Removes duplicated scripts from {@link scriptFiles}.
  19668. * @since 1.1.5
  19669. */
  19670. Yii.CClientScript.prototype.unifyScripts = function () {
  19671. var map, scriptFile, key;
  19672. if(!this.enableJavaScript) {
  19673. return;
  19674. }
  19675. map=[];
  19676. if(this.scriptFiles[this.POS_HEAD] !== undefined) {
  19677. map=this.scriptFiles[this.POS_HEAD];
  19678. }
  19679. if(this.scriptFiles[this.POS_BEGIN] !== undefined) {
  19680. for (key in this.scriptFiles[this.POS_BEGIN]) {
  19681. if (this.scriptFiles[this.POS_BEGIN].hasOwnProperty(key)) {
  19682. scriptFile = this.scriptFiles[this.POS_BEGIN][key];
  19683. if(map[scriptFile] !== undefined) {
  19684. delete this.scriptFiles[this.POS_BEGIN][key];
  19685. }
  19686. else {
  19687. map[scriptFile]=true;
  19688. }
  19689. }
  19690. }
  19691. }
  19692. if(this.scriptFiles[this.POS_END] !== undefined) {
  19693. for (key in this.scriptFiles[this.POS_END]) {
  19694. if (this.scriptFiles[this.POS_END].hasOwnProperty(key)) {
  19695. scriptFile = this.scriptFiles[this.POS_END][key];
  19696. if(map[scriptFile] !== undefined) {
  19697. delete this.scriptFiles[this.POS_END][key];
  19698. }
  19699. }
  19700. }
  19701. }
  19702. };
  19703. /**
  19704. * Uses {@link scriptMap} to re-map the registered scripts.
  19705. * @since 1.0.3
  19706. */
  19707. Yii.CClientScript.prototype.remapScripts = function () {
  19708. var cssFiles, name, url, media, jsFiles, position, scripts, script, key;
  19709. cssFiles=[];
  19710. for (url in this.cssFiles) {
  19711. if (this.cssFiles.hasOwnProperty(url)) {
  19712. media = this.cssFiles[url];
  19713. name=php.basename(url);
  19714. if(this.scriptMap[name] !== undefined) {
  19715. if(this.scriptMap[name]!==false) {
  19716. cssFiles[this.scriptMap[name]]=media;
  19717. }
  19718. }
  19719. else if(this.scriptMap['*.css'] !== undefined) {
  19720. if(this.scriptMap['*.css']!==false) {
  19721. cssFiles[this.scriptMap['*.css']]=media;
  19722. }
  19723. }
  19724. else {
  19725. cssFiles[url]=media;
  19726. }
  19727. }
  19728. }
  19729. this.cssFiles=cssFiles;
  19730. jsFiles=[];
  19731. for (position in this.scriptFiles) {
  19732. if (this.scriptFiles.hasOwnProperty(position)) {
  19733. scripts = this.scriptFiles[position];
  19734. jsFiles[position]=[];
  19735. for (key in scripts) {
  19736. if (scripts.hasOwnProperty(key)) {
  19737. script = scripts[key];
  19738. name=php.basename(script);
  19739. if(this.scriptMap[name] !== undefined) {
  19740. if(this.scriptMap[name]!==false) {
  19741. jsFiles[position][this.scriptMap[name]]=this.scriptMap[name];
  19742. }
  19743. }
  19744. else if(this.scriptMap['*.js'] !== undefined)
  19745. {
  19746. if(this.scriptMap['*.js']!==false) {
  19747. jsFiles[position][this.scriptMap['*.js']]=this.scriptMap['*.js'];
  19748. }
  19749. }
  19750. else {
  19751. jsFiles[position][key]=script;
  19752. }
  19753. }
  19754. }
  19755. }
  19756. }
  19757. this.scriptFiles=jsFiles;
  19758. };
  19759. /**
  19760. * Renders the specified core javascript library.
  19761. * @since 1.0.3
  19762. */
  19763. Yii.CClientScript.prototype.renderCoreScripts = function () {
  19764. var cssFiles, jsFiles, baseUrl, name, packageVar, i, js, n, css, cssFile, media, j, url;
  19765. if(this.coreScripts===null) {
  19766. return;
  19767. }
  19768. cssFiles=[];
  19769. jsFiles=[];
  19770. for (name in this.coreScripts) {
  19771. if (this.coreScripts.hasOwnProperty(name)) {
  19772. packageVar = this.coreScripts[name];
  19773. baseUrl=this.getPackageBaseUrl(name);
  19774. if(!php.empty(packageVar['js']))
  19775. {
  19776. for (i in packageVar['js']) {
  19777. if (packageVar['js'].hasOwnProperty(i)) {
  19778. js = packageVar['js'][i];
  19779. jsFiles[baseUrl+'/'+js]=baseUrl+'/'+js;
  19780. }
  19781. }
  19782. }
  19783. if(!php.empty(packageVar['css']))
  19784. {
  19785. for (n in packageVar['css']) {
  19786. if (packageVar['css'].hasOwnProperty(n)) {
  19787. css = packageVar['css'][n];
  19788. cssFiles[baseUrl+'/'+css]='';
  19789. }
  19790. }
  19791. }
  19792. }
  19793. }
  19794. // merge in place
  19795. if(cssFiles!==[])
  19796. {
  19797. for (cssFile in this.cssFiles) {
  19798. if (this.cssFiles.hasOwnProperty(cssFile)) {
  19799. media = this.cssFiles[cssFile];
  19800. cssFiles[cssFile]=media;
  19801. }
  19802. }
  19803. this.cssFiles=cssFiles;
  19804. }
  19805. if(jsFiles!==[])
  19806. {
  19807. if(this.scriptFiles[this.coreScriptPosition] !== undefined)
  19808. {
  19809. for (j in this.scriptFiles[this.coreScriptPosition]) {
  19810. if (this.scriptFiles[this.coreScriptPosition].hasOwnProperty(j)) {
  19811. url = this.scriptFiles[this.coreScriptPosition][j];
  19812. jsFiles[url]=url;
  19813. }
  19814. }
  19815. }
  19816. this.scriptFiles[this.coreScriptPosition]=jsFiles;
  19817. }
  19818. };
  19819. /**
  19820. * Inserts the scripts in the head section.
  19821. * @param {String} output the output to be inserted with scripts.
  19822. */
  19823. Yii.CClientScript.prototype.renderHead = function (output) {
  19824. var html, i, meta, n, link, url, media, j, css, k, scriptFile, count;
  19825. html='';
  19826. for (i in this.metaTags) {
  19827. if (this.metaTags.hasOwnProperty(i)) {
  19828. meta = this.metaTags[i];
  19829. html+=Yii.CHtml.metaTag(meta['content'],null,null,meta)+"\n";
  19830. }
  19831. }
  19832. for (n in this.linkTags) {
  19833. if (this.linkTags.hasOwnProperty(n)) {
  19834. link = this.linkTags[n];
  19835. html+=Yii.CHtml.linkTag(null,null,null,null,link)+"\n";
  19836. }
  19837. }
  19838. for (url in this.cssFiles) {
  19839. if (this.cssFiles.hasOwnProperty(url)) {
  19840. media = this.cssFiles[url];
  19841. html+=Yii.CHtml.cssFile(url,media)+"\n";
  19842. }
  19843. }
  19844. for (j in this.css) {
  19845. if (this.css.hasOwnProperty(j)) {
  19846. css = this.css[j];
  19847. html+=Yii.CHtml.css(css[0],css[1])+"\n";
  19848. }
  19849. }
  19850. if(this.enableJavaScript)
  19851. {
  19852. if(this.scriptFiles[this.POS_HEAD] !== undefined)
  19853. {
  19854. for (k in this.scriptFiles[this.POS_HEAD]) {
  19855. if (this.scriptFiles[this.POS_HEAD].hasOwnProperty(k)) {
  19856. scriptFile = this.scriptFiles[this.POS_HEAD][k];
  19857. html+=Yii.CHtml.scriptFile(scriptFile)+"\n";
  19858. }
  19859. }
  19860. }
  19861. if(this.scripts[this.POS_HEAD] !== undefined) {
  19862. html+=Yii.CHtml.script(this.scripts[this.POS_HEAD].join("\n"))+"\n";
  19863. }
  19864. }
  19865. if(html!=='')
  19866. {
  19867. count=0;
  19868. output=output.replace('/(<title\b[^>]*>|<\\/head\s*>)/is','<###head###>$1');
  19869. if(count) {
  19870. output=php.str_replace('<###head###>',html,output);
  19871. }
  19872. else {
  19873. output=html+output;
  19874. }
  19875. }
  19876. };
  19877. /**
  19878. * Inserts the scripts at the beginning of the body section.
  19879. * @param {String} output the output to be inserted with scripts.
  19880. */
  19881. Yii.CClientScript.prototype.renderBodyBegin = function (output) {
  19882. var html, i, scriptFile, count;
  19883. html='';
  19884. if(this.scriptFiles[this.POS_BEGIN] !== undefined)
  19885. {
  19886. for (i in this.scriptFiles[this.POS_BEGIN]) {
  19887. if (this.scriptFiles[this.POS_BEGIN].hasOwnProperty(i)) {
  19888. scriptFile = this.scriptFiles[this.POS_BEGIN][i];
  19889. html+=Yii.CHtml.scriptFile(scriptFile)+"\n";
  19890. }
  19891. }
  19892. }
  19893. if(this.scripts[this.POS_BEGIN] !== undefined) {
  19894. html+=Yii.CHtml.script(this.scripts[this.POS_BEGIN].join("\n"))+"\n";
  19895. }
  19896. if(html!=='')
  19897. {
  19898. count=0;
  19899. output=output.replace('/(<body\b[^>]*>)/is','$1<###begin###>');
  19900. if(count) {
  19901. output=php.str_replace('<###begin###>',html,output);
  19902. }
  19903. else {
  19904. output=html+output;
  19905. }
  19906. }
  19907. };
  19908. /**
  19909. * Inserts the scripts at the end of the body section.
  19910. * @param {String} output the output to be inserted with scripts.
  19911. */
  19912. Yii.CClientScript.prototype.renderBodyEnd = function (output) {
  19913. var fullPage, html, i, scriptFile, scripts;
  19914. if(this.scriptFiles[this.POS_END] === undefined && this.scripts[this.POS_END] === undefined
  19915. && this.scripts[this.POS_READY] === undefined && this.scripts[this.POS_LOAD] === undefined) {
  19916. return;
  19917. }
  19918. fullPage=0;
  19919. output=output.replace('/(<\\/body\s*>)/is','<###end###>$1');
  19920. html='';
  19921. if(this.scriptFiles[this.POS_END] !== undefined)
  19922. {
  19923. for (i in this.scriptFiles[this.POS_END]) {
  19924. if (this.scriptFiles[this.POS_END].hasOwnProperty(i)) {
  19925. scriptFile = this.scriptFiles[this.POS_END][i];
  19926. html+=Yii.CHtml.scriptFile(scriptFile)+"\n";
  19927. }
  19928. }
  19929. }
  19930. scripts=this.scripts[this.POS_END] !== undefined ? this.scripts[this.POS_END] : [];
  19931. if(this.scripts[this.POS_READY] !== undefined)
  19932. {
  19933. if(fullPage) {
  19934. scripts.push("jQuery(function($) {\n"+this.scripts[this.POS_READY].join("\n")+"\n});");
  19935. }
  19936. else {
  19937. scripts.push(this.scripts[this.POS_READY].join("\n"));
  19938. }
  19939. }
  19940. if(this.scripts[this.POS_LOAD] !== undefined)
  19941. {
  19942. if(fullPage) {
  19943. scripts.push("jQuery(window).load(function() {\n"+this.scripts[this.POS_LOAD].join("\n")+"\n});");
  19944. }
  19945. else {
  19946. scripts.push(this.scripts[this.POS_LOAD].join("\n"));
  19947. }
  19948. }
  19949. if(!php.empty(scripts)) {
  19950. html+=Yii.CHtml.script(scripts.join("\n"))+"\n";
  19951. }
  19952. if(fullPage) {
  19953. output=php.str_replace('<###end###>',html,output);
  19954. }
  19955. else {
  19956. output=output+html;
  19957. }
  19958. };
  19959. /**
  19960. * Returns the base URL of all core javascript files.
  19961. * If the base URL is not explicitly set, this method will publish the whole directory
  19962. * 'framework/web/js/source' and return the corresponding URL.
  19963. * @returns {String} the base URL of all core javascript files
  19964. */
  19965. Yii.CClientScript.prototype.getCoreScriptUrl = function () {
  19966. if(this._baseUrl!==null) {
  19967. return this._baseUrl;
  19968. }
  19969. else {
  19970. return (this._baseUrl=Yii.app().getAssetManager().publish(YII_PATH+'/web/js/source'));
  19971. }
  19972. };
  19973. /**
  19974. * Sets the base URL of all core javascript files.
  19975. * This setter is provided in case when core javascript files are manually published
  19976. * to a pre-specified location. This may save asset publishing time for large-scale applications.
  19977. * @param {String} value the base URL of all core javascript files.
  19978. */
  19979. Yii.CClientScript.prototype.setCoreScriptUrl = function (value) {
  19980. this._baseUrl=value;
  19981. };
  19982. /**
  19983. * Returns the base URL for a registered package with the specified name.
  19984. * If needed, this method may publish the assets of the package and returns the published base URL.
  19985. * @param {String} name the package name
  19986. * @returns {String} the base URL for the named package. False is returned if the package is not registered yet.
  19987. * @see registerPackage
  19988. * @since 1.1.8
  19989. */
  19990. Yii.CClientScript.prototype.getPackageBaseUrl = function (name) {
  19991. var packageVar, baseUrl;
  19992. if(this.coreScripts[name] === undefined) {
  19993. return false;
  19994. }
  19995. packageVar=this.coreScripts[name];
  19996. if(packageVar['baseUrl'] !== undefined)
  19997. {
  19998. baseUrl=packageVar['baseUrl'];
  19999. if(baseUrl==='' || baseUrl[0]!=='/' && php.strpos(baseUrl,'://')===false) {
  20000. baseUrl=Yii.app().getRequest().getBaseUrl()+'/'+baseUrl;
  20001. }
  20002. baseUrl=php.rtrim(baseUrl,'/');
  20003. }
  20004. else if(packageVar['basePath'] !== undefined) {
  20005. baseUrl=Yii.app().getAssetManager().publish(Yii.getPathOfAlias(packageVar['basePath']));
  20006. }
  20007. else {
  20008. baseUrl=this.getCoreScriptUrl();
  20009. }
  20010. return (this.coreScripts[name]['baseUrl']=baseUrl);
  20011. };
  20012. /**
  20013. * Registers a script package that is listed in {@link packages}.
  20014. * This method is the same as {@link registerCoreScript}.
  20015. * @param {String} name the name of the script package.
  20016. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20017. * @since 1.1.7
  20018. * @see renderCoreScript
  20019. */
  20020. Yii.CClientScript.prototype.registerPackage = function (name) {
  20021. return this.registerCoreScript(name);
  20022. };
  20023. /**
  20024. * Registers a script package that is listed in {@link packages}.
  20025. * @param {String} name the name of the script package.
  20026. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20027. * @see renderCoreScript
  20028. */
  20029. Yii.CClientScript.prototype.registerCoreScript = function (name) {
  20030. var packageVar, i, p, params;
  20031. if(this.coreScripts[name] !== undefined) {
  20032. return this;
  20033. }
  20034. if(this.packages[name] !== undefined) {
  20035. packageVar=this.packages[name];
  20036. }
  20037. else
  20038. {
  20039. if(this.corePackages===null) {
  20040. this.corePackages=require(YII_PATH+'/web/js/packages.php');
  20041. }
  20042. if(this.corePackages[name] !== undefined) {
  20043. packageVar=this.corePackages[name];
  20044. }
  20045. }
  20046. if(packageVar !== undefined)
  20047. {
  20048. if(!php.empty(packageVar['depends']))
  20049. {
  20050. for (i in packageVar['depends']) {
  20051. if (packageVar['depends'].hasOwnProperty(i)) {
  20052. p = packageVar['depends'][i];
  20053. this.registerCoreScript(p);
  20054. }
  20055. }
  20056. }
  20057. this.coreScripts[name]=packageVar;
  20058. this.hasScripts=true;
  20059. params=func_get_args();
  20060. this.recordCachingAction('clientScript','registerCoreScript',params);
  20061. }
  20062. return this;
  20063. };
  20064. /**
  20065. * Registers a CSS file
  20066. * @param {String} url URL of the CSS file
  20067. * @param {String} media media that the CSS file should be applied to. If empty, it means all media types.
  20068. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20069. */
  20070. Yii.CClientScript.prototype.registerCssFile = function (url, media) {
  20071. var params;
  20072. if (media === undefined) {
  20073. media = '';
  20074. }
  20075. this.hasScripts=true;
  20076. this.cssFiles[url]=media;
  20077. params=func_get_args();
  20078. this.recordCachingAction('clientScript','registerCssFile',params);
  20079. return this;
  20080. };
  20081. /**
  20082. * Registers a piece of CSS code.
  20083. * @param {String} id ID that uniquely identifies this piece of CSS code
  20084. * @param {String} css the CSS code
  20085. * @param {String} media media that the CSS code should be applied to. If empty, it means all media types.
  20086. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20087. */
  20088. Yii.CClientScript.prototype.registerCss = function (id, css, media) {
  20089. var params;
  20090. if (media === undefined) {
  20091. media = '';
  20092. }
  20093. this.hasScripts=true;
  20094. this.css[id]=[css,media];
  20095. params=func_get_args();
  20096. this.recordCachingAction('clientScript','registerCss',params);
  20097. return this;
  20098. };
  20099. /**
  20100. * Registers a javascript file.
  20101. * @param {String} url URL of the javascript file
  20102. * @param {Integer} position the position of the JavaScript code. Valid values include the following:
  20103. * <ul>
  20104. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  20105. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  20106. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  20107. * </ul>
  20108. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20109. */
  20110. Yii.CClientScript.prototype.registerScriptFile = function (url, position) {
  20111. var params;
  20112. if (position === undefined) {
  20113. position = 0;
  20114. }
  20115. this.hasScripts=true;
  20116. this.scriptFiles[position][url]=url;
  20117. params=func_get_args();
  20118. this.recordCachingAction('clientScript','registerScriptFile',params);
  20119. return this;
  20120. };
  20121. /**
  20122. * Registers a piece of javascript code.
  20123. * @param {String} id ID that uniquely identifies this piece of JavaScript code
  20124. * @param {String} script the javascript code
  20125. * @param {Integer} position the position of the JavaScript code. Valid values include the following:
  20126. * <ul>
  20127. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  20128. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  20129. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  20130. * <li>CClientScript::POS_LOAD : the script is inserted in the window.onload() function.</li>
  20131. * <li>CClientScript::POS_READY : the script is inserted in the jQuery's ready function.</li>
  20132. * </ul>
  20133. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20134. */
  20135. Yii.CClientScript.prototype.registerScript = function (id, script, position) {
  20136. var params;
  20137. if (position === undefined) {
  20138. position = 4;
  20139. }
  20140. this.hasScripts=true;
  20141. this.scripts[position][id]=script;
  20142. if(position===this.POS_READY || position===this.POS_LOAD) {
  20143. this.registerCoreScript('jquery');
  20144. }
  20145. params=func_get_args();
  20146. this.recordCachingAction('clientScript','registerScript',params);
  20147. return this;
  20148. };
  20149. /**
  20150. * Registers a meta tag that will be inserted in the head section (right before the title element) of the resulting page.
  20151. * @param {String} content content attribute of the meta tag
  20152. * @param {String} name name attribute of the meta tag. If null, the attribute will not be generated
  20153. * @param {String} httpEquiv http-equiv attribute of the meta tag. If null, the attribute will not be generated
  20154. * @param {Array} options other options in name-value pairs (e.g. 'scheme', 'lang')
  20155. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20156. * @since 1.0.1
  20157. */
  20158. Yii.CClientScript.prototype.registerMetaTag = function (content, name, httpEquiv, options) {
  20159. var params;
  20160. if (name === undefined) {
  20161. name = null;
  20162. }
  20163. if (httpEquiv === undefined) {
  20164. httpEquiv = null;
  20165. }
  20166. if (options === undefined) {
  20167. options = [];
  20168. }
  20169. this.hasScripts=true;
  20170. if(name!==null) {
  20171. options['name']=name;
  20172. }
  20173. if(httpEquiv!==null) {
  20174. options['http-equiv']=httpEquiv;
  20175. }
  20176. options['content']=content;
  20177. this.metaTags[serialize(options)]=options;
  20178. params=func_get_args();
  20179. this.recordCachingAction('clientScript','registerMetaTag',params);
  20180. return this;
  20181. };
  20182. /**
  20183. * Registers a link tag that will be inserted in the head section (right before the title element) of the resulting page.
  20184. * @param {String} relation rel attribute of the link tag. If null, the attribute will not be generated.
  20185. * @param {String} type type attribute of the link tag. If null, the attribute will not be generated.
  20186. * @param {String} href href attribute of the link tag. If null, the attribute will not be generated.
  20187. * @param {String} media media attribute of the link tag. If null, the attribute will not be generated.
  20188. * @param {Array} options other options in name-value pairs
  20189. * @returns {Yii.CClientScript} the CClientScript object itself (to support method chaining, available since version 1.1.5).
  20190. * @since 1.0.1
  20191. */
  20192. Yii.CClientScript.prototype.registerLinkTag = function (relation, type, href, media, options) {
  20193. var params;
  20194. if (relation === undefined) {
  20195. relation = null;
  20196. }
  20197. if (type === undefined) {
  20198. type = null;
  20199. }
  20200. if (href === undefined) {
  20201. href = null;
  20202. }
  20203. if (media === undefined) {
  20204. media = null;
  20205. }
  20206. if (options === undefined) {
  20207. options = [];
  20208. }
  20209. this.hasScripts=true;
  20210. if(relation!==null) {
  20211. options['rel']=relation;
  20212. }
  20213. if(type!==null) {
  20214. options['type']=type;
  20215. }
  20216. if(href!==null) {
  20217. options['href']=href;
  20218. }
  20219. if(media!==null) {
  20220. options['media']=media;
  20221. }
  20222. this.linkTags[serialize(options)]=options;
  20223. params=func_get_args();
  20224. this.recordCachingAction('clientScript','registerLinkTag',params);
  20225. return this;
  20226. };
  20227. /**
  20228. * Checks whether the CSS file has been registered.
  20229. * @param {String} url URL of the CSS file
  20230. * @returns {Boolean} whether the CSS file is already registered
  20231. */
  20232. Yii.CClientScript.prototype.isCssFileRegistered = function (url) {
  20233. return this.cssFiles[url] !== undefined;
  20234. };
  20235. /**
  20236. * Checks whether the CSS code has been registered.
  20237. * @param {String} id ID that uniquely identifies the CSS code
  20238. * @returns {Boolean} whether the CSS code is already registered
  20239. */
  20240. Yii.CClientScript.prototype.isCssRegistered = function (id) {
  20241. return this.css[id] !== undefined;
  20242. };
  20243. /**
  20244. * Checks whether the JavaScript file has been registered.
  20245. * @param {String} url URL of the javascript file
  20246. * @param {Integer} position the position of the JavaScript code. Valid values include the following:
  20247. * <ul>
  20248. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  20249. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  20250. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  20251. * </ul>
  20252. * @returns {Boolean} whether the javascript file is already registered
  20253. */
  20254. Yii.CClientScript.prototype.isScriptFileRegistered = function (url, position) {
  20255. if (position === undefined) {
  20256. position = 0;
  20257. }
  20258. return this.scriptFiles[position][url] !== undefined;
  20259. };
  20260. /**
  20261. * Checks whether the JavaScript code has been registered.
  20262. * @param {String} id ID that uniquely identifies the JavaScript code
  20263. * @param {Integer} position the position of the JavaScript code. Valid values include the following:
  20264. * <ul>
  20265. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  20266. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  20267. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  20268. * <li>CClientScript::POS_LOAD : the script is inserted in the window.onload() function.</li>
  20269. * <li>CClientScript::POS_READY : the script is inserted in the jQuery's ready function.</li>
  20270. * </ul>
  20271. * @returns {Boolean} whether the javascript code is already registered
  20272. */
  20273. Yii.CClientScript.prototype.isScriptRegistered = function (id, position) {
  20274. if (position === undefined) {
  20275. position = 4;
  20276. }
  20277. return this.scripts[position][id] !== undefined;
  20278. };
  20279. /**
  20280. * Records a method call when an output cache is in effect.
  20281. * This is a shortcut to Yii::app()->controller->recordCachingAction.
  20282. * In case when controller is absent, nothing is recorded.
  20283. * @param {String} context a property name of the controller. It refers to an object
  20284. * whose method is being called. If empty it means the controller itself.
  20285. * @param {String} method the method name
  20286. * @param {Array} params parameters passed to the method
  20287. * @see COutputCache
  20288. * @since 1.0.5
  20289. */
  20290. Yii.CClientScript.prototype.recordCachingAction = function (context, method, params) {
  20291. var controller;
  20292. if((controller=Yii.app().getController())!==null) {
  20293. controller.recordCachingAction(context,method,params);
  20294. }
  20295. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  20296. /**
  20297. * CController manages a set of actions which deal with the corresponding user requests.
  20298. *
  20299. * Through the actions, CController coordinates the data flow between models and views.
  20300. *
  20301. * When a user requests an action 'XYZ', CController will do one of the following:
  20302. * 1. Method-based action: call method 'actionXYZ' if it exists;
  20303. * 2. Class-based action: create an instance of class 'XYZ' if the class is found in the action class map
  20304. * (specified via {@link actions()}, and execute the action;
  20305. * 3. Call {@link missingAction()}, which by default will raise a 404 HTTP exception.
  20306. *
  20307. * If the user does not specify an action, CController will run the action specified by
  20308. * {@link defaultAction}, instead.
  20309. *
  20310. * CController may be configured to execute filters before and after running actions.
  20311. * Filters preprocess/postprocess the user request/response and may quit executing actions
  20312. * if needed. They are executed in the order they are specified. If during the execution,
  20313. * any of the filters returns true, the rest filters and the action will no longer get executed.
  20314. *
  20315. * Filters can be individual objects, or methods defined in the controller class.
  20316. * They are specified by overriding {@link filters()} method. The following is an example
  20317. * of the filter specification:
  20318. * <pre>
  20319. * {
  20320. * 'accessControl - login',
  20321. * 'ajaxOnly + search',
  20322. * {
  20323. * 'COutputCache + list',
  20324. * 'duration':300,
  20325. * },
  20326. * }
  20327. * </pre>
  20328. * The above example declares three filters: accessControl, ajaxOnly, COutputCache. The first two
  20329. * are method-based filters (defined in CController), which refer to filtering methods in the controller class;
  20330. * while the last refers to a object-based filter whose class is 'system.web.widgets.COutputCache' and
  20331. * the 'duration' property is initialized as 300 (s).
  20332. *
  20333. * For method-based filters, a method named 'filterXYZ($filterChain)' in the controller class
  20334. * will be executed, where 'XYZ' stands for the filter name as specified in {@link filters()}.
  20335. * Note, inside the filter method, you must call <code>$filterChain->run()</code> if the action should
  20336. * be executed. Otherwise, the filtering process would stop at this filter.
  20337. *
  20338. * Filters can be specified so that they are executed only when running certain actions.
  20339. * For method-based filters, this is done by using '+' and '-' operators in the filter specification.
  20340. * The '+' operator means the filter runs only when the specified actions are requested;
  20341. * while the '-' operator means the filter runs only when the requested action is not among those actions.
  20342. * For object-based filters, the '+' and '-' operators are following the class name.
  20343. *
  20344. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  20345. * @version $Id: CController.php 3137 2011-03-28 11:08:06Z mdomba $
  20346. * @package system.web
  20347. * @since 1.0
  20348. * @author Charles Pick
  20349. * @class
  20350. * @extends Yii.CBaseController
  20351. */
  20352. Yii.CController = function CController(id, module) {
  20353. if (id !== false) {
  20354. this.construct(id, module);
  20355. }
  20356. };
  20357. Yii.CController.prototype = new Yii.CBaseController();
  20358. Yii.CController.prototype.constructor = Yii.CController;
  20359. /**
  20360. * @const
  20361. */
  20362. Yii.CController.prototype.STATE_INPUT_NAME = 'YII_PAGE_STATE';
  20363. /**
  20364. * @var {Mixed} the name of the layout to be applied to this controller's views.
  20365. * Defaults to null, meaning the {@link CWebApplication::layout application layout}
  20366. * is used. If it is false, no layout will be applied.
  20367. * Since version 1.0.3, the {@link CWebModule::layout module layout} will be used
  20368. * if the controller belongs to a module and this layout property is null.
  20369. */
  20370. Yii.CController.prototype.layout = null;
  20371. /**
  20372. * @var {String} the name of the default action. Defaults to 'index'.
  20373. */
  20374. Yii.CController.prototype.defaultAction = 'index';
  20375. Yii.CController.prototype._id = null;
  20376. Yii.CController.prototype._action = null;
  20377. Yii.CController.prototype._pageTitle = null;
  20378. Yii.CController.prototype._cachingStack = null;
  20379. Yii.CController.prototype._clips = null;
  20380. Yii.CController.prototype._dynamicOutput = null;
  20381. Yii.CController.prototype._pageStates = null;
  20382. Yii.CController.prototype._module = null;
  20383. /**
  20384. * jQuery events to delegate for this controller.
  20385. * Array should be of the following format:
  20386. * <pre>
  20387. * [
  20388. * ['#selector a.someLink', 'click', function (e) { alert("clicked!")}],
  20389. * ['#selector form', 'submit', function (e) { alert('Submitted!'); e.preventDefault(); }]
  20390. * ]
  20391. * </pre>
  20392. * These events will be bound to their selectors when the controller is run
  20393. * @var Array
  20394. */
  20395. Yii.CController.prototype.delegates = [];
  20396. /**
  20397. * @param {String} id id of this controller
  20398. * @param {Yii.CWebModule} module the module that this controller belongs to. This parameter
  20399. * has been available since version 1.0.3.
  20400. */
  20401. Yii.CController.prototype.construct = function (id, module) {
  20402. if (module === undefined) {
  20403. module = null;
  20404. }
  20405. this._id=id;
  20406. this._module=module;
  20407. this.attachBehaviors(this.behaviors());
  20408. };
  20409. /**
  20410. * Initializes the controller.
  20411. * This method is called by the application before the controller starts to execute.
  20412. * You may override this method to perform the needed initialization for the controller.
  20413. * @since 1.0.1
  20414. */
  20415. Yii.CController.prototype.init = function () {
  20416. Yii.forEach(this.delegates, function(i, item) {
  20417. jQuery("body").undelegate(item[0], item[1]).delegate(item[0], item[1], item[2]);
  20418. });
  20419. };
  20420. /**
  20421. * Returns the filter configurations.
  20422. *
  20423. * By overriding this method, child classes can specify filters to be applied to actions.
  20424. *
  20425. * This method returns an array of filter specifications. Each array element specify a single filter.
  20426. *
  20427. * For a method-based filter (called inline filter), it is specified as 'FilterName[ +|- Action1, Action2, ...]',
  20428. * where the '+' ('-') operators describe which actions should be (should not be) applied with the filter.
  20429. *
  20430. * For a class-based filter, it is specified as an array like the following:
  20431. * <pre>
  20432. * {
  20433. * 'FilterClass[ +|- Action1, Action2, ...]',
  20434. * 'name1':'value1',
  20435. * 'name2':'value2',
  20436. * +++
  20437. * }
  20438. * </pre>
  20439. * where the name-value pairs will be used to initialize the properties of the filter.
  20440. *
  20441. * Note, in order to inherit filters defined in the parent class, a child class needs to
  20442. * merge the parent filters with child filters using functions like array_merge().
  20443. *
  20444. * @returns {Object} a list of filter configurations.
  20445. * @see CFilter
  20446. */
  20447. Yii.CController.prototype.filters = function () {
  20448. return {};
  20449. };
  20450. /**
  20451. * Returns a list of external action classes.
  20452. * Array keys are action IDs, and array values are the corresponding
  20453. * action class in dot syntax (e.g. 'edit'=>'application.controllers.article.EditArticle')
  20454. * or arrays representing the configuration of the actions, such as the following,
  20455. * <pre>
  20456. * return {
  20457. * 'action1':'path.to.Action1Class',
  20458. * 'action2':{
  20459. * 'class':'path.to.Action2Class',
  20460. * 'property1':'value1',
  20461. * 'property2':'value2',
  20462. * },
  20463. * };
  20464. * </pre>
  20465. * Derived classes may override this method to declare external actions.
  20466. *
  20467. * Note, in order to inherit actions defined in the parent class, a child class needs to
  20468. * merge the parent actions with child actions using functions like array_merge().
  20469. *
  20470. * Since version 1.0.1, you may import actions from an action provider
  20471. * (such as a widget, see {@link CWidget::actions}), like the following:
  20472. * <pre>
  20473. * return {
  20474. * +++other actions+++
  20475. * // import actions declared in ProviderClass::actions()
  20476. * // the action IDs will be prefixed with 'pro.'
  20477. * 'pro.':'path.to.ProviderClass',
  20478. * // similar as above except that the imported actions are
  20479. * // configured with the specified initial property values
  20480. * 'pro2.':{
  20481. * 'class':'path.to.ProviderClass',
  20482. * 'action1':{
  20483. * 'property1':'value1',
  20484. * },
  20485. * 'action2':{
  20486. * 'property2':'value2',
  20487. * },
  20488. * ),
  20489. * }
  20490. * </pre>
  20491. *
  20492. * In the above, we differentiate action providers from other action
  20493. * declarations by the array keys. For action providers, the array keys
  20494. * must contain a dot. As a result, an action ID 'pro2.action1' will
  20495. * be resolved as the 'action1' action declared in the 'ProviderClass'.
  20496. *
  20497. * @returns {Object} list of external action classes
  20498. * @see createAction
  20499. */
  20500. Yii.CController.prototype.actions = function () {
  20501. return {};
  20502. };
  20503. /**
  20504. * Returns a list of behaviors that this controller should behave as.
  20505. * The return value should be an array of behavior configurations indexed by
  20506. * behavior names. Each behavior configuration can be either a string specifying
  20507. * the behavior class or an array of the following structure:
  20508. * <pre>
  20509. * 'behaviorName':{
  20510. * 'class':'path.to.BehaviorClass',
  20511. * 'property1':'value1',
  20512. * 'property2':'value2',
  20513. * }
  20514. * </pre>
  20515. *
  20516. * Note, the behavior classes must implement {@link IBehavior} or extend from
  20517. * {@link CBehavior}. Behaviors declared in this method will be attached
  20518. * to the controller when it is instantiated.
  20519. *
  20520. * For more details about behaviors, see {@link CComponent}.
  20521. * @returns {Object} the behavior configurations (behavior name=>behavior configuration)
  20522. * @since 1.0.6
  20523. */
  20524. Yii.CController.prototype.behaviors = function () {
  20525. return {};
  20526. };
  20527. /**
  20528. * Returns the access rules for this controller.
  20529. * Override this method if you use the {@link filterAccessControl accessControl} filter.
  20530. * @returns {Array} list of access rules. See {@link CAccessControlFilter} for details about rule specification.
  20531. */
  20532. Yii.CController.prototype.accessRules = function () {
  20533. return [];
  20534. };
  20535. /**
  20536. * Runs the named action.
  20537. * Filters specified via {@link filters()} will be applied.
  20538. * @param {String} actionID action ID
  20539. * @throws {Yii.CHttpException} if the action does not exist or the action name is not proper.
  20540. * @see filters
  20541. * @see createAction
  20542. * @see runAction
  20543. */
  20544. Yii.CController.prototype.run = function (actionID) {
  20545. var action, parent;
  20546. if((action=this.createAction(actionID))!==null) {
  20547. if((parent=this.getModule())===null) {
  20548. parent=Yii.app();
  20549. }
  20550. if(parent.beforeControllerAction(this,action)) {
  20551. this.runActionWithFilters(action,this.filters());
  20552. parent.afterControllerAction(this,action);
  20553. }
  20554. }
  20555. else {
  20556. this.missingAction(actionID);
  20557. }
  20558. };
  20559. /**
  20560. * Runs an action with the specified filters.
  20561. * A filter chain will be created based on the specified filters
  20562. * and the action will be executed then.
  20563. * @param {Yii.CAction} action the action to be executed.
  20564. * @param {Array} filters list of filters to be applied to the action.
  20565. * @see filters
  20566. * @see createAction
  20567. * @see runAction
  20568. */
  20569. Yii.CController.prototype.runActionWithFilters = function (action, filters) {
  20570. var priorAction;
  20571. if(php.empty(filters)) {
  20572. this.runAction(action);
  20573. }
  20574. else
  20575. {
  20576. priorAction=this._action;
  20577. this._action=action;
  20578. Yii.CFilterChain.prototype.create(this,action,filters).run();
  20579. this._action=priorAction;
  20580. }
  20581. };
  20582. /**
  20583. * Runs the action after passing through all filters.
  20584. * This method is invoked by {@link runActionWithFilters} after all possible filters have been executed
  20585. * and the action starts to run.
  20586. * @param {Yii.CAction} action action to run
  20587. */
  20588. Yii.CController.prototype.runAction = function (action) {
  20589. this._action=action;
  20590. if(this.beforeAction(action)) {
  20591. if(action.runWithParams(this.getActionParams())===false) {
  20592. this.invalidActionParams(action);
  20593. }
  20594. else {
  20595. this.afterAction(action);
  20596. }
  20597. }
  20598. };
  20599. /**
  20600. * Returns the request parameters that will be used for action parameter binding.
  20601. * By default, this method will return $_GET. You may override this method if you
  20602. * want to use other request parameters (e.g. $_GET+$_POST).
  20603. * @returns {Array} the request parameters to be used for action parameter binding
  20604. * @since 1.1.7
  20605. */
  20606. Yii.CController.prototype.getActionParams = function () {
  20607. return Yii.app().getRequest().params;
  20608. };
  20609. /**
  20610. * This method is invoked when the request parameters do not satisfy the requirement of the specified action.
  20611. * The default implementation will throw a 400 HTTP exception.
  20612. * @param {Yii.CAction} action the action being executed
  20613. * @since 1.1.7
  20614. */
  20615. Yii.CController.prototype.invalidActionParams = function (action) {
  20616. throw new Yii.CHttpException(400,Yii.t('yii','Your request is invalid.'));
  20617. };
  20618. /**
  20619. * Postprocesses the output generated by {@link render()}.
  20620. * This method is invoked at the end of {@link render()} and {@link renderText()}.
  20621. * If there are registered client scripts, this method will insert them into the output
  20622. * at appropriate places. If there are dynamic contents, they will also be inserted.
  20623. * This method may also save the persistent page states in hidden fields of
  20624. * stateful forms in the page.
  20625. * @param {String} output the output generated by the current action
  20626. * @returns {String} the output that has been processed.
  20627. */
  20628. Yii.CController.prototype.processOutput = function (output) {
  20629. Yii.app().getClientScript().render(output);
  20630. // if using page caching, we should delay dynamic output replacement
  20631. if(this._dynamicOutput!==null && this.isCachingStackEmpty())
  20632. {
  20633. output=this.processDynamicOutput(output);
  20634. this._dynamicOutput=null;
  20635. }
  20636. if(this._pageStates===null) {
  20637. this._pageStates=this.loadPageStates();
  20638. }
  20639. if(!php.empty(this._pageStates)) {
  20640. output = this.savePageStates(this._pageStates,output);
  20641. }
  20642. return output;
  20643. };
  20644. /**
  20645. * Postprocesses the dynamic output.
  20646. * This method is internally used. Do not call this method directly.
  20647. * @param {String} output output to be processed
  20648. * @returns {String} the processed output
  20649. * @since 1.0.4
  20650. */
  20651. Yii.CController.prototype.processDynamicOutput = function (output) {
  20652. if(this._dynamicOutput) {
  20653. output=output.replace(/<###dynamic-(\d+)###>/,Yii.getFunction([this,'replaceDynamicOutput']));
  20654. }
  20655. return output;
  20656. };
  20657. /**
  20658. * Replaces the dynamic content placeholders with actual content.
  20659. * This is a callback function used internally.
  20660. * @param {Array} matches matches
  20661. * @returns {String} the replacement
  20662. * @see processOutput
  20663. */
  20664. Yii.CController.prototype.replaceDynamicOutput = function (matches) {
  20665. var content;
  20666. content=matches[0];
  20667. if(this._dynamicOutput[matches[1]] !== undefined) {
  20668. content=this._dynamicOutput[matches[1]];
  20669. this._dynamicOutput[matches[1]]=null;
  20670. }
  20671. return content;
  20672. };
  20673. /**
  20674. * Creates the action instance based on the action name.
  20675. * The action can be either an inline action or an object.
  20676. * The latter is created by looking up the action map specified in {@link actions}.
  20677. * @param {String} actionID ID of the action. If empty, the {@link defaultAction default action} will be used.
  20678. * @returns {Yii.CAction} the action instance, null if the action does not exist.
  20679. * @see actions
  20680. */
  20681. Yii.CController.prototype.createAction = function (actionID) {
  20682. var action;
  20683. if(actionID==='') {
  20684. actionID=this.defaultAction;
  20685. }
  20686. actionID = php.ucfirst(actionID);
  20687. if(php.method_exists(this,'action'+actionID) && php.strcasecmp(actionID,'s')) { // we have actions method
  20688. return new Yii.CInlineAction(this,actionID);
  20689. }
  20690. else {
  20691. action=this.createActionFromMap(this.actions(),actionID,actionID);
  20692. if(action!==null && action['run'] === undefined) {
  20693. throw new Yii.CException(Yii.t('yii', 'Action class {class} must implement the "run" method.', {'{class}':php.get_class(action)}));
  20694. }
  20695. return action;
  20696. }
  20697. };
  20698. /**
  20699. * Creates the action instance based on the action map.
  20700. * This method will check to see if the action ID appears in the given
  20701. * action map. If so, the corresponding configuration will be used to
  20702. * create the action instance.
  20703. * @param {Array} actionMap the action map
  20704. * @param {String} actionID the action ID that has its prefix stripped off
  20705. * @param {String} requestActionID the originally requested action ID
  20706. * @param {Array} config the action configuration that should be applied on top of the configuration specified in the map
  20707. * @returns {Yii.CAction} the action instance, null if the action does not exist.
  20708. * @since 1.0.1
  20709. */
  20710. Yii.CController.prototype.createActionFromMap = function (actionMap, actionID, requestActionID, config) {
  20711. var pos, baseConfig, prefix, provider, providerType, classVar, map;
  20712. actionID = php.lcfirst(actionID);
  20713. requestActionID = php.lcfirst(requestActionID);
  20714. if (config === undefined) {
  20715. config = [];
  20716. }
  20717. if((pos=php.strpos(actionID,'.'))===false && actionMap[actionID] !== undefined) {
  20718. baseConfig= typeof actionMap[actionID] === 'object' ? actionMap[actionID] : {'class':actionMap[actionID]};
  20719. return Yii.createComponent(php.empty(config)?baseConfig:php.array_merge(baseConfig,config),this,requestActionID);
  20720. }
  20721. else if(pos===false) {
  20722. return null;
  20723. }
  20724. // the action is defined in a provider
  20725. prefix=actionID.slice(0, pos+1);
  20726. if(actionMap[prefix] === undefined) {
  20727. return null;
  20728. }
  20729. actionID=String(actionID.slice(pos+1));
  20730. provider=actionMap[prefix];
  20731. if(typeof(provider) === 'string') {
  20732. providerType=provider;
  20733. }
  20734. else if(typeof provider === 'object' && provider['class'] !== undefined) {
  20735. providerType=provider['class'];
  20736. if(provider[actionID] !== undefined) {
  20737. if(typeof(provider[actionID]) === 'string') {
  20738. config=php.array_merge({'class':provider[actionID]},config);
  20739. }
  20740. else {
  20741. config=php.array_merge(provider[actionID],config);
  20742. }
  20743. }
  20744. }
  20745. else {
  20746. throw new Yii.CException(Yii.t('yii','Object configuration must be an array containing a "class" element.'));
  20747. }
  20748. classVar=Yii.imports(providerType,true);
  20749. map=php.call_user_func([classVar,'actions']);
  20750. return this.createActionFromMap(map,actionID,requestActionID,config);
  20751. };
  20752. /**
  20753. * Handles the request whose action is not recognized.
  20754. * This method is invoked when the controller cannot find the requested action.
  20755. * The default implementation simply throws an exception.
  20756. * @param {String} actionID the missing action name
  20757. * @throws {Yii.CHttpException} whenever this method is invoked
  20758. */
  20759. Yii.CController.prototype.missingAction = function (actionID) {
  20760. throw new Yii.CHttpException(404,Yii.t('yii','The system is unable to find the requested action "{action}".',
  20761. {'{action}':actionID===''?this.defaultAction:actionID}));
  20762. };
  20763. /**
  20764. * @returns {Yii.CAction} the action currently being executed, null if no active action.
  20765. */
  20766. Yii.CController.prototype.getAction = function () {
  20767. return this._action;
  20768. };
  20769. /**
  20770. * @param {Yii.CAction} value the action currently being executed.
  20771. */
  20772. Yii.CController.prototype.setAction = function (value) {
  20773. this._action=value;
  20774. };
  20775. /**
  20776. * @returns {String} ID of the controller
  20777. */
  20778. Yii.CController.prototype.getId = function () {
  20779. return this._id;
  20780. };
  20781. /**
  20782. * @returns {String} the controller ID that is prefixed with the module ID (if any).
  20783. * @since 1.0.3
  20784. */
  20785. Yii.CController.prototype.getUniqueId = function () {
  20786. return this._module ? this._module.getId()+'/'+this._id : this._id;
  20787. };
  20788. /**
  20789. * @returns {String} the route (module ID, controller ID and action ID) of the current request.
  20790. * @since 1.1.0
  20791. */
  20792. Yii.CController.prototype.getRoute = function () {
  20793. var action;
  20794. if((action=this.getAction())!==null) {
  20795. return this.getUniqueId()+'/'+action.getId();
  20796. }
  20797. else {
  20798. return this.getUniqueId();
  20799. }
  20800. };
  20801. /**
  20802. * @returns {Yii.CWebModule} the module that this controller belongs to. It returns null
  20803. * if the controller does not belong to any module
  20804. * @since 1.0.3
  20805. */
  20806. Yii.CController.prototype.getModule = function () {
  20807. return this._module;
  20808. };
  20809. /**
  20810. * Returns the directory containing view files for this controller.
  20811. * The default implementation returns 'protected/views/ControllerID'.
  20812. * Child classes may override this method to use customized view path.
  20813. * If the controller belongs to a module (since version 1.0.3), the default view path
  20814. * is the {@link CWebModule::getViewPath module view path} appended with the controller ID.
  20815. * @returns {String} the directory containing the view files for this controller. Defaults to 'protected/views/ControllerID'.
  20816. */
  20817. Yii.CController.prototype.getViewPath = function () {
  20818. var module;
  20819. if((module=this.getModule())===null) {
  20820. module=Yii.app();
  20821. }
  20822. return module.getViewPath()+'/'+this.getId();
  20823. };
  20824. /**
  20825. * Looks for the view file according to the given view name.
  20826. *
  20827. * When a theme is currently active, this method will call {@link CTheme::getViewFile} to determine
  20828. * which view file should be returned.
  20829. *
  20830. * Otherwise, this method will return the corresponding view file based on the following criteria:
  20831. * <ul>
  20832. * <li>absolute view within a module: the view name starts with a single slash '/'.
  20833. * In this case, the view will be searched for under the currently active module's view path.
  20834. * If there is no active module, the view will be searched for under the application's view path.</li>
  20835. * <li>absolute view within the application: the view name starts with double slashes '//'.
  20836. * In this case, the view will be searched for under the application's view path.
  20837. * This syntax has been available since version 1.1.3.</li>
  20838. * <li>aliased view: the view name contains dots and refers to a path alias.
  20839. * The view file is determined by calling {@link YiiBase::getPathOfAlias()}. Note that aliased views
  20840. * cannot be themed because they can refer to a view file located at arbitrary places.</li>
  20841. * <li>relative view: otherwise. Relative views will be searched for under the currently active
  20842. * controller's view path.</li>
  20843. * </ul>
  20844. *
  20845. * After the view file is identified, this method may further call {@link CApplication::findLocalizedFile}
  20846. * to find its localized version if internationalization is needed.
  20847. *
  20848. * @param {String} viewName view name
  20849. * @returns {String} the view file path, false if the view file does not exist
  20850. * @see resolveViewFile
  20851. * @see CApplication::findLocalizedFile
  20852. */
  20853. Yii.CController.prototype.getViewFile = function (viewName) {
  20854. var theme, viewFile, moduleViewPath, basePath, module;
  20855. if((theme=Yii.app().getTheme())!==null && (viewFile=theme.getViewFile(this,viewName))!==false) {
  20856. return viewFile;
  20857. }
  20858. moduleViewPath=basePath=Yii.app().getViewPath();
  20859. if((module=this.getModule())!==null) {
  20860. moduleViewPath=module.getViewPath();
  20861. }
  20862. return this.resolveViewFile(viewName,this.getViewPath(),basePath,moduleViewPath);
  20863. };
  20864. /**
  20865. * Looks for the layout view script based on the layout name.
  20866. *
  20867. * The layout name can be specified in one of the following ways:
  20868. *
  20869. * <ul>
  20870. * <li>layout is false: returns false, meaning no layout.</li>
  20871. * <li>layout is null: the currently active module's layout will be used. If there is no active module,
  20872. * the application's layout will be used.</li>
  20873. * <li>a regular view name.</li>
  20874. * </ul>
  20875. *
  20876. * The resolution of the view file based on the layout view is similar to that in {@link getViewFile}.
  20877. * In particular, the following rules are followed:
  20878. *
  20879. * Otherwise, this method will return the corresponding view file based on the following criteria:
  20880. * <ul>
  20881. * <li>When a theme is currently active, this method will call {@link CTheme::getLayoutFile} to determine
  20882. * which view file should be returned.</li>
  20883. * <li>absolute view within a module: the view name starts with a single slash '/'.
  20884. * In this case, the view will be searched for under the currently active module's view path.
  20885. * If there is no active module, the view will be searched for under the application's view path.</li>
  20886. * <li>absolute view within the application: the view name starts with double slashes '//'.
  20887. * In this case, the view will be searched for under the application's view path.
  20888. * This syntax has been available since version 1.1.3.</li>
  20889. * <li>aliased view: the view name contains dots and refers to a path alias.
  20890. * The view file is determined by calling {@link YiiBase::getPathOfAlias()}. Note that aliased views
  20891. * cannot be themed because they can refer to a view file located at arbitrary places.</li>
  20892. * <li>relative view: otherwise. Relative views will be searched for under the currently active
  20893. * module's layout path. In case when there is no active module, the view will be searched for
  20894. * under the application's layout path.</li>
  20895. * </ul>
  20896. *
  20897. * After the view file is identified, this method may further call {@link CApplication::findLocalizedFile}
  20898. * to find its localized version if internationalization is needed.
  20899. *
  20900. * @param {Mixed} layoutName layout name
  20901. * @returns {String} the view file for the layout. False if the view file cannot be found
  20902. */
  20903. Yii.CController.prototype.getLayoutFile = function (layoutName) {
  20904. var theme, layoutFile, module;
  20905. if(layoutName===false) {
  20906. return false;
  20907. }
  20908. if((theme=Yii.app().getTheme())!==null && (layoutFile=theme.getLayoutFile(this,layoutName))!==false) {
  20909. return layoutFile;
  20910. }
  20911. if(php.empty(layoutName)) {
  20912. module=this.getModule();
  20913. while(module!==null) {
  20914. if(module.layout===false) {
  20915. return false;
  20916. }
  20917. if(!php.empty(module.layout)) {
  20918. break;
  20919. }
  20920. module=module.getParentModule();
  20921. }
  20922. if(module===null) {
  20923. module=Yii.app();
  20924. }
  20925. layoutName=module.layout;
  20926. }
  20927. else if((module=this.getModule())===null) {
  20928. module=Yii.app();
  20929. }
  20930. return this.resolveViewFile(layoutName,module.getLayoutPath(),Yii.app().getViewPath(),module.getViewPath());
  20931. };
  20932. /**
  20933. * Finds a view file based on its name.
  20934. * The view name can be in one of the following formats:
  20935. * <ul>
  20936. * <li>absolute view within a module: the view name starts with a single slash '/'.
  20937. * In this case, the view will be searched for under the currently active module's view path.
  20938. * If there is no active module, the view will be searched for under the application's view path.</li>
  20939. * <li>absolute view within the application: the view name starts with double slashes '//'.
  20940. * In this case, the view will be searched for under the application's view path.
  20941. * This syntax has been available since version 1.1.3.</li>
  20942. * <li>aliased view: the view name contains dots and refers to a path alias.
  20943. * The view file is determined by calling {@link YiiBase::getPathOfAlias()}. Note that aliased views
  20944. * cannot be themed because they can refer to a view file located at arbitrary places.</li>
  20945. * <li>relative view: otherwise. Relative views will be searched for under the currently active
  20946. * controller's view path.</li>
  20947. * </ul>
  20948. * For absolute view and relative view, the corresponding view file is a PHP file
  20949. * whose name is the same as the view name. The file is located under a specified directory.
  20950. * This method will call {@link CApplication::findLocalizedFile} to search for a localized file, if any.
  20951. * @param {String} viewName the view name
  20952. * @param {String} viewPath the directory that is used to search for a relative view name
  20953. * @param {String} basePath the directory that is used to search for an absolute view name under the application
  20954. * @param {String} moduleViewPath the directory that is used to search for an absolute view name under the current module.
  20955. * If this is not set, the application base view path will be used.
  20956. * @returns {Mixed} the view file path. False if the view file does not exist.
  20957. * @since 1.0.3
  20958. */
  20959. Yii.CController.prototype.resolveViewFile = function (viewName, viewPath, basePath, moduleViewPath) {
  20960. var renderer, extension, viewFile;
  20961. if (moduleViewPath === undefined) {
  20962. moduleViewPath = null;
  20963. }
  20964. if(php.empty(viewName)) {
  20965. return false;
  20966. }
  20967. if(moduleViewPath===null) {
  20968. moduleViewPath=basePath;
  20969. }
  20970. extension='.js';
  20971. if(viewName[0]==='/') {
  20972. if(php.strncmp(viewName,'//',2)===0) {
  20973. viewFile=basePath+viewName.slice(1);
  20974. }
  20975. else {
  20976. viewFile=moduleViewPath+viewName;
  20977. }
  20978. }
  20979. else if(php.strpos(viewName,'.')) {
  20980. viewFile=Yii.getPathOfAlias(viewName);
  20981. }
  20982. else {
  20983. viewFile=viewPath+'/'+viewName;
  20984. }
  20985. return Yii.app().findLocalizedFile(viewFile+extension);
  20986. };
  20987. /**
  20988. * Returns the list of clips.
  20989. * A clip is a named piece of rendering result that can be
  20990. * inserted at different places.
  20991. * @returns {Yii.CMap} the list of clips
  20992. * @see CClipWidget
  20993. */
  20994. Yii.CController.prototype.getClips = function () {
  20995. if(this._clips!==null) {
  20996. return this._clips;
  20997. }
  20998. else {
  20999. return (this._clips=new Yii.CMap());
  21000. }
  21001. };
  21002. /**
  21003. * Processes the request using another controller action.
  21004. * This is like {@link redirect}, but the user browser's URL remains unchanged.
  21005. * In most cases, you should call {@link redirect} instead of this method.
  21006. * @param {String} route the route of the new controller action. This can be an action ID, or a complete route
  21007. * with module ID (optional in the current module), controller ID and action ID. If the former, the action is assumed
  21008. * to be located within the current controller.
  21009. * @param {Boolean} exit whether to end the application after this call. Defaults to true.
  21010. * @since 1.1.0
  21011. */
  21012. Yii.CController.prototype.forward = function (route, exit) {
  21013. var module;
  21014. if (exit === undefined) {
  21015. exit = true;
  21016. }
  21017. if(php.strpos(route,'/')===false) {
  21018. this.run(route);
  21019. }
  21020. else
  21021. {
  21022. if(route[0]!=='/' && (module=this.getModule())!==null) {
  21023. route=module.getId()+'/'+route;
  21024. }
  21025. Yii.app().runController(route);
  21026. }
  21027. if(exit) {
  21028. Yii.app().end();
  21029. }
  21030. };
  21031. /**
  21032. * Renders a view with a layout.
  21033. *
  21034. * This method first calls {@link renderPartial} to render the view (called content view).
  21035. * It then renders the layout view which may embed the content view at appropriate place.
  21036. * In the layout view, the content view rendering result can be accessed via variable
  21037. * <code>$content</code>. At the end, it calls {@link processOutput} to insert scripts
  21038. * and dynamic contents if they are available.
  21039. *
  21040. * By default, the layout view script is "protected/views/layouts/main.php".
  21041. * This may be customized by changing {@link layout}.
  21042. *
  21043. * @param {String} view name of the view to be rendered. See {@link getViewFile} for details
  21044. * about how the view script is resolved.
  21045. * @param {Array} data data to be extracted into PHP variables and made available to the view script
  21046. * @param {Boolean} returnVar whether the rendering result should be returned instead of being displayed to end users.
  21047. * @returns {String} the rendering result. Null if the rendering result is not required.
  21048. * @see renderPartial
  21049. * @see getLayoutFile
  21050. */
  21051. Yii.CController.prototype.render = function (viewAlias, data, callback) {
  21052. var viewFile, self = this;
  21053. if (data === undefined) {
  21054. data = null;
  21055. }
  21056. if((viewFile=this.getViewFile(viewAlias))!==false) {
  21057. return Yii.CView.prototype.load(viewFile, function (view) {
  21058. if (typeof data === "object") {
  21059. Yii.forEach(data, function (name, value) {
  21060. view[name] = value;
  21061. });
  21062. if (self.beforeRender(view)) {
  21063. view.render(function(html) {
  21064. self.afterRender(view, html);
  21065. return callback.apply(view, arguments);
  21066. });
  21067. }
  21068. }
  21069. });
  21070. }
  21071. else {
  21072. throw new Yii.CException(Yii.t('yii','{controller} cannot find the requested view "{view}".',
  21073. {'{controller}':php.get_class(this), '{view}':view}));
  21074. }
  21075. };
  21076. /**
  21077. * This method is invoked at the beginning of {@link render()}.
  21078. * You may override this method to do some preprocessing when rendering a view.
  21079. * @param {String} view the view to be rendered
  21080. * @returns {Boolean} whether the view should be rendered.
  21081. * @since 1.1.5
  21082. */
  21083. Yii.CController.prototype.beforeRender = function (view) {
  21084. return true;
  21085. };
  21086. /**
  21087. * This method is invoked after the specified is rendered by calling {@link render()}.
  21088. * Note that this method is invoked BEFORE {@link processOutput()}.
  21089. * You may override this method to do some postprocessing for the view rendering.
  21090. * @param {String} view the view that has been rendered
  21091. * @param {String} output the rendering result of the view. Note that this parameter is passed
  21092. * as a reference. That means you can modify it within this method.
  21093. * @since 1.1.5
  21094. */
  21095. Yii.CController.prototype.afterRender = function (view, output) {
  21096. };
  21097. /**
  21098. * Renders a static text string.
  21099. * The string will be inserted in the current controller layout and returned back.
  21100. * @param {String} text the static text string
  21101. * @param {Boolean} returnVar whether the rendering result should be returned instead of being displayed to end users.
  21102. * @returns {String} the rendering result. Null if the rendering result is not required.
  21103. * @see getLayoutFile
  21104. */
  21105. Yii.CController.prototype.renderText = function (text, returnVar) {
  21106. var layoutFile;
  21107. if (returnVar === undefined) {
  21108. returnVar = false;
  21109. }
  21110. if((layoutFile=this.getLayoutFile(this.layout))!==false) {
  21111. text=this.renderFile(layoutFile,{'content':text},true);
  21112. }
  21113. text=this.processOutput(text);
  21114. if(returnVar) {
  21115. return text;
  21116. }
  21117. else {
  21118. $("body").append(text);
  21119. }
  21120. };
  21121. /**
  21122. * Renders a view.
  21123. *
  21124. * The named view refers to a PHP script (resolved via {@link getViewFile})
  21125. * that is included by this method. If $data is an associative array,
  21126. * it will be extracted as PHP variables and made available to the script.
  21127. *
  21128. * This method differs from {@link render()} in that it does not
  21129. * apply a layout to the rendered result. It is thus mostly used
  21130. * in rendering a partial view, or an AJAX response.
  21131. *
  21132. * @param {String} view name of the view to be rendered. See {@link getViewFile} for details
  21133. * about how the view script is resolved.
  21134. * @param {Array} data data to be made available to the view
  21135. * @param {Function} callback The callback to execute with the rendering result
  21136. * @returns {String} the rendering result. Null if the rendering result is not required.
  21137. * @throws {Yii.CException} if the view does not exist
  21138. * @see getViewFile
  21139. * @see processOutput
  21140. * @see render
  21141. */
  21142. Yii.CController.prototype.renderPartial = function (viewAlias, data, callback) {
  21143. var viewFile;
  21144. if (data === undefined) {
  21145. data = null;
  21146. }
  21147. if((viewFile=this.getViewFile(viewAlias))!==false) {
  21148. return Yii.CView.prototype.load(viewFile, function (view) {
  21149. if (typeof data === "object") {
  21150. Yii.forEach(data, function (name, value) {
  21151. view[name] = value;
  21152. });
  21153. console.log(view);
  21154. view.renderPartial(callback);
  21155. }
  21156. });
  21157. return this.renderFile(viewFile,data,callback);
  21158. }
  21159. else {
  21160. throw new Yii.CException(Yii.t('yii','{controller} cannot find the requested view "{view}".',
  21161. {'{controller}':php.get_class(this), '{view}':view}));
  21162. }
  21163. };
  21164. /**
  21165. * Renders dynamic content returned by the specified callback.
  21166. * This method is used together with {@link COutputCache}. Dynamic contents
  21167. * will always show as their latest state even if the content surrounding them is being cached.
  21168. * This is especially useful when caching pages that are mostly static but contain some small
  21169. * dynamic regions, such as username or current time.
  21170. * We can use this method to render these dynamic regions to ensure they are always up-to-date.
  21171. *
  21172. * The first parameter to this method should be a valid PHP callback, while the rest parameters
  21173. * will be passed to the callback.
  21174. *
  21175. * Note, the callback and its parameter values will be serialized and saved in cache.
  21176. * Make sure they are serializable.
  21177. *
  21178. * @param {Yii.Callback} callback a PHP callback which returns the needed dynamic content.
  21179. * When the callback is specified as a string, it will be first assumed to be a method of the current
  21180. * controller class. If the method does not exist, it is assumed to be a global PHP function.
  21181. * Note, the callback should return the dynamic content instead of echoing it.
  21182. */
  21183. Yii.CController.prototype.renderDynamic = function (callback) {
  21184. var n, params;
  21185. n=php.count(this._dynamicOutput);
  21186. document.write("<###dynamic-n###>");
  21187. params=arguments;
  21188. php.array_shift(params);
  21189. this.renderDynamicInternal(callback,params);
  21190. };
  21191. /**
  21192. * This method is internally used.
  21193. * @param {Yii.Callback} callback a PHP callback which returns the needed dynamic content.
  21194. * @param {Array} params parameters passed to the PHP callback
  21195. * @see renderDynamic
  21196. */
  21197. Yii.CController.prototype.renderDynamicInternal = function (callback, params) {
  21198. this.recordCachingAction('','renderDynamicInternal',[callback,params]);
  21199. if(typeof(callback) === 'string' && php.method_exists(this,callback)) {
  21200. callback=[this,callback];
  21201. }
  21202. this._dynamicOutput.push(php.call_user_func_array(callback,params));
  21203. };
  21204. /**
  21205. * Creates a relative URL for the specified action defined in this controller.
  21206. * @param {String} route the URL route. This should be in the format of 'ControllerID/ActionID'.
  21207. * If the ControllerID is not present, the current controller ID will be prefixed to the route.
  21208. * If the route is empty, it is assumed to be the current action.
  21209. * Since version 1.0.3, if the controller belongs to a module, the {@link CWebModule::getId module ID}
  21210. * will be prefixed to the route. (If you do not want the module ID prefix, the route should start with a slash '/'.)
  21211. * @param {Array} params additional GET parameters (name=>value). Both the name and value will be URL-encoded.
  21212. * If the name is '#', the corresponding value will be treated as an anchor
  21213. * and will be appended at the end of the URL. This anchor feature has been available since version 1.0.1.
  21214. * @param {String} ampersand the token separating name-value pairs in the URL.
  21215. * @returns {String} the constructed URL
  21216. */
  21217. Yii.CController.prototype.createUrl = function (route, params, ampersand) {
  21218. var module;
  21219. if (params === undefined) {
  21220. params = [];
  21221. }
  21222. if (ampersand === undefined) {
  21223. ampersand = '&';
  21224. }
  21225. if(route==='') {
  21226. route=this.getId()+'/'+this.getAction().getId();
  21227. }
  21228. else if(php.strpos(route,'/')===false) {
  21229. route=this.getId()+'/'+route;
  21230. }
  21231. if(route[0]!=='/' && (module=this.getModule())!==null) {
  21232. route=module.getId()+'/'+route;
  21233. }
  21234. return Yii.app().createUrl(php.trim(route,'/'),params,ampersand);
  21235. };
  21236. /**
  21237. * Creates an absolute URL for the specified action defined in this controller.
  21238. * @param {String} route the URL route. This should be in the format of 'ControllerID/ActionID'.
  21239. * If the ControllerPath is not present, the current controller ID will be prefixed to the route.
  21240. * If the route is empty, it is assumed to be the current action.
  21241. * @param {Array} params additional GET parameters (name=>value). Both the name and value will be URL-encoded.
  21242. * @param {String} schema schema to use (e.g. http, https). If empty, the schema used for the current request will be used.
  21243. * @param {String} ampersand the token separating name-value pairs in the URL.
  21244. * @returns {String} the constructed URL
  21245. */
  21246. Yii.CController.prototype.createAbsoluteUrl = function (route, params, schema, ampersand) {
  21247. var url;
  21248. if (params === undefined) {
  21249. params = [];
  21250. }
  21251. if (schema === undefined) {
  21252. schema = '';
  21253. }
  21254. if (ampersand === undefined) {
  21255. ampersand = '&';
  21256. }
  21257. url=this.createUrl(route,params,ampersand);
  21258. if(php.strpos(url,'http')===0) {
  21259. return url;
  21260. }
  21261. else {
  21262. return Yii.app().getRequest().getHostInfo(schema)+url;
  21263. }
  21264. };
  21265. /**
  21266. * @returns {String} the page title. Defaults to the controller name and the action name.
  21267. */
  21268. Yii.CController.prototype.getPageTitle = function () {
  21269. var name;
  21270. if(this._pageTitle!==null) {
  21271. return this._pageTitle;
  21272. }
  21273. else {
  21274. name=php.ucfirst(php.basename(this.getId()));
  21275. if(this.getAction()!==null && php.strcasecmp(this.getAction().getId(),this.defaultAction)) {
  21276. return (this._pageTitle=Yii.app().name+' - '+php.ucfirst(this.getAction().getId())+' '+name);
  21277. }
  21278. else {
  21279. return (this._pageTitle=Yii.app().name+' - '+name);
  21280. }
  21281. }
  21282. };
  21283. /**
  21284. * @param {String} value the page title.
  21285. */
  21286. Yii.CController.prototype.setPageTitle = function (value) {
  21287. this._pageTitle=value;
  21288. document.title = value;
  21289. };
  21290. /**
  21291. * Redirects the browser to the specified URL or route (controller/action).
  21292. * @param {Mixed} url the URL to be redirected to. If the parameter is an array,
  21293. * the first element must be a route to a controller action and the rest
  21294. * are GET parameters in name-value pairs.
  21295. * @param {Boolean} terminate whether to terminate the current application after calling this method
  21296. * @param {Integer} statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html}
  21297. * for details about HTTP status code. This parameter has been available since version 1.0.4.
  21298. */
  21299. Yii.CController.prototype.redirect = function (url, terminate, statusCode) {
  21300. var route;
  21301. if (terminate === undefined) {
  21302. terminate = true;
  21303. }
  21304. if (statusCode === undefined) {
  21305. statusCode = 302;
  21306. }
  21307. if(Object.prototype.toString.call(url) === '[object Array]')
  21308. {
  21309. route=url[0] !== undefined ? url[0] : '';
  21310. url=this.createUrl(route,php.array_splice(url,1));
  21311. }
  21312. Yii.app().getRequest().redirect(url,terminate,statusCode);
  21313. };
  21314. /**
  21315. * Refreshes the current page.
  21316. * The effect of this method call is the same as user pressing the
  21317. * refresh button on the browser (without post data).
  21318. * @param {Boolean} terminate whether to terminate the current application after calling this method
  21319. * @param {String} anchor the anchor that should be appended to the redirection URL.
  21320. * Defaults to empty. Make sure the anchor starts with '#' if you want to specify it.
  21321. * The parameter has been available since version 1.0.7.
  21322. */
  21323. Yii.CController.prototype.refresh = function (terminate, anchor) {
  21324. if (terminate === undefined) {
  21325. terminate = true;
  21326. }
  21327. if (anchor === undefined) {
  21328. anchor = '';
  21329. }
  21330. this.redirect(Yii.app().getRequest().getUrl()+anchor,terminate);
  21331. };
  21332. /**
  21333. * Records a method call when an output cache is in effect.
  21334. * When the content is served from the output cache, the recorded
  21335. * method will be re-invoked.
  21336. * @param {String} context a property name of the controller. It refers to an object
  21337. * whose method is being called. If empty it means the controller itself.
  21338. * @param {String} method the method name
  21339. * @param {Array} params parameters passed to the method
  21340. * @see COutputCache
  21341. */
  21342. Yii.CController.prototype.recordCachingAction = function (context, method, params) {
  21343. var i, cache;
  21344. if(this._cachingStack) {// record only when there is an active output cache
  21345. for (i in this._cachingStack) {
  21346. if (this._cachingStack.hasOwnProperty(i)) {
  21347. cache = this._cachingStack[i];
  21348. cache.recordAction(context,method,params);
  21349. }
  21350. }
  21351. }
  21352. };
  21353. /**
  21354. * @param {Boolean} createIfNull whether to create a stack if it does not exist yet. Defaults to true.
  21355. * @returns {Yii.CStack} stack of {@link COutputCache} objects
  21356. */
  21357. Yii.CController.prototype.getCachingStack = function (createIfNull) {
  21358. if (createIfNull === undefined) {
  21359. createIfNull = true;
  21360. }
  21361. if(!this._cachingStack) {
  21362. this._cachingStack=new Yii.CStack();
  21363. }
  21364. return this._cachingStack;
  21365. };
  21366. /**
  21367. * Returns whether the caching stack is empty.
  21368. * @returns {Boolean} whether the caching stack is empty. If not empty, it means currently there are
  21369. * some output cache in effect. Note, the return result of this method may change when it is
  21370. * called in different output regions, depending on the partition of output caches.
  21371. * @since 1.0.5
  21372. */
  21373. Yii.CController.prototype.isCachingStackEmpty = function () {
  21374. return this._cachingStack===null || !this._cachingStack.getCount();
  21375. };
  21376. /**
  21377. * This method is invoked right before an action is to be executed (after all possible filters.)
  21378. * You may override this method to do last-minute preparation for the action.
  21379. * @param {Yii.CAction} action the action to be executed.
  21380. * @returns {Boolean} whether the action should be executed.
  21381. */
  21382. Yii.CController.prototype.beforeAction = function (action) {
  21383. return true;
  21384. };
  21385. /**
  21386. * This method is invoked right after an action is executed.
  21387. * You may override this method to do some postprocessing for the action.
  21388. * @param {Yii.CAction} action the action just executed.
  21389. */
  21390. Yii.CController.prototype.afterAction = function (action) {
  21391. };
  21392. /**
  21393. * The filter method for 'postOnly' filter.
  21394. * This filter reports an error if the applied action is receiving a non-POST request.
  21395. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  21396. * @throws {Yii.CHttpException} if the current request is not a POST request
  21397. */
  21398. Yii.CController.prototype.filterPostOnly = function (filterChain) {
  21399. if(Yii.app().getRequest().getIsPostRequest()) {
  21400. filterChain.run();
  21401. }
  21402. else {
  21403. throw new Yii.CHttpException(400,Yii.t('yii','Your request is not valid.'));
  21404. }
  21405. };
  21406. /**
  21407. * The filter method for 'ajaxOnly' filter.
  21408. * This filter reports an error if the applied action is receiving a non-AJAX request.
  21409. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  21410. * @throws {Yii.CHttpException} if the current request is not an AJAX request.
  21411. */
  21412. Yii.CController.prototype.filterAjaxOnly = function (filterChain) {
  21413. if(Yii.app().getRequest().getIsAjaxRequest()) {
  21414. filterChain.run();
  21415. }
  21416. else {
  21417. throw new Yii.CHttpException(400,Yii.t('yii','Your request is not valid.'));
  21418. }
  21419. };
  21420. /**
  21421. * The filter method for 'accessControl' filter.
  21422. * This filter is a wrapper of {@link CAccessControlFilter}.
  21423. * To use this filter, you must override {@link accessRules} method.
  21424. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  21425. */
  21426. Yii.CController.prototype.filterAccessControl = function (filterChain) {
  21427. var filter;
  21428. filter=new Yii.CAccessControlFilter();
  21429. filter.setRules(this.accessRules());
  21430. filter.filter(filterChain);
  21431. };
  21432. /**
  21433. * Returns a persistent page state value.
  21434. * A page state is a variable that is persistent across POST requests of the same page.
  21435. * In order to use persistent page states, the form(s) must be stateful
  21436. * which are generated using {@link CHtml::statefulForm}.
  21437. * @param {String} name the state name
  21438. * @param {Mixed} defaultValue the value to be returned if the named state is not found
  21439. * @returns {Mixed} the page state value
  21440. * @see setPageState
  21441. * @see CHtml::statefulForm
  21442. */
  21443. Yii.CController.prototype.getPageState = function (name, defaultValue) {
  21444. if (defaultValue === undefined) {
  21445. defaultValue = null;
  21446. }
  21447. if(this._pageStates===null) {
  21448. this._pageStates=this.loadPageStates();
  21449. }
  21450. return this._pageStates[name] !== undefined?this._pageStates[name]:defaultValue;
  21451. };
  21452. /**
  21453. * Saves a persistent page state value.
  21454. * A page state is a variable that is persistent across POST requests of the same page.
  21455. * In order to use persistent page states, the form(s) must be stateful
  21456. * which are generated using {@link CHtml::statefulForm}.
  21457. * @param {String} name the state name
  21458. * @param {Mixed} value the page state value
  21459. * @param {Mixed} defaultValue the default page state value. If this is the same as
  21460. * the given value, the state will be removed from persistent storage.
  21461. * @see getPageState
  21462. * @see CHtml::statefulForm
  21463. */
  21464. Yii.CController.prototype.setPageState = function (name, value, defaultValue) {
  21465. var params;
  21466. if (defaultValue === undefined) {
  21467. defaultValue = null;
  21468. }
  21469. if(this._pageStates===null) {
  21470. this._pageStates=this.loadPageStates();
  21471. }
  21472. if(value===defaultValue) {
  21473. delete this._pageStates[name];
  21474. }
  21475. else {
  21476. this._pageStates[name]=value;
  21477. }
  21478. params=arguments;
  21479. this.recordCachingAction('','setPageState',params);
  21480. };
  21481. /**
  21482. * Removes all page states.
  21483. */
  21484. Yii.CController.prototype.clearPageStates = function () {
  21485. this._pageStates=[];
  21486. };
  21487. /**
  21488. * Loads page states from a hidden input.
  21489. * @returns {Object} the loaded page states
  21490. */
  21491. Yii.CController.prototype.loadPageStates = function () {
  21492. return {};
  21493. };
  21494. /**
  21495. * Saves page states as a base64 string.
  21496. * @param {Array} states the states to be saved.
  21497. * @param {String} output the output to be modified.
  21498. * @returns {String} the modified output
  21499. */
  21500. Yii.CController.prototype.savePageStates = function (states, output) {
  21501. var data, value;
  21502. data=Yii.app().getSecurityManager().hashData(Yii.CJSON.encode(states));
  21503. value=php.base64_encode(data);
  21504. return php.str_replace(Yii.CHtml.pageStateField(''),Yii.CHtml.pageStateField(value),output);
  21505. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  21506. /**
  21507. * CFormModel represents a data model that collects HTML form inputs.
  21508. *
  21509. * Unlike {@link CActiveRecord}, the data collected by CFormModel are stored
  21510. * in memory only, instead of database.
  21511. *
  21512. * To collect user inputs, you may extend CFormModel and define the attributes
  21513. * whose values are to be collected from user inputs. You may override
  21514. * {@link rules()} to declare validation rules that should be applied to
  21515. * the attributes.
  21516. *
  21517. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  21518. * @version $Id: CFormModel.php 2799 2011-01-01 19:31:13Z qiang.xue $
  21519. * @package system.web
  21520. * @since 1.0
  21521. * @author Charles Pick
  21522. * @class
  21523. * @extends Yii.CModel
  21524. */
  21525. Yii.CFormModel = function CFormModel(scenario) {
  21526. if (scenario !== false) {
  21527. this.construct(scenario);
  21528. }
  21529. };
  21530. Yii.CFormModel.prototype = new Yii.CModel();
  21531. Yii.CFormModel.prototype.constructor = Yii.CFormModel;
  21532. Yii.CFormModel.prototype._names = null;
  21533. /**
  21534. * Constructor.
  21535. * @param {String} scenario name of the scenario that this model is used in.
  21536. * See {@link CModel::scenario} on how scenario is used by models.
  21537. * @see getScenario
  21538. */
  21539. Yii.CFormModel.prototype.construct = function (scenario) {
  21540. if (scenario === undefined) {
  21541. scenario = '';
  21542. }
  21543. this.setScenario(scenario);
  21544. this.init();
  21545. this.attachBehaviors(this.behaviors());
  21546. this.afterConstruct();
  21547. };
  21548. /**
  21549. * Initializes this model.
  21550. * This method is invoked in the constructor right after {@link scenario} is set.
  21551. * You may override this method to provide code that is needed to initialize the model (e.g. setting
  21552. * initial property values.)
  21553. * @since 1.0.8
  21554. */
  21555. Yii.CFormModel.prototype.init = function () {
  21556. };
  21557. /**
  21558. * Returns the list of attribute names.
  21559. * By default, this method returns all public properties of the class.
  21560. * You may override this method to change the default.
  21561. * @returns {Array} list of attribute names. Defaults to all public properties of the class.
  21562. */
  21563. Yii.CFormModel.prototype.attributeNames = function () {
  21564. var i;
  21565. if(this._names === null) {
  21566. this._names=[];
  21567. for (i in this) {
  21568. if (this.hasOwnProperty(i) && i.slice(0,1) !== "_") {
  21569. this._names.push(i);
  21570. }
  21571. }
  21572. return this._names;
  21573. }
  21574. else {
  21575. return this._names;
  21576. }
  21577. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  21578. /**
  21579. * CHttpRequest encapsulates the $_SERVER variable and resolves its inconsistency among different Web servers.
  21580. *
  21581. * CHttpRequest also manages the cookies sent from and sent to the user.
  21582. * By setting {@link enableCookieValidation} to true,
  21583. * cookies sent from the user will be validated to see if they are tampered.
  21584. * The property {@link getCookies cookies} returns the collection of cookies.
  21585. * For more details, see {@link CCookieCollection}.
  21586. *
  21587. * CHttpRequest is a default application component loaded by {@link CWebApplication}. It can be
  21588. * accessed via {@link CWebApplication::getRequest()}.
  21589. *
  21590. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  21591. * @version $Id: CHttpRequest.php 3050 2011-03-12 13:22:11Z qiang.xue $
  21592. * @package system.web
  21593. * @since 1.0
  21594. * @author Charles Pick
  21595. * @class
  21596. * @extends Yii.CApplicationComponent
  21597. */
  21598. Yii.CHttpRequest = function CHttpRequest () {
  21599. };
  21600. Yii.CHttpRequest.prototype = new Yii.CApplicationComponent();
  21601. Yii.CHttpRequest.prototype.constructor = Yii.CHttpRequest;
  21602. /**
  21603. * @var {Boolean} whether cookies should be validated to ensure they are not tampered. Defaults to false.
  21604. */
  21605. Yii.CHttpRequest.prototype.enableCookieValidation = false;
  21606. /**
  21607. * @var {Boolean} whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false.
  21608. * By setting this property to true, forms submitted to an Yii Web application must be originated
  21609. * from the same application. If not, a 400 HTTP exception will be raised.
  21610. * Note, this feature requires that the user client accepts cookie.
  21611. * You also need to use {@link CHtml::form} or {@link CHtml::statefulForm} to generate
  21612. * the needed HTML forms in your pages.
  21613. * @see http://seclab.stanford.edu/websec/csrf/csrf.pdf
  21614. */
  21615. Yii.CHttpRequest.prototype.enableCsrfValidation = false;
  21616. /**
  21617. * @var {String} the name of the token used to prevent CSRF. Defaults to 'YII_CSRF_TOKEN'.
  21618. * This property is effectively only when {@link enableCsrfValidation} is true.
  21619. */
  21620. Yii.CHttpRequest.prototype.csrfTokenName = 'YII_CSRF_TOKEN';
  21621. /**
  21622. * @var {Object} the property values (in name-value pairs) used to initialize the CSRF cookie.
  21623. * Any property of {@link CHttpCookie} may be initialized.
  21624. * This property is effective only when {@link enableCsrfValidation} is true.
  21625. */
  21626. Yii.CHttpRequest.prototype.csrfCookie = null;
  21627. /**
  21628. * @var {Object} a list of GET parameters for this URL
  21629. */
  21630. Yii.CHttpRequest.prototype.params = {};
  21631. Yii.CHttpRequest.prototype._requestUri = null;
  21632. Yii.CHttpRequest.prototype._pathInfo = null;
  21633. Yii.CHttpRequest.prototype._scriptFile = null;
  21634. Yii.CHttpRequest.prototype._scriptUrl = null;
  21635. Yii.CHttpRequest.prototype._hostInfo = null;
  21636. Yii.CHttpRequest.prototype._baseUrl = null;
  21637. Yii.CHttpRequest.prototype._cookies = null;
  21638. Yii.CHttpRequest.prototype._preferredLanguage = null;
  21639. Yii.CHttpRequest.prototype._csrfToken = null;
  21640. Yii.CHttpRequest.prototype._deleteParams = null;
  21641. Yii.CHttpRequest.prototype._putParams = null;
  21642. Yii.CHttpRequest.prototype._port = null;
  21643. Yii.CHttpRequest.prototype._securePort = null;
  21644. /**
  21645. * Initializes the application component.
  21646. * This method overrides the parent implementation by preprocessing
  21647. * the user request data.
  21648. */
  21649. Yii.CHttpRequest.prototype.init = function () {
  21650. Yii.CApplicationComponent.prototype.init.call(this);
  21651. this.normalizeRequest();
  21652. };
  21653. /**
  21654. * Normalizes the request data.
  21655. */
  21656. Yii.CHttpRequest.prototype.normalizeRequest = function () {
  21657. this.parseParams();
  21658. };
  21659. /**
  21660. * Returns the named GET parameter value. POST is not supported because JavaScript doesn't have access to it.
  21661. * If the GET parameter does not exist, the second parameter to this method will be returned.
  21662. * @param {String} name the GET parameter name
  21663. * @param {Mixed} defaultValue the default parameter value if the GET parameter does not exist.
  21664. * @returns {Mixed} the GET parameter value
  21665. * @since 1.0.4
  21666. * @see getQuery
  21667. */
  21668. Yii.CHttpRequest.prototype.getParam = function (name, defaultValue) {
  21669. if (this.params.hasOwnProperty(name)) {
  21670. return this.params[name];
  21671. }
  21672. return defaultValue;
  21673. };
  21674. /**
  21675. * Returns the named GET parameter value.
  21676. * If the GET parameter does not exist, the second parameter to this method will be returned.
  21677. * @param {String} name the GET parameter name
  21678. * @param {Mixed} defaultValue the default parameter value if the GET parameter does not exist.
  21679. * @returns {Mixed} the GET parameter value
  21680. * @since 1.0.4
  21681. * @see getPost
  21682. * @see getParam
  21683. */
  21684. Yii.CHttpRequest.prototype.getQuery = function (name, defaultValue) {
  21685. if (this.params.hasOwnProperty(name)) {
  21686. return this.params[name];
  21687. }
  21688. return defaultValue;
  21689. };
  21690. /**
  21691. * Parses the query string and adds the relevant GET variables to the list of parameters,
  21692. * @see CHttpRequest.params
  21693. * @returns {Object} The GET parameters key: value
  21694. */
  21695. Yii.CHttpRequest.prototype.parseParams = function () {
  21696. var i, limit, matches, key, value;
  21697. if (document.location.search.length === 0) {
  21698. return false;
  21699. }
  21700. matches = document.location.search.slice(1).split("&");
  21701. limit = matches.length;
  21702. for (i = 0; i < limit; i++) {
  21703. value = matches[i].split("=");
  21704. key = value.shift();
  21705. key = decodeURIComponent((key + '').replace(/\+/g, '%20'));
  21706. value = decodeURIComponent((value.join("=") + '').replace(/\+/g, '%20'));
  21707. this.params = this._setParamValue(key, value, this.params);
  21708. }
  21709. return this.params;
  21710. };
  21711. /**
  21712. * Sets / parses a GET parameter, do not call this function directly
  21713. * @see CHttpRequest.parseParams
  21714. * @private
  21715. *
  21716. * @param {String} key The key to set
  21717. * @param {mixed} value The value to set this key to
  21718. * @param {Object} params The list of parameters to modify
  21719. * @returns {Object} the modified list of parameters
  21720. */
  21721. Yii.CHttpRequest.prototype._setParamValue = function (key, value, params) {
  21722. var parts, firstItem, secondItem, i, limit = 0;
  21723. if (key.indexOf("[") === -1) {
  21724. params[key] = value;
  21725. return params;
  21726. }
  21727. parts = key.split("[");
  21728. firstItem = parts.shift();
  21729. if (firstItem.length === 0) {
  21730. for (i in params) {
  21731. if (params.hasOwnProperty(i)) {
  21732. limit++;
  21733. }
  21734. }
  21735. limit++;
  21736. params[limit] = value;
  21737. return params;
  21738. }
  21739. secondItem = parts.shift().split("]").shift();
  21740. if (secondItem.length === 0) {
  21741. limit = 0;
  21742. for (i in params) {
  21743. if (params.hasOwnProperty(i)) {
  21744. limit++;
  21745. }
  21746. }
  21747. limit++;
  21748. secondItem = limit;
  21749. }
  21750. if (parts.length > 0) {
  21751. parts = "[" + parts.join("[");
  21752. }
  21753. else {
  21754. parts = "";
  21755. }
  21756. if (params[firstItem] === undefined) {
  21757. params[firstItem] = {};
  21758. }
  21759. params[firstItem] = this._setParamValue(secondItem + parts, value, params[firstItem]);
  21760. return params;
  21761. };
  21762. /**
  21763. * Returns the currently requested URL.
  21764. * This is the same as {@link getRequestUri}.
  21765. * @returns {String} part of the request URL after the host info.
  21766. */
  21767. Yii.CHttpRequest.prototype.getUrl = function () {
  21768. return this.getRequestUri();
  21769. };
  21770. /**
  21771. * Returns the schema and host part of the application URL.
  21772. * The returned URL does not have an ending slash.
  21773. * By default this is determined based on the user request information.
  21774. * You may explicitly specify it by setting the {@link setHostInfo hostInfo} property.
  21775. * @param {String} schema schema to use (e.g. http, https). If empty, the schema used for the current request will be used.
  21776. * @returns {String} schema and hostname part (with port number if needed) of the request URL (e.g. http://www.yiiframework.com)
  21777. * @see setHostInfo
  21778. */
  21779. Yii.CHttpRequest.prototype.getHostInfo = function (schema) {
  21780. var secure, http, port, pos;
  21781. if (this._hostInfo === null) {
  21782. secure = this.getIsSecureConnection();
  21783. if (secure) {
  21784. http = "https";
  21785. }
  21786. else {
  21787. http = "http";
  21788. }
  21789. this._hostInfo = http + "://" + location.host;
  21790. }
  21791. if (schema !== undefined && schema !== null) {
  21792. secure = this.getIsSecureConnection();
  21793. if ((secure && schema === 'https') || (!secure && schema === 'http')) {
  21794. return this._hostInfo;
  21795. }
  21796. port = this.getPort();
  21797. if ((port !== 80 && schema === 'http') || (port !== 443 && schema === 'https')) {
  21798. port = ':' + port;
  21799. }
  21800. else {
  21801. port = '';
  21802. }
  21803. return this._hostInfo + port;
  21804. }
  21805. else {
  21806. return this._hostInfo;
  21807. }
  21808. };
  21809. /**
  21810. * Sets the schema and host part of the application URL.
  21811. * This setter is provided in case the schema and hostname cannot be determined
  21812. * on certain Web servers.
  21813. * @param {String} value the schema and host part of the application URL.
  21814. */
  21815. Yii.CHttpRequest.prototype.setHostInfo = function (value) {
  21816. this._hostInfo=php.rtrim(value,'/');
  21817. };
  21818. /**
  21819. * Returns the relative URL for the application.
  21820. * This is similar to {@link getScriptUrl scriptUrl} except that
  21821. * it does not have the script file name, and the ending slashes are stripped off.
  21822. * @param {Boolean} absolute whether to return an absolute URL. Defaults to false, meaning returning a relative one.
  21823. * This parameter has been available since 1.0.2.
  21824. * @returns {String} the relative URL for the application
  21825. * @see setScriptUrl
  21826. */
  21827. Yii.CHttpRequest.prototype.getBaseUrl = function (absolute) {
  21828. if (absolute === undefined) {
  21829. absolute = false;
  21830. }
  21831. if(this._baseUrl===null) {
  21832. this._baseUrl=php.rtrim(php.dirname(this.getScriptUrl()),'\\/');
  21833. }
  21834. return absolute ? this.getHostInfo() + this._baseUrl : this._baseUrl;
  21835. };
  21836. /**
  21837. * Sets the relative URL for the application.
  21838. * By default the URL is determined based on the entry script URL.
  21839. * This setter is provided in case you want to change this behavior.
  21840. * @param {String} value the relative URL for the application
  21841. */
  21842. Yii.CHttpRequest.prototype.setBaseUrl = function (value) {
  21843. this._baseUrl=value;
  21844. };
  21845. /**
  21846. * Returns the relative URL of the entry script.
  21847. * @returns {String} the relative URL of the entry script.
  21848. */
  21849. Yii.CHttpRequest.prototype.getScriptUrl = function () {
  21850. if(this._scriptUrl===null) {
  21851. this._scriptUrl = "";
  21852. }
  21853. return this._scriptUrl;
  21854. };
  21855. /**
  21856. * Sets the relative URL for the application entry script.
  21857. * This setter is provided in case the entry script URL cannot be determined
  21858. * on certain Web servers.
  21859. * @param {String} value the relative URL for the application entry script.
  21860. */
  21861. Yii.CHttpRequest.prototype.setScriptUrl = function (value) {
  21862. this._scriptUrl='/'+php.trim(value,'/');
  21863. };
  21864. /**
  21865. * Returns the path info of the currently requested URL.
  21866. * This refers to the part that is after the entry script and before the question mark.
  21867. * The starting and ending slashes are stripped off.
  21868. * @returns {String} part of the request URL that is after the entry script and before the question mark.
  21869. */
  21870. Yii.CHttpRequest.prototype.getPathInfo = function () {
  21871. if(this._pathInfo===null) {
  21872. this._pathInfo = location.pathname;
  21873. if (this._pathInfo.slice(0, 1) === "/") {
  21874. this._pathInfo = this._pathInfo.slice(1);
  21875. }
  21876. if (this._pathInfo.slice(-1) === "/") {
  21877. this._pathInfo = this._pathInfo.slice(0, -1);
  21878. }
  21879. }
  21880. return this._pathInfo;
  21881. };
  21882. /**
  21883. * Returns the request URI portion for the currently requested URL.
  21884. * This refers to the portion that is after the {@link hostInfo host info} part.
  21885. * It includes the {@link queryString query string} part if any.
  21886. * The implementation of this method referenced Zend_Controller_Request_Http in Zend Framework.
  21887. * @returns {String} the request URI portion for the currently requested URL.
  21888. * @throws {Yii.CException} if the request URI cannot be determined due to improper server configuration
  21889. * @since 1.0.1
  21890. */
  21891. Yii.CHttpRequest.prototype.getRequestUri = function () {
  21892. if (this._requestUri === null) {
  21893. this._requestUri = document.location.pathname + document.location.search;
  21894. }
  21895. return this._requestUri;
  21896. };
  21897. /**
  21898. * Returns part of the request URL that is after the question mark.
  21899. * @returns {String} part of the request URL that is after the question mark
  21900. */
  21901. Yii.CHttpRequest.prototype.getQueryString = function () {
  21902. return location.search.length === 0 ? '' : location.search.slice(1);
  21903. };
  21904. /**
  21905. * Return if the request is sent via secure channel (https).
  21906. * @returns {Boolean} if the request is sent via secure channel (https)
  21907. */
  21908. Yii.CHttpRequest.prototype.getIsSecureConnection = function () {
  21909. return location.protocol === "https:";
  21910. };
  21911. /**
  21912. * Returns the request type. Always GET in this version.
  21913. * @returns {String} request type, such as GET, POST, HEAD, PUT, DELETE.
  21914. */
  21915. Yii.CHttpRequest.prototype.getRequestType = function () {
  21916. return "GET";
  21917. };
  21918. /**
  21919. * Returns the server name.
  21920. * @returns {String} server name
  21921. */
  21922. Yii.CHttpRequest.prototype.getServerName = function () {
  21923. return location.host;
  21924. };
  21925. /**
  21926. * Returns the server port number.
  21927. * @returns {Integer} server port number
  21928. */
  21929. Yii.CHttpRequest.prototype.getServerPort = function () {
  21930. return location.port;
  21931. };
  21932. /**
  21933. * Returns the URL referrer, null if not present
  21934. * @returns {String} URL referrer, null if not present
  21935. */
  21936. Yii.CHttpRequest.prototype.getUrlReferrer = function () {
  21937. return document.referrer !== "" ? document.referrer :null;
  21938. };
  21939. /**
  21940. * Returns the user agent, null if not present.
  21941. * @returns {String} user agent, null if not present
  21942. */
  21943. Yii.CHttpRequest.prototype.getUserAgent = function () {
  21944. return navigator.userAgent !== undefined && navigator.userAgent !== ''? navigator.userAgent : null;
  21945. };
  21946. /**
  21947. * Doesn't return the user IP address because it's impossible without a server side call
  21948. * @returns {String} user IP address
  21949. */
  21950. Yii.CHttpRequest.prototype.getUserHostAddress = function () {
  21951. return null;
  21952. };
  21953. /**
  21954. * Returns the user host name, null if it cannot be determined.
  21955. * @returns {String} user host name, null if cannot be determined
  21956. */
  21957. Yii.CHttpRequest.prototype.getUserHost = function () {
  21958. return null;
  21959. };
  21960. /**
  21961. * Returns entry script file path.
  21962. * @returns {String} entry script file path (processed w/ realpath())
  21963. */
  21964. Yii.CHttpRequest.prototype.getScriptFile = function () {
  21965. if(this._scriptFile!==null) {
  21966. return this._scriptFile;
  21967. }
  21968. else {
  21969. return (this._scriptFile="/");
  21970. }
  21971. };
  21972. /**
  21973. * Returns user browser accept types, null if not present.
  21974. * @returns {String} user browser accept types, null if not present
  21975. */
  21976. Yii.CHttpRequest.prototype.getAcceptTypes = function () {
  21977. return null;
  21978. };
  21979. /**
  21980. * Returns the port to use for insecure requests.
  21981. * Defaults to 80, or the port specified by the server if the current
  21982. * request is insecure.
  21983. * You may explicitly specify it by setting the {@link setPort port} property.
  21984. * @returns {Integer} port number for insecure requests.
  21985. * @see setPort
  21986. * @since 1.1.3
  21987. */
  21988. Yii.CHttpRequest.prototype.getPort = function () {
  21989. if(this._port===null) {
  21990. if (location.port === '') {
  21991. if (this.getIsSecureConnection()) {
  21992. this._port = 443;
  21993. }
  21994. else {
  21995. this._port = 80;
  21996. }
  21997. }
  21998. }
  21999. return this._port;
  22000. };
  22001. /**
  22002. * Sets the port to use for insecure requests.
  22003. * This setter is provided in case a custom port is necessary for certain
  22004. * server configurations.
  22005. * @param {Integer} value port number.
  22006. * @since 1.1.3
  22007. */
  22008. Yii.CHttpRequest.prototype.setPort = function (value) {
  22009. this._port=Number(value);
  22010. this._hostInfo=null;
  22011. };
  22012. /**
  22013. * Returns the port to use for secure requests.
  22014. * Defaults to 443, or the port specified by the server if the current
  22015. * request is secure.
  22016. * You may explicitly specify it by setting the {@link setSecurePort securePort} property.
  22017. * @returns {Integer} port number for secure requests.
  22018. * @see setSecurePort
  22019. * @since 1.1.3
  22020. */
  22021. Yii.CHttpRequest.prototype.getSecurePort = function () {
  22022. if(this._securePort===null) {
  22023. this._securePort=this.getIsSecureConnection() && location.port !== '' ? Number(location.port) : 443;
  22024. }
  22025. return this._securePort;
  22026. };
  22027. /**
  22028. * Sets the port to use for secure requests.
  22029. * This setter is provided in case a custom port is necessary for certain
  22030. * server configurations.
  22031. * @param {Integer} value port number.
  22032. * @since 1.1.3
  22033. */
  22034. Yii.CHttpRequest.prototype.setSecurePort = function (value) {
  22035. this._securePort=Number(value);
  22036. this._hostInfo=null;
  22037. };
  22038. /**
  22039. * Returns the cookie collection.
  22040. * The result can be used like an associative array. Adding {@link CHttpCookie} objects
  22041. * to the collection will send the cookies to the client; and removing the objects
  22042. * from the collection will delete those cookies on the client.
  22043. * @returns {Yii.CCookieCollection} the cookie collection.
  22044. */
  22045. Yii.CHttpRequest.prototype.getCookies = function () {
  22046. if(this._cookies!==null) {
  22047. return this._cookies;
  22048. }
  22049. else {
  22050. return (this._cookies=new Yii.CCookieCollection(this));
  22051. }
  22052. };
  22053. /**
  22054. * Redirects the browser to the specified URL.
  22055. * @param {String} url URL to be redirected to. If the URL is a relative one, the base URL of
  22056. * the application will be inserted at the beginning.
  22057. * @param {Boolean} terminate whether to terminate the current application
  22058. * @param {Integer} statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html}
  22059. * for details about HTTP status code. This parameter has been available since version 1.0.4.
  22060. */
  22061. Yii.CHttpRequest.prototype.redirect = function (url, terminate, statusCode) {
  22062. if (terminate === undefined) {
  22063. terminate = true;
  22064. }
  22065. if (statusCode === undefined) {
  22066. statusCode = 302;
  22067. }
  22068. if(php.strpos(url,'/')===0) {
  22069. url=this.getHostInfo()+url;
  22070. }
  22071. document.location = url;
  22072. if(terminate) {
  22073. Yii.app().end();
  22074. }
  22075. };
  22076. /**
  22077. * Returns the user preferred language.
  22078. * The returned language ID will be canonicalized using {@link CLocale::getCanonicalID}.
  22079. * This method returns false if the user does not have language preference.
  22080. * @returns {String} the user preferred language.
  22081. */
  22082. Yii.CHttpRequest.prototype.getPreferredLanguage = function () {
  22083. if(this._preferredLanguage===null) {
  22084. return (this._preferredLanguage=Yii.CLocale.getCanonicalID(navigator.language));
  22085. }
  22086. return this._preferredLanguage;
  22087. };
  22088. /**
  22089. * Returns the random token used to perform CSRF validation.
  22090. * The token will be read from cookie first. If not found, a new token
  22091. * will be generated.
  22092. * @returns {String} the random token for CSRF validation.
  22093. * @see enableCsrfValidation
  22094. */
  22095. Yii.CHttpRequest.prototype.getCsrfToken = function () {
  22096. return this._csrfToken;
  22097. };
  22098. /**
  22099. * Determine whether this is an AJAX request, always false.
  22100. * @returns {Boolean} false
  22101. */
  22102. Yii.CHttpRequest.prototype.getIsAjaxRequest = function () {
  22103. return false;
  22104. };
  22105. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  22106. /**
  22107. * CLayoutView is a base class for layouts
  22108. *
  22109. * @package system.web
  22110. * @since 1.0
  22111. * @author Charles Pick
  22112. * @class
  22113. * @extends Yii.CComponent
  22114. */
  22115. Yii.CLayoutView = function CLayoutView (config) {
  22116. if (config !== false) {
  22117. this.template = null;
  22118. this.construct(config);
  22119. }
  22120. };
  22121. Yii.CLayoutView.prototype = new Yii.CView(false);
  22122. Yii.CLayoutView.prototype.constructor = Yii.CLayoutView;
  22123. /**
  22124. * The content to render
  22125. * @var String
  22126. */
  22127. Yii.CLayoutView.prototype.content = "";
  22128. /**
  22129. * The template to render
  22130. * @var String
  22131. */
  22132. Yii.CLayoutView.prototype.templateURL = "application.views.layouts.main";
  22133. /**
  22134. * Gets the page title
  22135. * @returns {String} The page title
  22136. */
  22137. Yii.CLayoutView.prototype.pageTitle = function () {
  22138. return Yii.app().getController().getPageTitle();
  22139. };
  22140. /**
  22141. * Displays the breadcrumbs
  22142. * @returns {String} The html for the main menu
  22143. */
  22144. Yii.CLayoutView.prototype.breadcrumbs = function () {
  22145. var crumbs, links;
  22146. if (Yii.app().getController().breadcrumbs !== undefined) {
  22147. links = Yii.app().getController().breadcrumbs;
  22148. if (links.length === 0) {
  22149. return "";
  22150. }
  22151. crumbs = new Yii.CBreadcrumbs;
  22152. crumbs.links = links;
  22153. return crumbs.run();
  22154. }
  22155. return "";
  22156. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  22157. /**
  22158. * CUrlManager manages the URLs of Yii Web applications.
  22159. *
  22160. * It provides URL construction ({@link createUrl()}) as well as parsing ({@link parseUrl()}) functionality.
  22161. *
  22162. * URLs managed via CUrlManager can be in one of the following two formats,
  22163. * by setting {@link setUrlFormat urlFormat} property:
  22164. * <ul>
  22165. * <li>'path' format: /path/to/EntryScript.php/name1/value1/name2/value2...</li>
  22166. * <li>'get' format: /path/to/EntryScript.php?name1=value1&name2=value2...</li>
  22167. * </ul>
  22168. *
  22169. * When using 'path' format, CUrlManager uses a set of {@link setRules rules} to:
  22170. * <ul>
  22171. * <li>parse the requested URL into a route ('ControllerID/ActionID') and GET parameters;</li>
  22172. * <li>create URLs based on the given route and GET parameters.</li>
  22173. * </ul>
  22174. *
  22175. * A rule consists of a route and a pattern. The latter is used by CUrlManager to determine
  22176. * which rule is used for parsing/creating URLs. A pattern is meant to match the path info
  22177. * part of a URL. It may contain named parameters using the syntax '&lt;ParamName:RegExp&gt;'.
  22178. *
  22179. * When parsing a URL, a matching rule will extract the named parameters from the path info
  22180. * and put them into the Yii.app().getRequest.params variable; when creating a URL, a matching rule will extract
  22181. * the named parameters from Yii.app().getRequest.params and put them into the path info part of the created URL.
  22182. *
  22183. * If a pattern ends with '/ *', it means additional GET parameters may be appended to the path
  22184. * info part of the URL; otherwise, the GET parameters can only appear in the query string part.
  22185. *
  22186. * To specify URL rules, set the {@link setRules rules} property as an array of rules (pattern=>route).
  22187. * For example,
  22188. * <pre>
  22189. * {
  22190. * 'articles':'article/list',
  22191. * 'article/<id:\d+>/ *':'article/read',
  22192. * }
  22193. * </pre>
  22194. * Two rules are specified in the above:
  22195. * <ul>
  22196. * <li>The first rule says that if the user requests the URL '/path/to/index.php/articles',
  22197. * it should be treated as '/path/to/index.php/article/list'; and vice versa applies
  22198. * when constructing such a URL.</li>
  22199. * <li>The second rule contains a named parameter 'id' which is specified using
  22200. * the &lt;ParamName:RegExp&gt; syntax. It says that if the user requests the URL
  22201. * '/path/to/index.php/article/13', it should be treated as '/path/to/index.php/article/read?id=13';
  22202. * and vice versa applies when constructing such a URL.</li>
  22203. * </ul>
  22204. *
  22205. * Starting from version 1.0.5, the route part may contain references to named parameters defined
  22206. * in the pattern part. This allows a rule to be applied to different routes based on matching criteria.
  22207. * For example,
  22208. * <pre>
  22209. * {
  22210. * '<_c:(post|comment)>/<id:\d+>/<_a:(create|update|delete)>':'<_c>/<_a>',
  22211. * '<_c:(post|comment)>/<id:\d+>':'<_c>/view',
  22212. * '<_c:(post|comment)>s/ *':'<_c>/list',
  22213. * }
  22214. * </pre>
  22215. * In the above, we use two named parameters '<_c>' and '<_a>' in the route part. The '<_c>'
  22216. * parameter matches either 'post' or 'comment', while the '<_a>' parameter matches an action ID.
  22217. *
  22218. * Like normal rules, these rules can be used for both parsing and creating URLs.
  22219. * For example, using the rules above, the URL '/index.php/post/123/create'
  22220. * would be parsed as the route 'post/create' with GET parameter 'id' being 123.
  22221. * And given the route 'post/list' and GET parameter 'page' being 2, we should get a URL
  22222. * '/index.php/posts/page/2'.
  22223. *
  22224. * Starting from version 1.0.11, it is also possible to include hostname into the rules
  22225. * for parsing and creating URLs. One may extract part of the hostname to be a GET parameter.
  22226. * For example, the URL <code>http://admin.example.com/en/profile</code> may be parsed into GET parameters
  22227. * <code>user=admin</code> and <code>lang=en</code>. On the other hand, rules with hostname may also be used to
  22228. * create URLs with parameterized hostnames.
  22229. *
  22230. * In order to use parameterized hostnames, simply declare URL rules with host info, e.g.:
  22231. * <pre>
  22232. * {
  22233. * 'http://<user:\w+>.example.com/<lang:\w+>/profile' : 'user/profile',
  22234. * }
  22235. * </pre>
  22236. *
  22237. * CUrlManager is a default application component that may be accessed via
  22238. * {@link CWebApplication::getUrlManager()}.
  22239. *
  22240. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  22241. * @version $Id: CUrlManager.php 3165 2011-04-06 08:27:40Z mdomba $
  22242. * @package system.web
  22243. * @since 1.0
  22244. * @author Charles Pick
  22245. * @class
  22246. * @extends Yii.CApplicationComponent
  22247. */
  22248. Yii.CUrlManager = function CUrlManager () {
  22249. };
  22250. Yii.CUrlManager.prototype = new Yii.CApplicationComponent();
  22251. Yii.CUrlManager.prototype.constructor = Yii.CUrlManager;
  22252. /**
  22253. * @const
  22254. */
  22255. Yii.CUrlManager.prototype.CACHE_KEY = 'Yii.CUrlManager.rules';
  22256. /**
  22257. * @const
  22258. */
  22259. Yii.CUrlManager.prototype.GET_FORMAT = 'get';
  22260. /**
  22261. * @const
  22262. */
  22263. Yii.CUrlManager.prototype.PATH_FORMAT = 'path';
  22264. /**
  22265. * @var {Array} an array of url rule configurations
  22266. */
  22267. Yii.CUrlManager.prototype.rules = [];
  22268. /**
  22269. * @var {String} the URL suffix used when in 'path' format.
  22270. * For example, ".html" can be used so that the URL looks like pointing to a static HTML page. Defaults to empty.
  22271. */
  22272. Yii.CUrlManager.prototype.urlSuffix = '';
  22273. /**
  22274. * @var {Boolean} whether to show entry script name in the constructed URL. Defaults to true.
  22275. */
  22276. Yii.CUrlManager.prototype.showScriptName = true;
  22277. /**
  22278. * @var {Boolean} whether to append GET parameters to the path info part. Defaults to true.
  22279. * This property is only effective when {@link urlFormat} is 'path' and is mainly used when
  22280. * creating URLs. When it is true, GET parameters will be appended to the path info and
  22281. * separate from each other using slashes. If this is false, GET parameters will be in query part.
  22282. * @since 1.0.3
  22283. */
  22284. Yii.CUrlManager.prototype.appendParams = true;
  22285. /**
  22286. * @var {String} the GET variable name for route. Defaults to 'r'.
  22287. */
  22288. Yii.CUrlManager.prototype.routeVar = 'r';
  22289. /**
  22290. * @var {Boolean} whether routes are case-sensitive. Defaults to true. By setting this to false,
  22291. * the route in the incoming request will be turned to lower case first before further processing.
  22292. * As a result, you should follow the convention that you use lower case when specifying
  22293. * controller mapping ({@link CWebApplication::controllerMap}) and action mapping
  22294. * ({@link CController::actions}). Also, the directory names for organizing controllers should
  22295. * be in lower case.
  22296. * @since 1.0.1
  22297. */
  22298. Yii.CUrlManager.prototype.caseSensitive = true;
  22299. /**
  22300. * @var {Boolean} whether the GET parameter values should match the corresponding
  22301. * sub-patterns in a rule before using it to create a URL. Defaults to false, meaning
  22302. * a rule will be used for creating a URL only if its route and parameter names match the given ones.
  22303. * If this property is set true, then the given parameter values must also match the corresponding
  22304. * parameter sub-patterns. Note that setting this property to true will degrade performance.
  22305. * @since 1.1.0
  22306. */
  22307. Yii.CUrlManager.prototype.matchValue = false;
  22308. /**
  22309. * @var {String} the ID of the cache application component that is used to cache the parsed URL rules.
  22310. * Defaults to 'cache' which refers to the primary cache application component.
  22311. * Set this property to false if you want to disable caching URL rules.
  22312. * @since 1.0.3
  22313. */
  22314. Yii.CUrlManager.prototype.cacheID = 'cache';
  22315. /**
  22316. * @var {Boolean} whether to enable strict URL parsing.
  22317. * This property is only effective when {@link urlFormat} is 'path'.
  22318. * If it is set true, then an incoming URL must match one of the {@link rules URL rules}.
  22319. * Otherwise, it will be treated as an invalid request and trigger a 404 HTTP exception.
  22320. * Defaults to false.
  22321. * @since 1.0.6
  22322. */
  22323. Yii.CUrlManager.prototype.useStrictParsing = false;
  22324. Yii.CUrlManager.prototype._urlFormat = 'get';
  22325. Yii.CUrlManager.prototype._rules = [];
  22326. Yii.CUrlManager.prototype._baseUrl = null;
  22327. /**
  22328. * Initializes the application component.
  22329. */
  22330. Yii.CUrlManager.prototype.init = function () {
  22331. Yii.CApplicationComponent.prototype.init.call(this);
  22332. this.processRules();
  22333. };
  22334. /**
  22335. * Processes the URL rules.
  22336. */
  22337. Yii.CUrlManager.prototype.processRules = function () {
  22338. var cache, hash, data, route, pattern, i, limit;
  22339. if(php.empty(this.rules) || this.getUrlFormat()===this.GET_FORMAT) {
  22340. return;
  22341. }
  22342. limit = this.rules.length;
  22343. for (i = 0; i < limit; i++) {
  22344. route = this.rules[i];
  22345. this._rules.push(this.createUrlRule(route, route.pattern));
  22346. }
  22347. if(cache !== undefined) {
  22348. cache.set(this.Yii.CACHE_KEY,[this._rules,hash]);
  22349. }
  22350. };
  22351. /**
  22352. * Adds new URL rules.
  22353. * In order to make the new rules effective, this method must be called BEFORE
  22354. * {@link CWebApplication::processRequest}.
  22355. * @param {Array} rules new URL rules (pattern=>route).
  22356. * @since 1.1.4
  22357. */
  22358. Yii.CUrlManager.prototype.addRules = function (rules) {
  22359. var route, pattern;
  22360. for (pattern in rules) {
  22361. if (rules.hasOwnProperty(pattern)) {
  22362. route = rules[pattern];
  22363. this._rules.push(this.createUrlRule(route,pattern));
  22364. }
  22365. }
  22366. };
  22367. /**
  22368. * Creates a URL rule instance.
  22369. * The default implementation returns a CUrlRule object.
  22370. * @param {Mixed} route the route part of the rule. This could be a string or an array
  22371. * @param {String} pattern the pattern part of the rule
  22372. * @returns {Yii.CUrlRule} the URL rule instance
  22373. * @since 1.1.0
  22374. */
  22375. Yii.CUrlManager.prototype.createUrlRule = function (route, pattern) {
  22376. return new Yii.CUrlRule(route,pattern);
  22377. };
  22378. /**
  22379. * Constructs a URL.
  22380. * @param {String} route the controller and the action (e.g. article/read)
  22381. * @param {Array} params list of GET parameters (name=>value). Both the name and value will be URL-encoded.
  22382. * If the name is '#', the corresponding value will be treated as an anchor
  22383. * and will be appended at the end of the URL. This anchor feature has been available since version 1.0.1.
  22384. * @param {String} ampersand the token separating name-value pairs in the URL. Defaults to '&'.
  22385. * @returns {String} the constructed URL
  22386. */
  22387. Yii.CUrlManager.prototype.createUrl = function (route, params, ampersand) {
  22388. var i, param, anchor, n, url, rule;
  22389. if (params === undefined) {
  22390. params = [];
  22391. }
  22392. if (ampersand === undefined) {
  22393. ampersand = '&';
  22394. }
  22395. delete params[this.routeVar];
  22396. for (i in params) {
  22397. if (params.hasOwnProperty(i)) {
  22398. if(params[i]===null) {
  22399. params[i]='';
  22400. }
  22401. }
  22402. }
  22403. if(params['#'] !== undefined) {
  22404. anchor='#'+params['#'];
  22405. delete params['#'];
  22406. }
  22407. else {
  22408. anchor='';
  22409. }
  22410. route=php.trim(route,'/');
  22411. for (n in this._rules) {
  22412. if (this._rules.hasOwnProperty(n)) {
  22413. rule = this._rules[n];
  22414. if((url=rule.createUrl(this,route,params,ampersand))!==false) {
  22415. if(rule.hasHostInfo) {
  22416. return url==='' ? '/'+anchor : url+anchor;
  22417. }
  22418. else {
  22419. return this.getBaseUrl()+'/'+url+anchor;
  22420. }
  22421. }
  22422. }
  22423. }
  22424. return this.createUrlDefault(route,params,ampersand)+anchor;
  22425. };
  22426. /**
  22427. * Contructs a URL based on default settings.
  22428. * @param {String} route the controller and the action (e.g. article/read)
  22429. * @param {Array} params list of GET parameters
  22430. * @param {String} ampersand the token separating name-value pairs in the URL.
  22431. * @returns {String} the constructed URL
  22432. */
  22433. Yii.CUrlManager.prototype.createUrlDefault = function (route, params, ampersand) {
  22434. var url, query;
  22435. if(this.getUrlFormat()===this.PATH_FORMAT) {
  22436. url=php.rtrim(this.getBaseUrl()+'/'+route,'/');
  22437. if(this.appendParams) {
  22438. url=php.rtrim(url+'/'+this.createPathInfo(params,'/','/'),'/');
  22439. return route==='' ? url : url+this.urlSuffix;
  22440. }
  22441. else {
  22442. if(route!=='') {
  22443. url+=this.urlSuffix;
  22444. }
  22445. query=this.createPathInfo(params,'=',ampersand);
  22446. return query==='' ? url : url+'?'+query;
  22447. }
  22448. }
  22449. else
  22450. {
  22451. url=this.getBaseUrl();
  22452. if(!this.showScriptName) {
  22453. url+='/';
  22454. }
  22455. if(route!=='') {
  22456. url+='?'+this.routeVar+'='+route;
  22457. if((query=this.createPathInfo(params,'=',ampersand))!=='') {
  22458. url+=ampersand+query;
  22459. }
  22460. }
  22461. else if((query=this.createPathInfo(params,'=',ampersand))!=='') {
  22462. url+='?'+query;
  22463. }
  22464. return url;
  22465. }
  22466. };
  22467. /**
  22468. * Parses the user request.
  22469. * @param {Yii.CHttpRequest} request the request application component
  22470. * @returns {String} the route (controllerID/actionID) and perhaps GET parameters in path format.
  22471. */
  22472. Yii.CUrlManager.prototype.parseUrl = function (request) {
  22473. var rawPathInfo, pathInfo, i, r, rule;
  22474. if(this.getUrlFormat()===this.PATH_FORMAT) {
  22475. rawPathInfo=request.getPathInfo();
  22476. pathInfo=this.removeUrlSuffix(rawPathInfo,this.urlSuffix);
  22477. for (i in this._rules) {
  22478. if (this._rules.hasOwnProperty(i)) {
  22479. rule = this._rules[i];
  22480. if((r=rule.parseUrl(this,request,pathInfo,rawPathInfo))!==false) {
  22481. return Yii.app().getRequest().params[this.routeVar] !== undefined ? Yii.app().getRequest().params[this.routeVar] : r;
  22482. }
  22483. }
  22484. }
  22485. if(this.useStrictParsing) {
  22486. throw new Yii.CHttpException(404,Yii.t('yii','Unable to resolve the request "{route}".',
  22487. {'{route}':pathInfo}));
  22488. }
  22489. else {
  22490. return pathInfo;
  22491. }
  22492. }
  22493. else if(Yii.app().getRequest().params[this.routeVar] !== undefined) {
  22494. return Yii.app().getRequest().params[this.routeVar];
  22495. }
  22496. else {
  22497. return '';
  22498. }
  22499. };
  22500. /**
  22501. * Parses a path info into URL segments and saves them to Yii.app().getRequest.params
  22502. * @param {String} pathInfo path info
  22503. * @since 1.0.3
  22504. */
  22505. Yii.CUrlManager.prototype.parsePathInfo = function (pathInfo) {
  22506. var segs, n, i, key, value, pos, m, matches, name, j, val;
  22507. if(pathInfo==='') {
  22508. return;
  22509. }
  22510. segs=pathInfo+'/'.split('/');
  22511. n=php.count(segs);
  22512. for(i=0;i<n-1;i+=2) {
  22513. key=segs[i];
  22514. if(key==='') {
  22515. continue;
  22516. }
  22517. value=segs[i+1];
  22518. if((pos=php.strpos(key,'['))!==false && (matches=key.match(/\[(.*?)\]/g)) !== null) {
  22519. name=key.slice(0, pos);
  22520. for(j=m-1;j>=0;--j) {
  22521. if(matches[1][j]==='') {
  22522. value=[value];
  22523. }
  22524. else {
  22525. val = {};
  22526. val[matches[1][j]] = value;
  22527. value = val;
  22528. }
  22529. }
  22530. if(Yii.app().getRequest.params[name] !== undefined && typeof Yii.app().getRequest.params[name] === 'object') {
  22531. value=Yii.CMap.prototype.mergeArray(Yii.app().getRequest.params[name],value);
  22532. }
  22533. Yii.app().getRequest.params[name]=value;
  22534. }
  22535. else {
  22536. Yii.app().getRequest.params[key]=value;
  22537. }
  22538. }
  22539. };
  22540. /**
  22541. * Creates a path info based on the given parameters.
  22542. * @param {Array} params list of GET parameters
  22543. * @param {String} equal the separator between name and value
  22544. * @param {String} ampersand the separator between name-value pairs
  22545. * @param {String} key this is used internally.
  22546. * @returns {String} the created path info
  22547. * @since 1.0.3
  22548. */
  22549. Yii.CUrlManager.prototype.createPathInfo = function (params, equal, ampersand, key) {
  22550. var pairs, k, v;
  22551. if (key === undefined) {
  22552. key = null;
  22553. }
  22554. pairs = [];
  22555. for (k in params) {
  22556. if (params.hasOwnProperty(k)) {
  22557. v = params[k];
  22558. if (key!==null) {
  22559. k = key+'['+k+']';
  22560. }
  22561. if (typeof v === "object") {
  22562. pairs.push(this.createPathInfo(v,equal,ampersand, k));
  22563. }
  22564. else {
  22565. pairs.push(php.urlencode(k)+equal+php.urlencode(v));
  22566. }
  22567. }
  22568. }
  22569. return pairs.join(ampersand);
  22570. };
  22571. /**
  22572. * Removes the URL suffix from path info.
  22573. * @param {String} pathInfo path info part in the URL
  22574. * @param {String} urlSuffix the URL suffix to be removed
  22575. * @returns {String} path info with URL suffix removed.
  22576. */
  22577. Yii.CUrlManager.prototype.removeUrlSuffix = function (pathInfo, urlSuffix) {
  22578. if(urlSuffix!=='' && pathInfo.slice(-php.strlen(urlSuffix))===urlSuffix) {
  22579. return pathInfo.slice(0, -php.strlen(urlSuffix));
  22580. }
  22581. else {
  22582. return pathInfo;
  22583. }
  22584. };
  22585. /**
  22586. * Returns the base URL of the application.
  22587. * @returns {String} the base URL of the application (the part after host name and before query string).
  22588. * If {@link showScriptName} is true, it will include the script name part.
  22589. * Otherwise, it will not, and the ending slashes are stripped off.
  22590. */
  22591. Yii.CUrlManager.prototype.getBaseUrl = function () {
  22592. if(this._baseUrl!==null) {
  22593. return this._baseUrl;
  22594. }
  22595. else
  22596. {
  22597. if(this.showScriptName) {
  22598. this._baseUrl=Yii.app().getRequest().getScriptUrl();
  22599. }
  22600. else {
  22601. this._baseUrl=Yii.app().getRequest().getBaseUrl();
  22602. }
  22603. return this._baseUrl;
  22604. }
  22605. };
  22606. /**
  22607. * Sets the base URL of the application (the part after host name and before query string).
  22608. * This method is provided in case the {@link baseUrl} cannot be determined automatically.
  22609. * The ending slashes should be stripped off. And you are also responsible to remove the script name
  22610. * if you set {@link showScriptName} to be false.
  22611. * @param {String} value the base URL of the application
  22612. * @since 1.1.1
  22613. */
  22614. Yii.CUrlManager.prototype.setBaseUrl = function (value) {
  22615. this._baseUrl=value;
  22616. };
  22617. /**
  22618. * Returns the URL format.
  22619. * @returns {String} the URL format. Defaults to 'path'. Valid values include 'path' and 'get'.
  22620. * Please refer to the guide for more details about the difference between these two formats.
  22621. */
  22622. Yii.CUrlManager.prototype.getUrlFormat = function () {
  22623. return this._urlFormat;
  22624. };
  22625. /**
  22626. * Sets the URL format.
  22627. * @param {String} value the URL format. It must be either 'path' or 'get'.
  22628. */
  22629. Yii.CUrlManager.prototype.setUrlFormat = function (value) {
  22630. if(value===this.PATH_FORMAT || value===this.GET_FORMAT) {
  22631. this._urlFormat=value;
  22632. }
  22633. else {
  22634. throw new Yii.CException(Yii.t('yii','CUrlManager.UrlFormat must be either "path" or "get".'));
  22635. }
  22636. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  22637. /**
  22638. * CUrlRule represents a URL formatting/parsing rule.
  22639. *
  22640. * It mainly consists of two parts: route and pattern. The former classifies
  22641. * the rule so that it only applies to specific controller-action route.
  22642. * The latter performs the actual formatting and parsing role. The pattern
  22643. * may have a set of named parameters.
  22644. *
  22645. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  22646. * @version $Id: CUrlManager.php 3165 2011-04-06 08:27:40Z mdomba $
  22647. * @package system.web
  22648. * @since 1.0
  22649. * @author Charles Pick
  22650. * @class
  22651. * @extends Yii.CComponent
  22652. */
  22653. Yii.CUrlRule = function CUrlRule (route, pattern) {
  22654. if (route !== false) {
  22655. this.construct(route, pattern);
  22656. }
  22657. };
  22658. Yii.CUrlRule.prototype = new Yii.CComponent();
  22659. Yii.CUrlRule.prototype.constructor = Yii.CUrlRule;
  22660. /**
  22661. * @var {String} the URL suffix used for this rule.
  22662. * For example, ".html" can be used so that the URL looks like pointing to a static HTML page.
  22663. * Defaults to null, meaning using the value of {@link CUrlManager::urlSuffix}.
  22664. * @since 1.0.6
  22665. */
  22666. Yii.CUrlRule.prototype.urlSuffix = null;
  22667. /**
  22668. * @var {Boolean} whether the rule is case sensitive. Defaults to null, meaning
  22669. * using the value of {@link CUrlManager::caseSensitive}.
  22670. * @since 1.0.1
  22671. */
  22672. Yii.CUrlRule.prototype.caseSensitive = null;
  22673. /**
  22674. * @var {Object} the default GET parameters (name=>value) that this rule provides.
  22675. * When this rule is used to parse the incoming request, the values declared in this property
  22676. * will be injected into Yii.app().getRequest().params
  22677. * @since 1.0.8
  22678. */
  22679. Yii.CUrlRule.prototype.defaultParams = {};
  22680. /**
  22681. * @var {Boolean} whether the GET parameter values should match the corresponding
  22682. * sub-patterns in the rule when creating a URL. Defaults to null, meaning using the value
  22683. * of {@link CUrlManager::matchValue}. When this property is false, it means
  22684. * a rule will be used for creating a URL if its route and parameter names match the given ones.
  22685. * If this property is set true, then the given parameter values must also match the corresponding
  22686. * parameter sub-patterns. Note that setting this property to true will degrade performance.
  22687. * @since 1.1.0
  22688. */
  22689. Yii.CUrlRule.prototype.matchValue = null;
  22690. /**
  22691. * @var {String} the HTTP verb (e.g. GET, POST, DELETE) that this rule should match.
  22692. * If this rule can match multiple verbs, please separate them with commas.
  22693. * If this property is not set, the rule can match any verb.
  22694. * Note that this property is only used when parsing a request. It is ignored for URL creation.
  22695. * @since 1.1.7
  22696. */
  22697. Yii.CUrlRule.prototype.verb = null;
  22698. /**
  22699. * @var {Boolean} whether this rule is only used for request parsing.
  22700. * Defaults to false, meaning the rule is used for both URL parsing and creation.
  22701. * @since 1.1.7
  22702. */
  22703. Yii.CUrlRule.prototype.parsingOnly = false;
  22704. /**
  22705. * @var {String} the controller/action pair
  22706. */
  22707. Yii.CUrlRule.prototype.route = null;
  22708. /**
  22709. * @var {Object} the mapping from route param name to token name (e.g. _r1=><1>)
  22710. * @since 1.0.5
  22711. */
  22712. Yii.CUrlRule.prototype.references = {};
  22713. /**
  22714. * @var {String} the pattern used to match route
  22715. * @since 1.0.5
  22716. */
  22717. Yii.CUrlRule.prototype.routePattern = null;
  22718. /**
  22719. * @var {String} regular expression used to parse a URL
  22720. */
  22721. Yii.CUrlRule.prototype.pattern = null;
  22722. /**
  22723. * @var {String} template used to construct a URL
  22724. */
  22725. Yii.CUrlRule.prototype.template = null;
  22726. /**
  22727. * @var {Object} list of parameters (name=>regular expression)
  22728. */
  22729. Yii.CUrlRule.prototype.params = {};
  22730. /**
  22731. * @var {Boolean} whether the URL allows additional parameters at the end of the path info.
  22732. */
  22733. Yii.CUrlRule.prototype.append = null;
  22734. /**
  22735. * @var {Boolean} whether host info should be considered for this rule
  22736. * @since 1.0.11
  22737. */
  22738. Yii.CUrlRule.prototype.hasHostInfo = null;
  22739. /**
  22740. * Constructor.
  22741. * @param {String} route the route of the URL (controller/action)
  22742. * @param {String} pattern the pattern for matching the URL
  22743. */
  22744. Yii.CUrlRule.prototype.construct = function (route, pattern) {
  22745. var i, name, tr2 = {}, tr = {}, matches2, n, matches, tokens, value, p, vals, limit;
  22746. this.references = {};
  22747. this.defaultParams = {};
  22748. this.params = {};
  22749. if(typeof route === 'object') {
  22750. vals = ['urlSuffix','caseSensitive','defaultParams','matchValue','verb','parsingOnly'];
  22751. limit = vals.length;
  22752. for (i = 0; i < limit; i ++) {
  22753. name = vals[i];
  22754. if(route[name] !== undefined) {
  22755. this[name]=route[name];
  22756. }
  22757. }
  22758. if(route.pattern !== undefined) {
  22759. pattern=route.pattern;
  22760. }
  22761. route=route.route;
  22762. }
  22763. this.route=php.trim(route,'/');
  22764. tr2['/']=tr['/']='\\/';
  22765. if(php.strpos(route,'<')!==false) {
  22766. matches2 = Yii.matchAll(/<(\w+)>/g, route);
  22767. limit = matches2.length;
  22768. for (n in matches2) {
  22769. if (matches2.hasOwnProperty(n)) {
  22770. this.references[matches2[n][1]] = "<" + matches2[n][1] + ">";
  22771. }
  22772. }
  22773. }
  22774. this.hasHostInfo=!php.strncasecmp(pattern,'http://',7) || !php.strncasecmp(pattern,'https://',8);
  22775. if(this.verb!==null) {
  22776. this.verb=this.verb.toUpperCase().split(/[\s,]+/);
  22777. }
  22778. matches = Yii.matchAll(/<(\w+):?(.*?)?>/g, pattern);
  22779. if (matches !== null) {
  22780. for (i in matches) {
  22781. if (matches.hasOwnProperty(i)) {
  22782. if (matches[i][2] === '') {
  22783. matches[i][2] = '[^\/]+';
  22784. }
  22785. tr["<" + matches[i][1] + ">"] = "(" + matches[i][2] + ")";
  22786. if (this.references[matches[i][1]] !== undefined) {
  22787. tr2["<" + matches[i][1] + ">"] = tr["<" + matches[i][1] + ">"];
  22788. }
  22789. else {
  22790. this.params[matches[i][1]] = matches[i][2];
  22791. }
  22792. }
  22793. }
  22794. }
  22795. p=php.rtrim(pattern,'*');
  22796. this.append=p!==pattern;
  22797. p=php.trim(p,'/');
  22798. this.template=p.replace(/<(\w+):?.*?>/g,'<$1>');
  22799. this.pattern='^'+php.strtr(this.template,tr) + "\/";
  22800. if(!this.append) {
  22801. this.pattern+='$';
  22802. }
  22803. limit = 0;
  22804. for (i in this.references) {
  22805. if (this.references.hasOwnProperty(i)) {
  22806. limit++;
  22807. }
  22808. }
  22809. if (limit > 0) {
  22810. this.routePattern = "^" + php.strtr(this.route, tr2) + "$";
  22811. }
  22812. };
  22813. /**
  22814. * Creates a URL based on this rule.
  22815. * @param {Yii.CUrlManager} manager the manager
  22816. * @param {String} route the route
  22817. * @param {Array} params list of parameters
  22818. * @param {String} ampersand the token separating name-value pairs in the URL.
  22819. * @returns {Mixed} the constructed URL or false on error
  22820. */
  22821. Yii.CUrlRule.prototype.createUrl = function (manager, route, params, ampersand) {
  22822. var caseVar, tr, matches, name, key, value, suffix, url, hostInfo, n;
  22823. if(this.parsingOnly) {
  22824. return false;
  22825. }
  22826. if(manager.caseSensitive && this.caseSensitive===null || this.caseSensitive) {
  22827. caseVar='';
  22828. }
  22829. else {
  22830. caseVar='i';
  22831. }
  22832. tr={};
  22833. if(route!==this.route) {
  22834. if(this.routePattern!==null && ((matches = new RegExp(this.routePattern,"u"+caseVar).exec(route)))) {
  22835. n = 1;
  22836. for (key in this.references) {
  22837. if (this.references.hasOwnProperty(key)) {
  22838. name = this.references[key];
  22839. tr[name]=matches[n];
  22840. n += 1;
  22841. }
  22842. }
  22843. }
  22844. else {
  22845. return false;
  22846. }
  22847. }
  22848. for (key in this.defaultParams) {
  22849. if (this.defaultParams.hasOwnProperty(key)) {
  22850. value = this.defaultParams[key];
  22851. if(params[key] !== undefined) {
  22852. if(params[key]==value) {
  22853. delete params[key];
  22854. }
  22855. else {
  22856. return false;
  22857. }
  22858. }
  22859. }
  22860. }
  22861. for (key in this.params) {
  22862. if (this.params.hasOwnProperty(key)) {
  22863. value = this.params[key];
  22864. if(params[key] === undefined) {
  22865. return false;
  22866. }
  22867. }
  22868. }
  22869. if(manager.matchValue && this.matchValue===null || this.matchValue) {
  22870. for (key in this.params) {
  22871. if (this.params.hasOwnProperty(key)) {
  22872. value = this.params[key];
  22873. if(!(new RegExp(value,caseVar)).exec(params[key])) {
  22874. return false;
  22875. }
  22876. }
  22877. }
  22878. }
  22879. for (key in this.params) {
  22880. if (this.params.hasOwnProperty(key)) {
  22881. value = this.params[key];
  22882. tr["<" + key + ">"]=php.urlencode(params[key]);
  22883. delete params[key];
  22884. }
  22885. }
  22886. suffix=this.urlSuffix===null ? manager.urlSuffix : this.urlSuffix;
  22887. url=php.strtr(this.template,tr);
  22888. if(this.hasHostInfo) {
  22889. hostInfo=Yii.app().getRequest().getHostInfo();
  22890. if(php.stripos(url,hostInfo)===0) {
  22891. url=url.slice(php.strlen(hostInfo));
  22892. }
  22893. }
  22894. if(php.empty(params)) {
  22895. return url!=='' ? url+suffix : url;
  22896. }
  22897. if(this.append) {
  22898. url+='/'+manager.createPathInfo(params,'/','/')+suffix;
  22899. }
  22900. else {
  22901. if(url!=='') {
  22902. url+=suffix;
  22903. }
  22904. url+='?'+manager.createPathInfo(params,'=',ampersand);
  22905. }
  22906. return url;
  22907. };
  22908. /**
  22909. * Parases a URL based on this rule.
  22910. * @param {Yii.CUrlManager} manager the URL manager
  22911. * @param {Yii.CHttpRequest} request the request object
  22912. * @param {String} pathInfo path info part of the URL
  22913. * @param {String} rawPathInfo path info that contains the potential URL suffix
  22914. * @returns {Mixed} the route that consists of the controller ID and action ID or false on error
  22915. */
  22916. Yii.CUrlRule.prototype.parseUrl = function (manager, request, pathInfo, rawPathInfo) {
  22917. var caseVar, urlSuffix, matches, name, value, tr, key, i, n;
  22918. if(this.verb!==null && !php.in_array(request.getRequestType(), this.verb, true)) {
  22919. return false;
  22920. }
  22921. if(manager.caseSensitive && this.caseSensitive===null || this.caseSensitive) {
  22922. caseVar='';
  22923. }
  22924. else {
  22925. caseVar='i';
  22926. }
  22927. if(this.urlSuffix!==null) {
  22928. pathInfo=manager.removeUrlSuffix(rawPathInfo,this.urlSuffix);
  22929. }
  22930. // URL suffix required, but not found in the requested URL
  22931. if(manager.useStrictParsing && pathInfo===rawPathInfo) {
  22932. urlSuffix=this.urlSuffix===null ? manager.urlSuffix : this.urlSuffix;
  22933. if(urlSuffix!='' && urlSuffix!=='/') {
  22934. return false;
  22935. }
  22936. }
  22937. if(this.hasHostInfo) {
  22938. pathInfo=request.getHostInfo().toLowerCase()+php.rtrim('/'+pathInfo,'/');
  22939. }
  22940. pathInfo+='/';
  22941. if((matches = new RegExp(this.pattern,caseVar).exec(pathInfo))) {
  22942. n = 1;
  22943. tr={};
  22944. for (i in this.references) {
  22945. if (this.references.hasOwnProperty(i)) {
  22946. tr[this.references[i]] = matches[n];
  22947. n += 1;
  22948. }
  22949. }
  22950. for (i in this.params) {
  22951. if (this.params.hasOwnProperty(i)) {
  22952. re = new RegExp(this.params[i]);
  22953. if (re.exec(matches[n])) {
  22954. request.params[i] = matches[n];
  22955. n += 1;
  22956. }
  22957. }
  22958. }
  22959. for (i in this.defaultParams) {
  22960. if (this.defaultParams.hasOwnProperty(i)) {
  22961. request.params[i] = this.defaultParams[i];
  22962. }
  22963. }
  22964. if(pathInfo!==matches[0]) { // there are additional GET params
  22965. manager.parsePathInfo(php.ltrim(pathInfo.slice(php.strlen(matches[0])),'/'));
  22966. }
  22967. if(this.routePattern!==null) {
  22968. return php.strtr(this.route,tr);
  22969. }
  22970. else {
  22971. return this.route;
  22972. }
  22973. }
  22974. else {
  22975. return false;
  22976. }
  22977. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  22978. /**
  22979. * CWebApplication extends CApplication by providing functionalities specific to Web requests.
  22980. *
  22981. * CWebApplication manages the controllers in MVC pattern, and provides the following additional
  22982. * core application components:
  22983. * <ul>
  22984. * <li>{@link urlManager}: provides URL parsing and constructing functionality;</li>
  22985. * <li>{@link request}: encapsulates the Web request information;</li>
  22986. * <li>{@link session}: provides the session-related functionalities;</li>
  22987. * <li>{@link assetManager}: manages the publishing of private asset files.</li>
  22988. * <li>{@link user}: represents the user session information.</li>
  22989. * <li>{@link themeManager}: manages themes.</li>
  22990. * <li>{@link authManager}: manages role-based access control (RBAC).</li>
  22991. * <li>{@link clientScript}: manages client scripts (javascripts and CSS).</li>
  22992. * <li>{@link widgetFactory}: creates widgets and supports widget skinning.</li>
  22993. * </ul>
  22994. *
  22995. * User requests are resolved as controller-action pairs and additional parameters.
  22996. * CWebApplication creates the requested controller instance and let it to handle
  22997. * the actual user request. If the user does not specify controller ID, it will
  22998. * assume {@link defaultController} is requested (which defaults to 'site').
  22999. *
  23000. * Controller class files must reside under the directory {@link getControllerPath controllerPath}
  23001. * (defaults to 'protected/controllers'). The file name and the class name must be
  23002. * the same as the controller ID with the first letter in upper case and appended with 'Controller'.
  23003. * For example, the controller 'article' is defined by the class 'ArticleController'
  23004. * which is in the file 'protected/controllers/ArticleController.php'.
  23005. *
  23006. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  23007. * @version $Id: CWebApplication.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  23008. * @package system.web
  23009. * @since 1.0
  23010. * @author Charles Pick
  23011. * @class
  23012. * @extends Yii.CApplication
  23013. */
  23014. Yii.CWebApplication = function CWebApplication (config) {
  23015. if (config !== false) {
  23016. this.views = {
  23017. layouts: {
  23018. main: 'application.views.layouts.main'
  23019. }
  23020. };
  23021. this.construct(config);
  23022. }
  23023. };
  23024. Yii.CWebApplication.prototype = new Yii.CApplication(false);
  23025. Yii.CWebApplication.prototype.constructor = Yii.CWebApplication;
  23026. /**
  23027. * @returns {String} the route of the default controller, action or module. Defaults to 'site'.
  23028. */
  23029. Yii.CWebApplication.prototype.defaultController = 'site';
  23030. /**
  23031. * @var {Mixed} the application-wide layout. Defaults to 'main' (relative to {@link getLayoutPath layoutPath}).
  23032. * If this is false, then no layout will be used.
  23033. */
  23034. Yii.CWebApplication.prototype.layout = 'main';
  23035. /**
  23036. * @var {Array} mapping from controller ID to controller configurations.
  23037. * Each name-value pair specifies the configuration for a single controller.
  23038. * A controller configuration can be either a string or an array.
  23039. * If the former, the string should be the class name or
  23040. * {@link YiiBase::getPathOfAlias class path alias} of the controller.
  23041. * If the latter, the array must contain a 'class' element which specifies
  23042. * the controller's class name or {@link YiiBase::getPathOfAlias class path alias}.
  23043. * The rest name-value pairs in the array are used to initialize
  23044. * the corresponding controller properties. For example,
  23045. * <pre>
  23046. * {
  23047. * 'post':{
  23048. * 'class':'path.to.PostController',
  23049. * 'pageTitle':'something new',
  23050. * },
  23051. * 'user':'path.to.UserController',,
  23052. * }
  23053. * </pre>
  23054. *
  23055. * Note, when processing an incoming request, the controller map will first be
  23056. * checked to see if the request can be handled by one of the controllers in the map.
  23057. * If not, a controller will be searched for under the {@link getControllerPath default controller path}.
  23058. */
  23059. Yii.CWebApplication.prototype.controllerMap = [];
  23060. /**
  23061. * @var {Array} the configuration specifying a controller which should handle
  23062. * all user requests. This is mainly used when the application is in maintenance mode
  23063. * and we should use a controller to handle all incoming requests.
  23064. * The configuration specifies the controller route (the first element)
  23065. * and GET parameters (the rest name-value pairs). For example,
  23066. * <pre>
  23067. * {
  23068. * 'offline/notice',
  23069. * 'param1':'value1',
  23070. * 'param2':'value2',
  23071. * }
  23072. * </pre>
  23073. * Defaults to null, meaning catch-all is not effective.
  23074. */
  23075. Yii.CWebApplication.prototype.catchAllRequest = null;
  23076. Yii.CWebApplication.prototype._controllerPath = null;
  23077. Yii.CWebApplication.prototype._viewPath = null;
  23078. Yii.CWebApplication.prototype._systemViewPath = null;
  23079. Yii.CWebApplication.prototype._layoutPath = null;
  23080. Yii.CWebApplication.prototype._controller = null;
  23081. Yii.CWebApplication.prototype._homeUrl = null;
  23082. Yii.CWebApplication.prototype._theme = null;
  23083. /**
  23084. * Processes the current request.
  23085. * It first resolves the request into controller and action,
  23086. * and then creates the controller to perform the action.
  23087. */
  23088. Yii.CWebApplication.prototype.processRequest = function () {
  23089. var route, nameValue, name, value;
  23090. if(Object.prototype.toString.call(this.catchAllRequest) === '[object Array]' && this.catchAllRequest[0] !== undefined) {
  23091. route=this.catchAllRequest[0];
  23092. nameValue = php.array_splice(this.catchAllRequest,1);
  23093. for (name in nameValue) {
  23094. if (nameValue.hasOwnProperty(name)) {
  23095. value = nameValue[name];
  23096. this.getRequest().params[name]=value;
  23097. }
  23098. }
  23099. }
  23100. else {
  23101. route=this.getUrlManager().parseUrl(this.getRequest());
  23102. }
  23103. this.runController(route);
  23104. };
  23105. /**
  23106. * Registers the core application components.
  23107. * This method overrides the parent implementation by registering additional core components.
  23108. * @see setComponents
  23109. */
  23110. Yii.CWebApplication.prototype.registerCoreComponents = function () {
  23111. var components;
  23112. Yii.CApplication.prototype.registerCoreComponents.call(this);
  23113. components={
  23114. 'session':{
  23115. 'class':'CHttpSession'
  23116. },
  23117. 'assetManager':{
  23118. 'class':'CAssetManager'
  23119. },
  23120. 'user':{
  23121. 'class':'CWebUser'
  23122. },
  23123. 'themeManager':{
  23124. 'class':'CThemeManager'
  23125. },
  23126. 'authManager':{
  23127. 'class':'CPhpAuthManager'
  23128. },
  23129. 'clientScript':{
  23130. 'class':'CClientScript'
  23131. },
  23132. 'widgetFactory':{
  23133. 'class':'CWidgetFactory'
  23134. }
  23135. };
  23136. this.setComponents(components);
  23137. };
  23138. /**
  23139. * @returns {IAuthManager} the authorization manager component
  23140. */
  23141. Yii.CWebApplication.prototype.getAuthManager = function () {
  23142. return this.getComponent('authManager');
  23143. };
  23144. /**
  23145. * @returns {Yii.CAssetManager} the asset manager component
  23146. */
  23147. Yii.CWebApplication.prototype.getAssetManager = function () {
  23148. return this.getComponent('assetManager');
  23149. };
  23150. /**
  23151. * @returns {Yii.CHttpSession} the session component
  23152. */
  23153. Yii.CWebApplication.prototype.getSession = function () {
  23154. return this.getComponent('session');
  23155. };
  23156. /**
  23157. * @returns {Yii.CWebUser} the user session information
  23158. */
  23159. Yii.CWebApplication.prototype.getUser = function () {
  23160. return this.getComponent('user');
  23161. };
  23162. /**
  23163. * Returns the view renderer.
  23164. * If this component is registered and enabled, the default
  23165. * view rendering logic defined in {@link CBaseController} will
  23166. * be replaced by this renderer.
  23167. * @returns {IViewRenderer} the view renderer.
  23168. */
  23169. Yii.CWebApplication.prototype.getViewRenderer = function () {
  23170. return this.getComponent('viewRenderer');
  23171. };
  23172. /**
  23173. * Returns the client script manager.
  23174. * @returns {Yii.CClientScript} the client script manager
  23175. */
  23176. Yii.CWebApplication.prototype.getClientScript = function () {
  23177. return this.getComponent('clientScript');
  23178. };
  23179. /**
  23180. * Returns the widget factory.
  23181. * @returns {IWidgetFactory} the widget factory
  23182. * @since 1.1
  23183. */
  23184. Yii.CWebApplication.prototype.getWidgetFactory = function () {
  23185. return this.getComponent('widgetFactory');
  23186. };
  23187. /**
  23188. * @returns {Yii.CThemeManager} the theme manager.
  23189. */
  23190. Yii.CWebApplication.prototype.getThemeManager = function () {
  23191. return this.getComponent('themeManager');
  23192. };
  23193. /**
  23194. * @returns {Yii.CTheme} the theme used currently. Null if no theme is being used.
  23195. */
  23196. Yii.CWebApplication.prototype.getTheme = function () {
  23197. if(typeof(this._theme) === 'string') {
  23198. this._theme=this.getThemeManager().getTheme(this._theme);
  23199. }
  23200. return this._theme;
  23201. };
  23202. /**
  23203. * @param {String} value the theme name
  23204. */
  23205. Yii.CWebApplication.prototype.setTheme = function (value) {
  23206. this._theme=value;
  23207. };
  23208. /**
  23209. * Creates a relative URL based on the given controller and action information.
  23210. * @param {String} route the URL route. This should be in the format of 'ControllerID/ActionID'.
  23211. * @param {Array} params additional GET parameters (name=>value). Both the name and value will be URL-encoded.
  23212. * @param {String} ampersand the token separating name-value pairs in the URL.
  23213. * @returns {String} the constructed URL
  23214. */
  23215. Yii.CWebApplication.prototype.createUrl = function (route, params, ampersand) {
  23216. if (params === undefined) {
  23217. params = [];
  23218. }
  23219. if (ampersand === undefined) {
  23220. ampersand = '&';
  23221. }
  23222. return this.getUrlManager().createUrl(route,params,ampersand);
  23223. };
  23224. /**
  23225. * Creates an absolute URL based on the given controller and action information.
  23226. * @param {String} route the URL route. This should be in the format of 'ControllerID/ActionID'.
  23227. * @param {Array} params additional GET parameters (name=>value). Both the name and value will be URL-encoded.
  23228. * @param {String} schema schema to use (e.g. http, https). If empty, the schema used for the current request will be used.
  23229. * @param {String} ampersand the token separating name-value pairs in the URL.
  23230. * @returns {String} the constructed URL
  23231. */
  23232. Yii.CWebApplication.prototype.createAbsoluteUrl = function (route, params, schema, ampersand) {
  23233. var url;
  23234. if (params === undefined) {
  23235. params = [];
  23236. }
  23237. if (schema === undefined) {
  23238. schema = '';
  23239. }
  23240. if (ampersand === undefined) {
  23241. ampersand = '&';
  23242. }
  23243. url=this.createUrl(route,params,ampersand);
  23244. if(php.strpos(url,'http')===0) {
  23245. return url;
  23246. }
  23247. else {
  23248. return this.getRequest().getHostInfo(schema)+url;
  23249. }
  23250. };
  23251. /**
  23252. * Returns the relative URL for the application.
  23253. * This is a shortcut method to {@link CHttpRequest::getBaseUrl()}.
  23254. * @param {Boolean} absolute whether to return an absolute URL. Defaults to false, meaning returning a relative one.
  23255. * This parameter has been available since 1.0.2.
  23256. * @returns {String} the relative URL for the application
  23257. * @see CHttpRequest::getBaseUrl()
  23258. */
  23259. Yii.CWebApplication.prototype.getBaseUrl = function (absolute) {
  23260. if (absolute === undefined) {
  23261. absolute = false;
  23262. }
  23263. return this.getRequest().getBaseUrl(absolute);
  23264. };
  23265. /**
  23266. * @returns {String} the homepage URL
  23267. */
  23268. Yii.CWebApplication.prototype.getHomeUrl = function () {
  23269. if(this._homeUrl===null) {
  23270. if(this.getUrlManager().showScriptName) {
  23271. return this.getRequest().getScriptUrl();
  23272. }
  23273. else {
  23274. return this.getRequest().getBaseUrl()+'/';
  23275. }
  23276. }
  23277. else {
  23278. return this._homeUrl;
  23279. }
  23280. };
  23281. /**
  23282. * @param {String} value the homepage URL
  23283. */
  23284. Yii.CWebApplication.prototype.setHomeUrl = function (value) {
  23285. this._homeUrl=value;
  23286. };
  23287. /**
  23288. * Creates the controller and performs the specified action.
  23289. * @param {String} route the route of the current request. See {@link createController} for more details.
  23290. * @throws {Yii.CHttpException} if the controller could not be created.
  23291. */
  23292. Yii.CWebApplication.prototype.runController = function (route) {
  23293. var ca, controller, actionID, oldController;
  23294. if((ca=this.createController(route))!==null && ca[0] !== undefined && ca[0] !== false) {
  23295. controller = ca[0];
  23296. actionID = ca[1];
  23297. // oldController=this._controller;
  23298. this._controller=controller;
  23299. controller.init();
  23300. controller.run(actionID);
  23301. // this._controller=oldController;
  23302. }
  23303. else {
  23304. throw new Yii.CHttpException(404,Yii.t('yii','Unable to resolve the request "{route}".',
  23305. {'{route}':route===''?this.defaultController:route}));
  23306. }
  23307. };
  23308. /**
  23309. * Creates a controller instance based on a route.
  23310. * The route should contain the controller ID and the action ID.
  23311. * It may also contain additional GET variables. All these must be concatenated together with slashes.
  23312. *
  23313. * This method will attempt to create a controller in the following order:
  23314. * <ol>
  23315. * <li>If the first segment is found in {@link controllerMap}, the corresponding
  23316. * controller configuration will be used to create the controller;</li>
  23317. * <li>If the first segment is found to be a module ID, the corresponding module
  23318. * will be used to create the controller;</li>
  23319. * <li>Otherwise, it will search under the {@link controllerPath} to create
  23320. * the corresponding controller. For example, if the route is "admin/user/create",
  23321. * then the controller will be created using the class file "protected/controllers/admin/UserController.php".</li>
  23322. * </ol>
  23323. * @param {String} route the route of the request.
  23324. * @param {Yii.CWebModule} owner the module that the new controller will belong to. Defaults to null, meaning the application
  23325. * instance is the owner.
  23326. * @returns {Array} the controller instance and the action ID. Null if the controller class does not exist or the route is invalid.
  23327. */
  23328. Yii.CWebApplication.prototype.createController = function (route, owner) {
  23329. var caseSensitive, pos, id, basePath = null, module, controllerID, className, classFile;
  23330. if (owner === undefined) {
  23331. owner = null;
  23332. }
  23333. if(owner===null) {
  23334. owner=this;
  23335. }
  23336. if((route=php.trim(route,'/'))==='') {
  23337. route=owner.defaultController;
  23338. }
  23339. caseSensitive=this.getUrlManager().caseSensitive;
  23340. route+='/';
  23341. while((pos=php.strpos(route,'/'))!==false) {
  23342. id=route.slice(0, pos);
  23343. if(!/^\w+$/.exec(id)) {
  23344. return null;
  23345. }
  23346. if(!caseSensitive) {
  23347. id=id.toLowerCase();
  23348. }
  23349. route=String(route.slice(pos+1));
  23350. if(basePath === null) {
  23351. // first segment
  23352. if(owner.controllerMap[id] !== undefined) {
  23353. return [
  23354. Yii.createComponent(owner.controllerMap[id],id,owner===this?null:owner),
  23355. this.parseActionParams(route)
  23356. ];
  23357. }
  23358. if((module=owner.getModule(id))!==null && module !== undefined) {
  23359. return this.createController(route,module);
  23360. }
  23361. basePath=owner.getControllerPath();
  23362. controllerID='';
  23363. }
  23364. else {
  23365. controllerID+='/';
  23366. }
  23367. // try and include the file
  23368. className=php.ucfirst(id)+'Controller';
  23369. classFile=basePath+'/'+className+'.js';
  23370. return [
  23371. Yii.createComponent(classFile,id,owner===this?null:owner),
  23372. this.parseActionParams(route)
  23373. ];
  23374. }
  23375. };
  23376. /**
  23377. * Parses a path info into an action ID and GET variables.
  23378. * @param {String} pathInfo path info
  23379. * @returns {String} action ID
  23380. * @since 1.0.3
  23381. */
  23382. Yii.CWebApplication.prototype.parseActionParams = function (pathInfo) {
  23383. var pos, manager, actionID;
  23384. if((pos=php.strpos(pathInfo,'/'))!==false) {
  23385. manager=this.getUrlManager();
  23386. manager.parsePathInfo(String(pathInfo.slice(pos+1)));
  23387. actionID=pathInfo.slice(0, pos);
  23388. return manager.caseSensitive ? actionID : actionID.toLowerCase();
  23389. }
  23390. else {
  23391. return pathInfo;
  23392. }
  23393. };
  23394. /**
  23395. * @returns {Yii.CController} the currently active controller
  23396. */
  23397. Yii.CWebApplication.prototype.getController = function () {
  23398. return this._controller;
  23399. };
  23400. /**
  23401. * @param {Yii.CController} value the currently active controller
  23402. * @since 1.0.6
  23403. */
  23404. Yii.CWebApplication.prototype.setController = function (value) {
  23405. this._controller=value;
  23406. };
  23407. /**
  23408. * @returns {String} the directory that contains the controller classes. Defaults to 'protected/controllers'.
  23409. */
  23410. Yii.CWebApplication.prototype.getControllerPath = function () {
  23411. if(this._controllerPath!==null) {
  23412. return this._controllerPath;
  23413. }
  23414. else {
  23415. return (this._controllerPath=this.getBasePath()+'/controllers');
  23416. }
  23417. };
  23418. /**
  23419. * @param {String} value the directory that contains the controller classes.
  23420. */
  23421. Yii.CWebApplication.prototype.setControllerPath = function (value) {
  23422. this._controllerPath=value;
  23423. };
  23424. /**
  23425. * @returns {String} the root directory of view files. Defaults to 'protected/views'.
  23426. */
  23427. Yii.CWebApplication.prototype.getViewPath = function () {
  23428. if(this._viewPath!==null) {
  23429. return this._viewPath;
  23430. }
  23431. else {
  23432. return (this._viewPath=this.getBasePath()+'/views');
  23433. }
  23434. };
  23435. /**
  23436. * @param {String} path the root directory of view files.
  23437. */
  23438. Yii.CWebApplication.prototype.setViewPath = function (path) {
  23439. this._viewPath=path;
  23440. };
  23441. /**
  23442. * @returns {String} the root directory of system view files. Defaults to 'protected/views/system'.
  23443. */
  23444. Yii.CWebApplication.prototype.getSystemViewPath = function () {
  23445. if(this._systemViewPath!==null) {
  23446. return this._systemViewPath;
  23447. }
  23448. else {
  23449. return (this._systemViewPath=this.getViewPath()+'/system');
  23450. }
  23451. };
  23452. /**
  23453. * @param {String} path the root directory of system view files.
  23454. */
  23455. Yii.CWebApplication.prototype.setSystemViewPath = function (path) {
  23456. this._systemViewPath=path;
  23457. };
  23458. /**
  23459. * @returns {String} the root directory of layout files. Defaults to 'protected/views/layouts'.
  23460. */
  23461. Yii.CWebApplication.prototype.getLayoutPath = function () {
  23462. if(this._layoutPath!==null) {
  23463. return this._layoutPath;
  23464. }
  23465. else {
  23466. return (this._layoutPath=this.getViewPath()+'/layouts');
  23467. }
  23468. };
  23469. /**
  23470. * @param {String} path the root directory of layout files.
  23471. */
  23472. Yii.CWebApplication.prototype.setLayoutPath = function (path) {
  23473. this._layoutPath=path;
  23474. };
  23475. /**
  23476. * The pre-filter for controller actions.
  23477. * This method is invoked before the currently requested controller action and all its filters
  23478. * are executed. You may override this method with logic that needs to be done
  23479. * before all controller actions.
  23480. * @param {Yii.CController} controller the controller
  23481. * @param {Yii.CAction} action the action
  23482. * @returns {Boolean} whether the action should be executed.
  23483. * @since 1.0.4
  23484. */
  23485. Yii.CWebApplication.prototype.beforeControllerAction = function (controller, action) {
  23486. return true;
  23487. };
  23488. /**
  23489. * The post-filter for controller actions.
  23490. * This method is invoked after the currently requested controller action and all its filters
  23491. * are executed. You may override this method with logic that needs to be done
  23492. * after all controller actions.
  23493. * @param {Yii.CController} controller the controller
  23494. * @param {Yii.CAction} action the action
  23495. * @since 1.0.4
  23496. */
  23497. Yii.CWebApplication.prototype.afterControllerAction = function (controller, action) {
  23498. };
  23499. /**
  23500. * Searches for a module by its ID.
  23501. * This method is used internally. Do not call this method.
  23502. * @param {String} id module ID
  23503. * @returns {Yii.CWebModule} the module that has the specified ID. Null if no module is found.
  23504. * @since 1.0.3
  23505. */
  23506. Yii.CWebApplication.prototype.findModule = function (id) {
  23507. var controller, module, m;
  23508. if((controller=this.getController())!==null && (module=controller.getModule())!==null) {
  23509. do
  23510. {
  23511. if((m=module.getModule(id))!==null) {
  23512. return m;
  23513. }
  23514. } while((module=module.getParentModule())!==null);
  23515. }
  23516. if((m=this.getModule(id))!==null) {
  23517. return m;
  23518. }
  23519. };
  23520. /**
  23521. * Initializes the application.
  23522. * This method overrides the parent implementation by preloading the 'request' component.
  23523. */
  23524. Yii.CWebApplication.prototype.init = function () {
  23525. Yii.CApplication.prototype.init.call(this);
  23526. // preload 'request' so that it has chance to respond to onBeginRequest event.
  23527. this.getRequest();
  23528. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  23529. /**
  23530. * CWidgetFactory creates new widgets to be used in views.
  23531. *
  23532. * CWidgetFactory is used as the default "widgetFactory" application component.
  23533. *
  23534. * When calling {@link CBaseController::createWidget}, {@link CBaseController::widget}
  23535. * or {@link CBaseController::beginWidget}, if the "widgetFactory" component is installed,
  23536. * it will be used to create the requested widget. To install the "widgetFactory" component,
  23537. * we should have the following application configuration:
  23538. * <pre>
  23539. * return {
  23540. * 'components':{
  23541. * 'widgetFactory':{
  23542. * 'class':'CWidgetFactory',
  23543. * },
  23544. * ),
  23545. * }
  23546. * </pre>
  23547. *
  23548. * CWidgetFactory implements the "skin" feature, which allows a new widget to be created
  23549. * and initialized with a set of predefined property values (called skin).
  23550. *
  23551. * When CWidgetFactory is used to create a new widget, it will first instantiate the
  23552. * widget instance. It then checks if there is a skin available for this widget
  23553. * according to the widget class name and the widget {@link CWidget::skin} property.
  23554. * If a skin is found, it will be merged with the initial properties passed via
  23555. * {@link createWidget}. Then the merged initial properties will be used to initialize
  23556. * the newly created widget instance.
  23557. *
  23558. * As aforementioned, a skin is a set of initial property values for a widget.
  23559. * It is thus represented as an associative array of name-value pairs.
  23560. * Skins are stored in PHP scripts like other configurations. Each script file stores the skins
  23561. * for a particular widget type and is named as the wiget class name (e.g. CLinkPager.php).
  23562. * Each widget type may have one or several skins, identified by the skin name set via
  23563. * {@link CWidget::skin} property. If the {@link CWidget::skin} property is not set for a given
  23564. * widget, it means the default skin would be used. The following shows the possible skins for
  23565. * the {@link CLinkPager} widget:
  23566. * <pre>
  23567. * return {
  23568. * 'default':{
  23569. * 'nextPageLabel':'&gt;&gt;',
  23570. * 'prevPageLabel':'&lt;&lt;',
  23571. * },
  23572. * 'short':{
  23573. * 'header':'',
  23574. * 'maxButtonCount':5,
  23575. * },
  23576. * };
  23577. * </pre>
  23578. * In the above, there are two skins. The first one is the default skin which is indexed by the string "default".
  23579. * Note that {@link CWidget::skin} defaults to "default". Therefore, this is the skin that will be applied
  23580. * if we do not explicitly specify the {@link CWidget::skin} property.
  23581. * The second one is named as the "short" skin which will be used only when we set {@link CWidget::skin}
  23582. * to be "short".
  23583. *
  23584. * By default, CWidgetFactory looks for the skin of a widget under the "skins" directory
  23585. * of the current application's {@link CWebApplication::viewPath} (e.g. protected/views/skins).
  23586. * If a theme is being used, it will look for the skin under the "skins" directory of
  23587. * the theme's {@link CTheme::viewPath} (as well as the aforementioned skin directory).
  23588. * In case the specified skin is not found, a widget will still be created
  23589. * normally without causing any error.
  23590. *
  23591. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  23592. * @version $Id: CWidgetFactory.php 2799 2011-01-01 19:31:13Z qiang.xue $
  23593. * @package system.web
  23594. * @since 1.1
  23595. * @author Charles Pick
  23596. * @class
  23597. * @extends Yii.CApplicationComponent
  23598. */
  23599. Yii.CWidgetFactory = function CWidgetFactory () {
  23600. };
  23601. Yii.CWidgetFactory.prototype = new Yii.CApplicationComponent();
  23602. Yii.CWidgetFactory.prototype.constructor = Yii.CWidgetFactory;
  23603. /**
  23604. * @var {Object} widget initial property values. Each array key-value pair
  23605. * represents the initial property values for a single widget class, with
  23606. * the array key being the widget class name, and array value being the initial
  23607. * property value array. For example,
  23608. * <pre>
  23609. * {
  23610. * 'CLinkPager':{
  23611. * 'maxButtonCount':5,
  23612. * 'cssFile':false,
  23613. * ),
  23614. * 'CJuiDatePicker':{
  23615. * 'language':'ru',
  23616. * },
  23617. * }
  23618. * </pre>
  23619. *
  23620. * Note that the initial values specified here may be overridden by
  23621. * the values given in {@link CBaseController::createWidget} calls.
  23622. * They may also be overridden by widget skins, if {@link enableSkin} is true.
  23623. * @since 1.1.3
  23624. */
  23625. Yii.CWidgetFactory.prototype.widgets = {};
  23626. /**
  23627. * Initializes the application component.
  23628. * This method overrides the parent implementation by resolving the skin path.
  23629. */
  23630. Yii.CWidgetFactory.prototype.init = function () {
  23631. Yii.CApplicationComponent.prototype.init.call(this);
  23632. };
  23633. /**
  23634. * Creates a new widget based on the given class name and initial properties.
  23635. * @param {Yii.CBaseController} owner the owner of the new widget
  23636. * @param {String} className the class name of the widget. This can also be a path alias (e.g. system.web.widgets.COutputCache)
  23637. * @param {Array} properties the initial property values (name=>value) of the widget.
  23638. * @returns {Yii.CWidget} the newly created widget whose properties have been initialized with the given values.
  23639. */
  23640. Yii.CWidgetFactory.prototype.createWidget = function (owner, className, properties) {
  23641. var widget, skinName, skin, name, value;
  23642. if (properties === undefined) {
  23643. properties = [];
  23644. }
  23645. className=Yii.imports(className,true);
  23646. widget=new Yii[className](owner);
  23647. if(this.widgets[className] !== undefined) {
  23648. properties=properties===[] ? this.widgets[className] : Yii.CMap.prototype.mergeArray(this.widgets[className],properties);
  23649. }
  23650. for (name in properties) {
  23651. if (properties.hasOwnProperty(name)) {
  23652. value = properties[name];
  23653. widget[name]=value;
  23654. }
  23655. }
  23656. return widget;
  23657. };
  23658. /*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  23659. /**
  23660. * CAction is the base class for all controller action classes.
  23661. *
  23662. * CAction provides a way to divide a complex controller into
  23663. * smaller actions in separate class files.
  23664. *
  23665. * Derived classes must implement {@link run()} which is invoked by
  23666. * controller when the action is requested.
  23667. *
  23668. * An action instance can access its controller via {@link getController controller} property.
  23669. *
  23670. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  23671. * @version $Id: CAction.php 3058 2011-03-13 04:20:12Z qiang.xue $
  23672. * @package system.web.actions
  23673. * @since 1.0
  23674. * @author Charles Pick
  23675. * @class
  23676. * @extends Yii.CComponent
  23677. */
  23678. Yii.CAction = function CAction(controller, id) {
  23679. if (controller !== false) {
  23680. this.construct(controller, id);
  23681. }
  23682. };
  23683. Yii.CAction.prototype = new Yii.CComponent();
  23684. Yii.CAction.prototype.constructor = Yii.CAction;
  23685. Yii.CAction.prototype._id = null;
  23686. Yii.CAction.prototype._controller = null;
  23687. /**
  23688. * Constructor.
  23689. * @param {Yii.CController} controller the controller who owns this action.
  23690. * @param {String} id id of the action.
  23691. */
  23692. Yii.CAction.prototype.construct = function (controller, id) {
  23693. this._controller=controller;
  23694. this._id=id;
  23695. };
  23696. /**
  23697. * @returns {Yii.CController} the controller who owns this action.
  23698. */
  23699. Yii.CAction.prototype.getController = function () {
  23700. return this._controller;
  23701. };
  23702. /**
  23703. * @returns {String} id of this action
  23704. */
  23705. Yii.CAction.prototype.getId = function () {
  23706. return this._id;
  23707. };
  23708. /**
  23709. * Runs the action with the supplied request parameters.
  23710. * This method is internally called by {@link CController::runAction()}.
  23711. * @param {Array} params the request parameters (name=>value)
  23712. * @returns {Boolean} whether the request parameters are valid
  23713. * @since 1.1.7
  23714. */
  23715. Yii.CAction.prototype.runWithParams = function (params) {
  23716. var methodParams = [], matches;
  23717. matches = /function(.*)\((.*)\)/.exec(this.run);
  23718. if (matches) {
  23719. methodParams = matches[2].split(/[\s,]+/);
  23720. }
  23721. if(methodParams.length >0) {
  23722. return this.runWithParamsInternal(this, "run", params);
  23723. }
  23724. else {
  23725. return this.run();
  23726. }
  23727. };
  23728. /**
  23729. * Executes a method of an object with the supplied named parameters.
  23730. * This method is internally used.
  23731. * @param {Mixed} object the object whose method is to be executed
  23732. * @param {String} method the name of the method
  23733. * @param {Array} params the named parameters
  23734. * @returns {Boolean} whether the named parameters are valid
  23735. * @since 1.1.7
  23736. */
  23737. Yii.CAction.prototype.runWithParamsInternal = function (object, method, params) {
  23738. var ps, paramList, name, param, i, limit;
  23739. ps=[];
  23740. paramList = /function(.*)\((.*)\)/.exec(object[method]).pop();
  23741. if (paramList !== '') {
  23742. paramList = paramList.split(/[\s,]+/);
  23743. }
  23744. else {
  23745. paramList = [];
  23746. }
  23747. limit = paramList.length;
  23748. for (i = 0; i < limit; i++) {
  23749. name = paramList[i];
  23750. if(params !== undefined && params[name] !== undefined) {
  23751. ps.push(params[name]);
  23752. }
  23753. }
  23754. object[method].apply(object,ps);
  23755. return true;
  23756. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  23757. /**
  23758. * CInlineAction represents an action that is defined as a controller method.
  23759. *
  23760. * The method name is like 'actionXYZ' where 'XYZ' stands for the action name.
  23761. *
  23762. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  23763. * @version $Id: CInlineAction.php 3137 2011-03-28 11:08:06Z mdomba $
  23764. * @package system.web.actions
  23765. * @since 1.0
  23766. * @author Charles Pick
  23767. * @class
  23768. * @extends Yii.CAction
  23769. */
  23770. Yii.CInlineAction = function CInlineAction(controller, id) {
  23771. if (controller !== false) {
  23772. this.construct(controller, id);
  23773. }
  23774. };
  23775. Yii.CInlineAction.prototype = new Yii.CAction(false);
  23776. Yii.CInlineAction.prototype.constructor = Yii.CInlineAction;
  23777. /**
  23778. * Runs the action.
  23779. * The action method defined in the controller is invoked.
  23780. * This method is required by {@link CAction}.
  23781. */
  23782. Yii.CInlineAction.prototype.run = function () {
  23783. var method;
  23784. method='action'+php.ucfirst(this.getId());
  23785. this.getController()[method]();
  23786. };
  23787. /**
  23788. * Runs the action with the supplied request parameters.
  23789. * This method is internally called by {@link CController::runAction()}.
  23790. * @param {Array} params the request parameters (name=>value)
  23791. * @returns {Boolean} whether the request parameters are valid
  23792. * @since 1.1.7
  23793. */
  23794. Yii.CInlineAction.prototype.runWithParams = function (params) {
  23795. var methodName, controller, method, paramList;
  23796. methodName='action'+this.getId();
  23797. controller=this.getController();
  23798. paramList = (/function(.*)\((.*)\)/.exec(controller[methodName])).pop();
  23799. if(paramList.length > 0) {
  23800. return this.runWithParamsInternal(controller, methodName, params);
  23801. }
  23802. else {
  23803. return controller[methodName]();
  23804. }
  23805. }/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  23806. /**
  23807. * CViewAction represents an action that displays a view according to a user-specified parameter.
  23808. *
  23809. * By default, the view being displayed is specified via the <code>view</code> GET parameter.
  23810. * The name of the GET parameter can be customized via {@link viewParam}.
  23811. * If the user doesn't provide the GET parameter, the default view specified by {@link defaultView}
  23812. * will be displayed.
  23813. *
  23814. * Users specify a view in the format of <code>path.to.view</code>, which translates to the view name
  23815. * <code>BasePath/path/to/view</code> where <code>BasePath</code> is given by {@link basePath}.
  23816. *
  23817. * Note, the user specified view can only contain word characters, dots and dashes and
  23818. * the first letter must be a word letter.
  23819. *
  23820. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  23821. * @version $Id: CViewAction.php 2799 2011-01-01 19:31:13Z qiang.xue $
  23822. * @package system.web.actions
  23823. * @since 1.0
  23824. * @author Charles Pick
  23825. * @class
  23826. * @extends Yii.CAction
  23827. */
  23828. Yii.CViewAction = function CViewAction (controller, id) {
  23829. if (controller !== false) {
  23830. this.construct(controller, id);
  23831. }
  23832. };
  23833. Yii.CViewAction.prototype = new Yii.CAction(false);
  23834. Yii.CViewAction.prototype.constructor = Yii.CViewAction;
  23835. /**
  23836. * @var {String} the name of the GET parameter that contains the requested view name. Defaults to 'view'.
  23837. */
  23838. Yii.CViewAction.prototype.viewParam = 'view';
  23839. /**
  23840. * @var {String} the name of the default view when {@link viewParam} GET parameter is not provided by user. Defaults to 'index'.
  23841. * This should be in the format of 'path.to.view', similar to that given in
  23842. * the GET parameter.
  23843. * @see basePath
  23844. */
  23845. Yii.CViewAction.prototype.defaultView = 'index';
  23846. /**
  23847. * @var {String} the name of the view to be rendered. This property will be set
  23848. * once the user requested view is resolved.
  23849. */
  23850. Yii.CViewAction.prototype.view = null;
  23851. /**
  23852. * @var {String} the base path for the views. Defaults to 'pages'.
  23853. * The base path will be prefixed to any user-specified page view.
  23854. * For example, if a user requests for <code>tutorial.chap1</code>, the corresponding view name will
  23855. * be <code>pages/tutorial/chap1</code>, assuming the base path is <code>pages</code>.
  23856. * The actual view file is determined by {@link CController::getViewFile}.
  23857. * @see CController::getViewFile
  23858. */
  23859. Yii.CViewAction.prototype.basePath = 'pages';
  23860. /**
  23861. * @var {Mixed} the name of the layout to be applied to the views.
  23862. * This will be assigned to {@link CController::layout} before the view is rendered.
  23863. * Defaults to null, meaning the controller's layout will be used.
  23864. * If false, no layout will be applied.
  23865. */
  23866. Yii.CViewAction.prototype.layout = null;
  23867. /**
  23868. * @var {Boolean} whether the view should be rendered as PHP script or static text. Defaults to false.
  23869. */
  23870. Yii.CViewAction.prototype.renderAsText = false;
  23871. Yii.CViewAction.prototype._viewPath = null;
  23872. /**
  23873. * Returns the name of the view requested by the user.
  23874. * If the user doesn't specify any view, the {@link defaultView} will be returned.
  23875. * @returns {String} the name of the view requested by the user.
  23876. * This is in the format of 'path.to.view'.
  23877. */
  23878. Yii.CViewAction.prototype.getRequestedView = function () {
  23879. if(this._viewPath===null) {
  23880. if(!php.empty(Yii.app().getRequest().params[this.viewParam])) {
  23881. this._viewPath=Yii.app().getRequest().params[this.viewParam];
  23882. }
  23883. else {
  23884. this._viewPath=this.defaultView;
  23885. }
  23886. }
  23887. return this._viewPath;
  23888. };
  23889. /**
  23890. * Resolves the user-specified view into a valid view name.
  23891. * @param {String} viewPath user-specified view in the format of 'path.to.view'.
  23892. * @returns {String} fully resolved view in the format of 'path/to/view'.
  23893. * @throw CHttpException if the user-specified view is invalid
  23894. */
  23895. Yii.CViewAction.prototype.resolveView = function (viewPath) {
  23896. var view;
  23897. // start with a word char and have word chars, dots and dashes only
  23898. if(/^\w[\w\.\-]*$/.exec(viewPath)) {
  23899. view=php.strtr(viewPath,'.','/');
  23900. if(!php.empty(this.basePath)) {
  23901. view=this.basePath+'/'+view;
  23902. }
  23903. if(this.getController().getViewFile(view)!==false) {
  23904. this.view=view;
  23905. return;
  23906. }
  23907. }
  23908. throw new Yii.CHttpException(404,Yii.t('yii','The requested view "{name}" was not found.',
  23909. {'{name}':viewPath}));
  23910. };
  23911. /**
  23912. * Runs the action.
  23913. * This method displays the view requested by the user.
  23914. * @throws {Yii.CHttpException} if the view is invalid
  23915. */
  23916. Yii.CViewAction.prototype.run = function () {
  23917. var controller, layout, event, text;
  23918. this.resolveView(this.getRequestedView());
  23919. controller=this.getController();
  23920. if(this.layout!==null) {
  23921. layout=controller.layout;
  23922. controller.layout=this.layout;
  23923. }
  23924. this.onBeforeRender(event=new Yii.CEvent(this));
  23925. if(!event.handled) {
  23926. if(this.renderAsText) {
  23927. text=file_get_contents(controller.getViewFile(this.view));
  23928. controller.renderText(text);
  23929. }
  23930. else {
  23931. controller.render(this.view, {}, function(html) {
  23932. jQuery("body").html(html);
  23933. });
  23934. }
  23935. this.onAfterRender(new Yii.CEvent(this));
  23936. }
  23937. if(this.layout!==null) {
  23938. controller.layout=layout;
  23939. }
  23940. };
  23941. /**
  23942. * Raised right before the action invokes the render method.
  23943. * Event handlers can set the {@link CEvent::handled} property
  23944. * to be true to stop further view rendering.
  23945. * @param {Yii.CEvent} event event parameter
  23946. */
  23947. Yii.CViewAction.prototype.onBeforeRender = function (event) {
  23948. this.raiseEvent('onBeforeRender',event);
  23949. };
  23950. /**
  23951. * Raised right after the action invokes the render method.
  23952. * @param {Yii.CEvent} event event parameter
  23953. */
  23954. Yii.CViewAction.prototype.onAfterRender = function (event) {
  23955. this.raiseEvent('onAfterRender',event);
  23956. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  23957. /**
  23958. * CAccessControlFilter performs authorization checks for the specified actions.
  23959. *
  23960. * By enabling this filter, controller actions can be checked for access permissions.
  23961. * When the user is not denied by one of the security rules or allowed by a rule explicitly,
  23962. * he will be able to access the action.
  23963. *
  23964. * For maximum security consider adding
  23965. * <pre>['deny']</pre>
  23966. * as a last rule in a list so all actions will be denied by default.
  23967. *
  23968. * To specify the access rules, set the {@link setRules rules} property, which should
  23969. * be an array of the rules. Each rule is specified as an array of the following structure:
  23970. * <pre>
  23971. * {
  23972. * 'allow', // or 'deny'
  23973. * // optional, list of action IDs (case insensitive) that this rule applies to
  23974. * 'actions':{'edit', 'delete'},
  23975. * // optional, list of controller IDs (case insensitive) that this rule applies to
  23976. * // This option is available since version 1.0.3.
  23977. * 'controllers':{'post', 'admin/user'},
  23978. * // optional, list of usernames (case insensitive) that this rule applies to
  23979. * // Use * to represent all users, ? guest users, and @ authenticated users
  23980. * 'users':{'thomas', 'kevin'},
  23981. * // optional, list of roles (case sensitive!) that this rule applies to.
  23982. * 'roles':{'admin', 'editor'},
  23983. * // optional, list of IP address/patterns that this rule applies to
  23984. * // e.g. 127.0.0.1, 127.0.0.*
  23985. * 'ips':{'127.0.0.1'},
  23986. * // optional, list of request types (case insensitive) that this rule applies to
  23987. * 'verbs':{'GET', 'POST'},
  23988. * // optional, a PHP expression whose value indicates whether this rule applies
  23989. * // This option is available since version 1.0.3.
  23990. * 'expression':'!$user->isGuest && $user->level==2',
  23991. * // optional, the customized error message to be displayed
  23992. * // This option is available since version 1.1.1.
  23993. * 'message':'Access Denied.',
  23994. * }
  23995. * </pre>
  23996. *
  23997. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  23998. * @version $Id: CAccessControlFilter.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  23999. * @package system.web.auth
  24000. * @since 1.0
  24001. * @author Charles Pick
  24002. * @class
  24003. * @extends Yii.CFilter
  24004. */
  24005. Yii.CAccessControlFilter = function CAccessControlFilter () {
  24006. };
  24007. Yii.CAccessControlFilter.prototype = new Yii.CFilter();
  24008. Yii.CAccessControlFilter.prototype.constructor = Yii.CAccessControlFilter;
  24009. /**
  24010. * @var {String} the error message to be displayed when authorization fails.
  24011. * This property can be overridden by individual access rule via {@link CAccessRule::message}.
  24012. * If this property is not set, a default error message will be displayed.
  24013. * @since 1.1.1
  24014. */
  24015. Yii.CAccessControlFilter.prototype.message = null;
  24016. Yii.CAccessControlFilter.prototype._rules = [];
  24017. /**
  24018. * @returns {Array} list of access rules.
  24019. */
  24020. Yii.CAccessControlFilter.prototype.getRules = function () {
  24021. return this._rules;
  24022. };
  24023. /**
  24024. * @param {Array} rules list of access rules.
  24025. */
  24026. Yii.CAccessControlFilter.prototype.setRules = function (rules) {
  24027. var i, rule, r, nameValue, name, value;
  24028. for (i in rules) {
  24029. if (rules.hasOwnProperty(i)) {
  24030. rule = rules[i];
  24031. if(Object.prototype.toString.call(rule) === '[object Array]' && rule[0] !== undefined)
  24032. {
  24033. r=new Yii.CAccessRule();
  24034. r.allow=rule[0]==='allow';
  24035. nameValue = php.array_slice(rule,1);
  24036. for (name in nameValue) {
  24037. if (nameValue.hasOwnProperty(name)) {
  24038. value = nameValue[name];
  24039. if(name==='expression' || name==='roles' || name==='message') {
  24040. r.name=value;
  24041. }
  24042. else {
  24043. r.name=php.array_map('strtolower',value);
  24044. }
  24045. }
  24046. }
  24047. this._rules.push(r);
  24048. }
  24049. }
  24050. }
  24051. };
  24052. /**
  24053. * Performs the pre-action filtering.
  24054. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  24055. * @returns {Boolean} whether the filtering process should continue and the action
  24056. * should be executed.
  24057. */
  24058. Yii.CAccessControlFilter.prototype.preFilter = function (filterChain) {
  24059. var app, request, user, verb, ip, i, ruleList, allow, rule;
  24060. app=Yii.app();
  24061. request=app.getRequest();
  24062. user=app.getUser();
  24063. verb=request.getRequestType();
  24064. ip=request.getUserHostAddress();
  24065. ruleList = this.getRules();
  24066. for (i in ruleList) {
  24067. if (ruleList.hasOwnProperty(i)) {
  24068. rule = ruleList[i];
  24069. if((allow=rule.isUserAllowed(user,filterChain.controller,filterChain.action,ip,verb))>0) { // allowed
  24070. break;
  24071. }
  24072. else if(allow<0) {
  24073. // denied
  24074. this.accessDenied(user,this.resolveErrorMessage(rule));
  24075. return false;
  24076. }
  24077. }
  24078. }
  24079. return true;
  24080. };
  24081. /**
  24082. * Resolves the error message to be displayed.
  24083. * This method will check {@link message} and {@link CAccessRule::message} to see
  24084. * what error message should be displayed.
  24085. * @param {Yii.CAccessRule} rule the access rule
  24086. * @returns {String} the error message
  24087. * @since 1.1.1
  24088. */
  24089. Yii.CAccessControlFilter.prototype.resolveErrorMessage = function (rule) {
  24090. if(rule.message!==null) {
  24091. return rule.message;
  24092. }
  24093. else if(this.message!==null) {
  24094. return this.message;
  24095. }
  24096. else {
  24097. return Yii.t('yii','You are not authorized to perform this action.');
  24098. }
  24099. };
  24100. /**
  24101. * Denies the access of the user.
  24102. * This method is invoked when access check fails.
  24103. * @param {IWebUser} user the current user
  24104. * @param {String} message the error message to be displayed
  24105. * @since 1.0.5
  24106. */
  24107. Yii.CAccessControlFilter.prototype.accessDenied = function (user, message) {
  24108. if(user.getIsGuest()) {
  24109. user.loginRequired();
  24110. }
  24111. else {
  24112. throw new Yii.CHttpException(403,message);
  24113. }
  24114. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  24115. /**
  24116. * CAccessRule represents an access rule that is managed by {@link CAccessControlFilter}.
  24117. *
  24118. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  24119. * @version $Id: CAccessControlFilter.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  24120. * @package system.web.auth
  24121. * @since 1.0
  24122. * @author Charles Pick
  24123. * @class
  24124. * @extends Yii.CComponent
  24125. */
  24126. Yii.CAccessRule = function CAccessRule () {
  24127. };
  24128. Yii.CAccessRule.prototype = new Yii.CComponent();
  24129. Yii.CAccessRule.prototype.constructor = Yii.CAccessRule;
  24130. /**
  24131. * @var {Boolean} whether this is an 'allow' rule or 'deny' rule.
  24132. */
  24133. Yii.CAccessRule.prototype.allow = null;
  24134. /**
  24135. * @var {Array} list of action IDs that this rule applies to. The comparison is case-insensitive.
  24136. */
  24137. Yii.CAccessRule.prototype.actions = null;
  24138. /**
  24139. * @var {Array} list of controler IDs that this rule applies to. The comparison is case-insensitive.
  24140. * @since 1.0.4
  24141. */
  24142. Yii.CAccessRule.prototype.controllers = null;
  24143. /**
  24144. * @var {Array} list of user names that this rule applies to. The comparison is case-insensitive.
  24145. */
  24146. Yii.CAccessRule.prototype.users = null;
  24147. /**
  24148. * @var {Array} list of roles this rule applies to. For each role, the current user's
  24149. * {@link CWebUser::checkAccess} method will be invoked. If one of the invocations
  24150. * returns true, the rule will be applied.
  24151. * Note, you should mainly use roles in an "allow" rule because by definition,
  24152. * a role represents a permission collection.
  24153. * @see CAuthManager
  24154. */
  24155. Yii.CAccessRule.prototype.roles = null;
  24156. /**
  24157. * @var {Array} IP patterns.
  24158. */
  24159. Yii.CAccessRule.prototype.ips = null;
  24160. /**
  24161. * @var {Array} list of request types (e.g. GET, POST) that this rule applies to.
  24162. */
  24163. Yii.CAccessRule.prototype.verbs = null;
  24164. /**
  24165. * @var {String} a PHP expression whose value indicates whether this rule should be applied.
  24166. * In this expression, you can use <code>$user</code> which refers to <code>Yii::app()->user</code>.
  24167. * Starting from version 1.0.11, the expression can also be a valid PHP callback,
  24168. * including class method name (array(ClassName/Object, MethodName)),
  24169. * or anonymous function (PHP 5.3.0+). The function/method signature should be as follows:
  24170. * <pre>
  24171. * function foo(user, rule) { +++ }
  24172. * </pre>
  24173. * where $user is the current application user object and $rule is this access rule.
  24174. * @since 1.0.3
  24175. */
  24176. Yii.CAccessRule.prototype.expression = null;
  24177. /**
  24178. * @var {String} the error message to be displayed when authorization is denied by this rule.
  24179. * If not set, a default error message will be displayed.
  24180. * @since 1.1.1
  24181. */
  24182. Yii.CAccessRule.prototype.message = null;
  24183. /**
  24184. * Checks whether the Web user is allowed to perform the specified action.
  24185. * @param {Yii.CWebUser} user the user object
  24186. * @param {Yii.CController} controller the controller currently being executed
  24187. * @param {Yii.CAction} action the action to be performed
  24188. * @param {String} ip the request IP address
  24189. * @param {String} verb the request verb (GET, POST, etc.)
  24190. * @returns {Integer} 1 if the user is allowed, -1 if the user is denied, 0 if the rule does not apply to the user
  24191. */
  24192. Yii.CAccessRule.prototype.isUserAllowed = function (user, controller, action, ip, verb) {
  24193. if(this.isActionMatched(action)
  24194. && this.isUserMatched(user)
  24195. && this.isRoleMatched(user)
  24196. && this.isIpMatched(ip)
  24197. && this.isVerbMatched(verb)
  24198. && this.isControllerMatched(controller)
  24199. && this.isExpressionMatched(user)) {
  24200. return this.allow ? 1 : -1;
  24201. }
  24202. else {
  24203. return 0;
  24204. }
  24205. };
  24206. /**
  24207. * @param {Yii.CAction} action the action
  24208. * @returns {Boolean} whether the rule applies to the action
  24209. */
  24210. Yii.CAccessRule.prototype.isActionMatched = function (action) {
  24211. return php.empty(this.actions) || php.in_array(action.getId().toLowerCase(),this.actions);
  24212. };
  24213. /**
  24214. * @param {Yii.CAction} controller the action
  24215. * @returns {Boolean} whether the rule applies to the action
  24216. */
  24217. Yii.CAccessRule.prototype.isControllerMatched = function (controller) {
  24218. return php.empty(this.controllers) || php.in_array(controller.getId().toLowerCase(),this.controllers);
  24219. };
  24220. /**
  24221. * @param {IWebUser} user the user
  24222. * @returns {Boolean} whether the rule applies to the user
  24223. */
  24224. Yii.CAccessRule.prototype.isUserMatched = function (user) {
  24225. var i, u;
  24226. if(php.empty(this.users)) {
  24227. return true;
  24228. }
  24229. for (i in this.users)
  24230. {
  24231. if (this.users.hasOwnProperty(i)) {
  24232. u = this.users[i];
  24233. if(u==='*') {
  24234. return true;
  24235. }
  24236. else if(u==='?' && user.getIsGuest()) {
  24237. return true;
  24238. }
  24239. else if(u==='@' && !user.getIsGuest()) {
  24240. return true;
  24241. }
  24242. else if(!php.strcasecmp(u,user.getName())) {
  24243. return true;
  24244. }
  24245. }
  24246. }
  24247. return false;
  24248. };
  24249. /**
  24250. * @param {IWebUser} user the user object
  24251. * @returns {Boolean} whether the rule applies to the role
  24252. */
  24253. Yii.CAccessRule.prototype.isRoleMatched = function (user) {
  24254. var i, role;
  24255. if(php.empty(this.roles)) {
  24256. return true;
  24257. }
  24258. for (i in this.roles)
  24259. {
  24260. if (this.roles.hasOwnProperty(i)) {
  24261. role = this.roles[i];
  24262. if(user.checkAccess(role)) {
  24263. return true;
  24264. }
  24265. }
  24266. }
  24267. return false;
  24268. };
  24269. /**
  24270. * @param {String} ip the IP address
  24271. * @returns {Boolean} whether the rule applies to the IP address
  24272. */
  24273. Yii.CAccessRule.prototype.isIpMatched = function (ip) {
  24274. var i, rule, pos;
  24275. if(php.empty(this.ips)) {
  24276. return true;
  24277. }
  24278. for (i in this.ips)
  24279. {
  24280. if (this.ips.hasOwnProperty(i)) {
  24281. rule = this.ips[i];
  24282. if(rule==='*' || rule===ip || ((pos=php.strpos(rule,'*'))!==false && !php.strncmp(ip,rule,pos))) {
  24283. return true;
  24284. }
  24285. }
  24286. }
  24287. return false;
  24288. };
  24289. /**
  24290. * @param {String} verb the request method
  24291. * @returns {Boolean} whether the rule applies to the request
  24292. */
  24293. Yii.CAccessRule.prototype.isVerbMatched = function (verb) {
  24294. return php.empty(this.verbs) || php.in_array(verb.toLowerCase(),this.verbs);
  24295. };
  24296. /**
  24297. * @param {IWebUser} user the user
  24298. * @returns {Boolean} the expression value. True if the expression is not specified.
  24299. * @since 1.0.3
  24300. */
  24301. Yii.CAccessRule.prototype.isExpressionMatched = function (user) {
  24302. if(this.expression===null) {
  24303. return true;
  24304. }
  24305. else {
  24306. return this.evaluateExpression(this.expression, {'user':user});
  24307. }
  24308. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  24309. /**
  24310. * CBaseUserIdentity is a base class implementing {@link IUserIdentity}.
  24311. *
  24312. * CBaseUserIdentity implements the scheme for representing identity
  24313. * information that needs to be persisted. It also provides the way
  24314. * to represent the authentication errors.
  24315. *
  24316. * Derived classes should implement {@link IUserIdentity::authenticate}
  24317. * and {@link IUserIdentity::getId} that are required by the {@link IUserIdentity}
  24318. * interface.
  24319. *
  24320. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  24321. * @version $Id: CBaseUserIdentity.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  24322. * @package system.web.auth
  24323. * @since 1.0
  24324. * @author Charles Pick
  24325. * @class
  24326. * @extends Yii.CComponent
  24327. */
  24328. Yii.CBaseUserIdentity = function CBaseUserIdentity () {
  24329. };
  24330. Yii.CBaseUserIdentity.prototype = new Yii.CComponent();
  24331. Yii.CBaseUserIdentity.prototype.constructor = Yii.CBaseUserIdentity;
  24332. /**
  24333. * @const
  24334. */
  24335. Yii.CBaseUserIdentity.ERROR_NONE = 0;
  24336. /**
  24337. * @const
  24338. */
  24339. Yii.CBaseUserIdentity.ERROR_USERNAME_INVALID = 1;
  24340. /**
  24341. * @const
  24342. */
  24343. Yii.CBaseUserIdentity.ERROR_PASSWORD_INVALID = 2;
  24344. /**
  24345. * @const
  24346. */
  24347. Yii.CBaseUserIdentity.ERROR_UNKNOWN_IDENTITY = 100;
  24348. /**
  24349. * @var {Integer} the authentication error code. If there is an error, the error code will be non-zero.
  24350. * Defaults to 100, meaning unknown identity. Calling {@link authenticate} will change this value.
  24351. */
  24352. Yii.CBaseUserIdentity.prototype.errorCode = 100;
  24353. /**
  24354. * @var {String} the authentication error message. Defaults to empty.
  24355. */
  24356. Yii.CBaseUserIdentity.prototype.errorMessage = '';
  24357. Yii.CBaseUserIdentity.prototype._state = [];
  24358. /**
  24359. * Returns a value that uniquely represents the identity.
  24360. * @returns {Mixed} a value that uniquely represents the identity (e.g. primary key value).
  24361. * The default implementation simply returns {@link name}.
  24362. */
  24363. Yii.CBaseUserIdentity.prototype.getId = function () {
  24364. return this.getName();
  24365. };
  24366. /**
  24367. * Returns the display name for the identity (e.g. username).
  24368. * @returns {String} the display name for the identity.
  24369. * The default implementation simply returns empty string.
  24370. */
  24371. Yii.CBaseUserIdentity.prototype.getName = function () {
  24372. return '';
  24373. };
  24374. /**
  24375. * Returns the identity states that should be persisted.
  24376. * This method is required by {@link IUserIdentity}.
  24377. * @returns {Array} the identity states that should be persisted.
  24378. */
  24379. Yii.CBaseUserIdentity.prototype.getPersistentStates = function () {
  24380. return this._state;
  24381. };
  24382. /**
  24383. * Sets an array of presistent states.
  24384. *
  24385. * @param {Array} states the identity states that should be persisted.
  24386. */
  24387. Yii.CBaseUserIdentity.prototype.setPersistentStates = function (states) {
  24388. this._state = states;
  24389. };
  24390. /**
  24391. * Returns a value indicating whether the identity is authenticated.
  24392. * This method is required by {@link IUserIdentity}.
  24393. * @returns {Whether} the authentication is successful.
  24394. */
  24395. Yii.CBaseUserIdentity.prototype.getIsAuthenticated = function () {
  24396. return this.errorCode==this.ERROR_NONE;
  24397. };
  24398. /**
  24399. * Gets the persisted state by the specified name.
  24400. * @param {String} name the name of the state
  24401. * @param {Mixed} defaultValue the default value to be returned if the named state does not exist
  24402. * @returns {Mixed} the value of the named state
  24403. */
  24404. Yii.CBaseUserIdentity.prototype.getState = function (name, defaultValue) {
  24405. if (defaultValue === undefined) {
  24406. defaultValue = null;
  24407. }
  24408. return this._state[name] !== undefined?this._state[name]:defaultValue;
  24409. };
  24410. /**
  24411. * Sets the named state with a given value.
  24412. * @param {String} name the name of the state
  24413. * @param {Mixed} value the value of the named state
  24414. */
  24415. Yii.CBaseUserIdentity.prototype.setState = function (name, value) {
  24416. this._state[name]=value;
  24417. };
  24418. /**
  24419. * Removes the specified state.
  24420. * @param {String} name the name of the state
  24421. * @since 1.0.8
  24422. */
  24423. Yii.CBaseUserIdentity.prototype.clearState = function (name) {
  24424. delete this._state[name];
  24425. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  24426. /**
  24427. * CUserIdentity is a base class for representing identities that are authenticated based on a username and a password.
  24428. *
  24429. * Derived classes should implement {@link authenticate} with the actual
  24430. * authentication scheme (e.g. checking username and password against a DB table).
  24431. *
  24432. * By default, CUserIdentity assumes the {@link username} is a unique identifier
  24433. * and thus use it as the {@link id ID} of the identity.
  24434. *
  24435. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  24436. * @version $Id: CUserIdentity.php 2799 2011-01-01 19:31:13Z qiang.xue $
  24437. * @package system.web.auth
  24438. * @since 1.0
  24439. * @author Charles Pick
  24440. * @class
  24441. * @extends Yii.CBaseUserIdentity
  24442. */
  24443. Yii.CUserIdentity = function CUserIdentity (username, password) {
  24444. if (username !== false) {
  24445. this.construct(username, password);
  24446. }
  24447. };
  24448. Yii.CUserIdentity.prototype = new Yii.CBaseUserIdentity();
  24449. Yii.CUserIdentity.prototype.constructor = Yii.CUserIdentity;
  24450. /**
  24451. * @var {String} username
  24452. */
  24453. Yii.CUserIdentity.prototype.username = null;
  24454. /**
  24455. * @var {String} password
  24456. */
  24457. Yii.CUserIdentity.prototype.password = null;
  24458. /**
  24459. * Constructor.
  24460. * @param {String} username username
  24461. * @param {String} password password
  24462. */
  24463. Yii.CUserIdentity.prototype.construct = function (username, password) {
  24464. this.username=username;
  24465. this.password=password;
  24466. };
  24467. /**
  24468. * Authenticates a user based on {@link username} and {@link password}.
  24469. * Derived classes should override this method, or an exception will be thrown.
  24470. * This method is required by {@link IUserIdentity}.
  24471. * @returns {Boolean} whether authentication succeeds.
  24472. */
  24473. Yii.CUserIdentity.prototype.authenticate = function () {
  24474. throw new Yii.CException(Yii.t('yii','{class}::authenticate() must be implemented.',{'{class}':this.getClassName()}));
  24475. };
  24476. /**
  24477. * Returns the unique identifier for the identity.
  24478. * The default implementation simply returns {@link username}.
  24479. * This method is required by {@link IUserIdentity}.
  24480. * @returns {String} the unique identifier for the identity.
  24481. */
  24482. Yii.CUserIdentity.prototype.getId = function () {
  24483. return this.username;
  24484. };
  24485. /**
  24486. * Returns the display name for the identity.
  24487. * The default implementation simply returns {@link username}.
  24488. * This method is required by {@link IUserIdentity}.
  24489. * @returns {String} the display name for the identity.
  24490. */
  24491. Yii.CUserIdentity.prototype.getName = function () {
  24492. return this.username;
  24493. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  24494. /**
  24495. * CWebUser represents the persistent state for a Web application user.
  24496. *
  24497. * CWebUser is used as an application component whose ID is 'user'.
  24498. * Therefore, at any place one can access the user state via
  24499. * <code>Yii::app()->user</code>.
  24500. *
  24501. * CWebUser should be used together with an {@link IUserIdentity identity}
  24502. * which implements the actual authentication algorithm.
  24503. *
  24504. * A typical authentication process using CWebUser is as follows:
  24505. * <ol>
  24506. * <li>The user provides information needed for authentication.</li>
  24507. * <li>An {@link IUserIdentity identity instance} is created with the user-provided information.</li>
  24508. * <li>Call {@link IUserIdentity::authenticate} to check if the identity is valid.</li>
  24509. * <li>If valid, call {@link CWebUser::login} to login the user, and
  24510. * Redirect the user browser to {@link returnUrl}.</li>
  24511. * <li>If not valid, retrieve the error code or message from the identity
  24512. * instance and display it.</li>
  24513. * </ol>
  24514. *
  24515. * The property {@link id} and {@link name} are both identifiers
  24516. * for the user. The former is mainly used internally (e.g. primary key), while
  24517. * the latter is for display purpose (e.g. username). The {@link id} property
  24518. * is a unique identifier for a user that is persistent
  24519. * during the whole user session. It can be a username, or something else,
  24520. * depending on the implementation of the {@link IUserIdentity identity class}.
  24521. *
  24522. * Both {@link id} and {@link name} are persistent during the user session.
  24523. * Besides, an identity may have additional persistent data which can
  24524. * be accessed by calling {@link getState}.
  24525. * Note, when {@link allowAutoLogin cookie-based authentication} is enabled,
  24526. * all these persistent data will be stored in cookie. Therefore, do not
  24527. * store password or other sensitive data in the persistent storage. Instead,
  24528. * you should store them directly in session on the server side if needed.
  24529. *
  24530. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  24531. * @version $Id: CWebUser.php 3167 2011-04-07 04:25:27Z qiang.xue $
  24532. * @package system.web.auth
  24533. * @since 1.0
  24534. * @author Charles Pick
  24535. * @class
  24536. * @extends Yii.CApplicationComponent
  24537. */
  24538. Yii.CWebUser = function CWebUser() {
  24539. };
  24540. Yii.CWebUser.prototype = new Yii.CApplicationComponent();
  24541. Yii.CWebUser.prototype.constructor = Yii.CWebUser;
  24542. /**
  24543. * @const
  24544. */
  24545. Yii.CWebUser.prototype.FLASH_KEY_PREFIX = 'Yii.CWebUser.flash.';
  24546. /**
  24547. * @const
  24548. */
  24549. Yii.CWebUser.prototype.FLASH_COUNTERS ='Yii.CWebUser.flashcounters';
  24550. /**
  24551. * @const
  24552. */
  24553. Yii.CWebUser.prototype.STATES_VAR = '__states';
  24554. /**
  24555. * @const
  24556. */
  24557. Yii.CWebUser.prototype.AUTH_TIMEOUT_VAR = '__timeout';
  24558. /**
  24559. * @var {Boolean} whether to enable cookie-based login. Defaults to false.
  24560. */
  24561. Yii.CWebUser.prototype.allowAutoLogin = false;
  24562. /**
  24563. * @var {String} the name for a guest user. Defaults to 'Guest'.
  24564. * This is used by {@link getName} when the current user is a guest (not authenticated).
  24565. */
  24566. Yii.CWebUser.prototype.guestName = 'Guest';
  24567. /**
  24568. * @var {String|array} the URL for login. If using array, the first element should be
  24569. * the route to the login action, and the rest name-value pairs are GET parameters
  24570. * to construct the login URL (e.g. array('/site/login')). If this property is null,
  24571. * a 403 HTTP exception will be raised instead.
  24572. * @see CController::createUrl
  24573. */
  24574. Yii.CWebUser.prototype.loginUrl = ['/site/login'];
  24575. /**
  24576. * @var {Array} the property values (in name-value pairs) used to initialize the identity cookie.
  24577. * Any property of {@link CHttpCookie} may be initialized.
  24578. * This property is effective only when {@link allowAutoLogin} is true.
  24579. * @since 1.0.5
  24580. */
  24581. Yii.CWebUser.prototype.identityCookie = null;
  24582. /**
  24583. * @var {Integer} timeout in seconds after which user is logged out if inactive.
  24584. * If this property is not set, the user will be logged out after the current session expires
  24585. * (c.f. {@link CHttpSession::timeout}).
  24586. * @since 1.1.7
  24587. */
  24588. Yii.CWebUser.prototype.authTimeout = null;
  24589. /**
  24590. * @var {Boolean} whether to automatically renew the identity cookie each time a page is requested.
  24591. * Defaults to false. This property is effective only when {@link allowAutoLogin} is true.
  24592. * When this is false, the identity cookie will expire after the specified duration since the user
  24593. * is initially logged in. When this is true, the identity cookie will expire after the specified duration
  24594. * since the user visits the site the last time.
  24595. * @see allowAutoLogin
  24596. * @since 1.1.0
  24597. */
  24598. Yii.CWebUser.prototype.autoRenewCookie = false;
  24599. /**
  24600. * @var {Boolean} whether to automatically update the validity of flash messages.
  24601. * Defaults to true, meaning flash messages will be valid only in the current and the next requests.
  24602. * If this is set false, you will be responsible for ensuring a flash message is deleted after usage.
  24603. * (This can be achieved by calling {@link getFlash} with the 3rd parameter being true).
  24604. * @since 1.1.7
  24605. */
  24606. Yii.CWebUser.prototype.autoUpdateFlash = true;
  24607. Yii.CWebUser.prototype._keyPrefix = null;
  24608. Yii.CWebUser.prototype._access = [];
  24609. /**
  24610. * PHP magic method.
  24611. * This method is overriden so that persistent states can be accessed like properties.
  24612. * @param {String} name property name
  24613. * @returns {Mixed} property value
  24614. * @since 1.0.3
  24615. */
  24616. Yii.CWebUser.prototype.get = function (name) {
  24617. if(this.hasState(name)) {
  24618. return this.getState(name);
  24619. }
  24620. else {
  24621. return Yii.CApplicationComponent.prototype.get.call(this, name);
  24622. }
  24623. };
  24624. /**
  24625. * PHP magic method.
  24626. * This method is overriden so that persistent states can be set like properties.
  24627. * @param {String} name property name
  24628. * @param {Mixed} value property value
  24629. * @since 1.0.3
  24630. */
  24631. Yii.CWebUser.prototype.set = function (name, value) {
  24632. if(this.hasState(name)) {
  24633. this.setState(name,value);
  24634. }
  24635. else {
  24636. Yii.CApplicationComponent.prototype.set.call(this, name,value);
  24637. }
  24638. };
  24639. /**
  24640. * PHP magic method.
  24641. * This method is overriden so that persistent states can also be checked for null value.
  24642. * @param {String} name property name
  24643. * @since 1.0.3
  24644. */
  24645. Yii.CWebUser.prototype.isset = function (name) {
  24646. if(this.hasState(name)) {
  24647. return this.getState(name)!==null;
  24648. }
  24649. else {
  24650. return Yii.CApplicationComponent.prototype.isset.call(this,name);
  24651. }
  24652. };
  24653. /**
  24654. * PHP magic method.
  24655. * This method is overriden so that persistent states can also be unset.
  24656. * @param {String} name property name
  24657. * @throws {Yii.CException} if the property is read only.
  24658. * @since 1.0.3
  24659. */
  24660. Yii.CWebUser.prototype.unset = function (name) {
  24661. if(this.hasState(name)) {
  24662. this.setState(name,null);
  24663. }
  24664. else {
  24665. Yii.CApplicationComponent.prototype.unset.call(this, name);
  24666. }
  24667. };
  24668. /**
  24669. * Initializes the application component.
  24670. * This method overrides the parent implementation by starting session,
  24671. * performing cookie-based authentication if enabled, and updating the flash variables.
  24672. */
  24673. Yii.CWebUser.prototype.init = function () {
  24674. Yii.CApplicationComponent.prototype.init();
  24675. if(this.autoUpdateFlash) {
  24676. this.updateFlash();
  24677. }
  24678. this.updateAuthStatus();
  24679. };
  24680. /**
  24681. * Logs in a user.
  24682. *
  24683. * The user identity information will be saved in storage that is
  24684. * persistent during the user session. By default, the storage is simply
  24685. * the session storage. If the duration parameter is greater than 0,
  24686. * a cookie will be sent to prepare for cookie-based login in future.
  24687. *
  24688. * Note, you have to set {@link allowAutoLogin} to true
  24689. * if you want to allow user to be authenticated based on the cookie information.
  24690. *
  24691. * @param {IUserIdentity} identity the user identity (which should already be authenticated)
  24692. * @param {Integer} duration number of seconds that the user can remain in logged-in status. Defaults to 0, meaning login till the user closes the browser.
  24693. * If greater than 0, cookie-based login will be used. In this case, {@link allowAutoLogin}
  24694. * must be set true, otherwise an exception will be thrown.
  24695. */
  24696. Yii.CWebUser.prototype.login = function (identity, duration) {
  24697. var id, states;
  24698. if (duration === undefined) {
  24699. duration = 0;
  24700. }
  24701. id=identity.getId();
  24702. states=identity.getPersistentStates();
  24703. if(this.beforeLogin(id,states,false))
  24704. {
  24705. this.changeIdentity(id,identity.getName(),states);
  24706. if(duration>0)
  24707. {
  24708. if(this.allowAutoLogin) {
  24709. this.saveToCookie(duration);
  24710. }
  24711. else {
  24712. throw new Yii.CException(Yii.t('yii','{class}.allowAutoLogin must be set true in order to use cookie-based authentication.',
  24713. {'{class}':this.getClassName()}));
  24714. }
  24715. }
  24716. this.afterLogin(false);
  24717. }
  24718. };
  24719. /**
  24720. * Logs out the current user.
  24721. * This will remove authentication-related session data.
  24722. * If the parameter is true, the whole session will be destroyed as well.
  24723. * @param {Boolean} destroySession whether to destroy the whole session. Defaults to true. If false,
  24724. * then {@link clearStates} will be called, which removes only the data stored via {@link setState}.
  24725. * This parameter has been available since version 1.0.7. Before 1.0.7, the behavior
  24726. * is to destroy the whole session.
  24727. */
  24728. Yii.CWebUser.prototype.logout = function (destroySession) {
  24729. var cookie;
  24730. if (destroySession === undefined) {
  24731. destroySession = true;
  24732. }
  24733. if(this.beforeLogout()) {
  24734. if(this.allowAutoLogin) {
  24735. Yii.app().getRequest().getCookies().remove(this.getStateKeyPrefix());
  24736. if(this.identityCookie!==null) {
  24737. cookie=this.createIdentityCookie(this.getStateKeyPrefix());
  24738. cookie.value=null;
  24739. cookie.expire=0;
  24740. Yii.app().getRequest().getCookies().add(cookie.name,cookie);
  24741. }
  24742. }
  24743. if(destroySession) {
  24744. Yii.app().getSession().destroy();
  24745. }
  24746. else {
  24747. this.clearStates();
  24748. }
  24749. this.afterLogout();
  24750. }
  24751. };
  24752. /**
  24753. * @returns {Boolean} whether the current application user is a guest.
  24754. */
  24755. Yii.CWebUser.prototype.getIsGuest = function () {
  24756. return this.getState('__id')===null;
  24757. };
  24758. /**
  24759. * @returns {Mixed} the unique identifier for the user. If null, it means the user is a guest.
  24760. */
  24761. Yii.CWebUser.prototype.getId = function () {
  24762. return this.getState('__id');
  24763. };
  24764. /**
  24765. * @param {Mixed} value the unique identifier for the user. If null, it means the user is a guest.
  24766. */
  24767. Yii.CWebUser.prototype.setId = function (value) {
  24768. this.setState('__id',value);
  24769. };
  24770. /**
  24771. * Returns the unique identifier for the user (e.g. username).
  24772. * This is the unique identifier that is mainly used for display purpose.
  24773. * @returns {String} the user name. If the user is not logged in, this will be {@link guestName}.
  24774. */
  24775. Yii.CWebUser.prototype.getName = function () {
  24776. var name;
  24777. if((name=this.getState('__name'))!==null) {
  24778. return name;
  24779. }
  24780. else {
  24781. return this.guestName;
  24782. }
  24783. };
  24784. /**
  24785. * Sets the unique identifier for the user (e.g. username).
  24786. * @param {String} value the user name.
  24787. * @see getName
  24788. */
  24789. Yii.CWebUser.prototype.setName = function (value) {
  24790. this.setState('__name',value);
  24791. };
  24792. /**
  24793. * Returns the URL that the user should be redirected to after successful login.
  24794. * This property is usually used by the login action. If the login is successful,
  24795. * the action should read this property and use it to redirect the user browser.
  24796. * @param {String} defaultUrl the default return URL in case it was not set previously. If this is null,
  24797. * the application entry URL will be considered as the default return URL.
  24798. * @returns {String} the URL that the user should be redirected to after login.
  24799. * @see loginRequired
  24800. */
  24801. Yii.CWebUser.prototype.getReturnUrl = function (defaultUrl) {
  24802. if (defaultUrl === undefined) {
  24803. defaultUrl = null;
  24804. }
  24805. return this.getState('__returnUrl', defaultUrl===null ? Yii.app().getRequest().getScriptUrl() : Yii.CHtml.normalizeUrl(defaultUrl));
  24806. };
  24807. /**
  24808. * @param {String} value the URL that the user should be redirected to after login.
  24809. */
  24810. Yii.CWebUser.prototype.setReturnUrl = function (value) {
  24811. this.setState('__returnUrl',value);
  24812. };
  24813. /**
  24814. * Redirects the user browser to the login page.
  24815. * Before the redirection, the current URL (if it's not an AJAX url) will be
  24816. * kept in {@link returnUrl} so that the user browser may be redirected back
  24817. * to the current page after successful login. Make sure you set {@link loginUrl}
  24818. * so that the user browser can be redirected to the specified login URL after
  24819. * calling this method.
  24820. * After calling this method, the current request processing will be terminated.
  24821. */
  24822. Yii.CWebUser.prototype.loginRequired = function () {
  24823. var app, request, url, route;
  24824. app=Yii.app();
  24825. request=app.getRequest();
  24826. if(!request.getIsAjaxRequest()) {
  24827. this.setReturnUrl(request.getUrl());
  24828. }
  24829. if((url=this.loginUrl)!==null)
  24830. {
  24831. if(Object.prototype.toString.call(url) === '[object Array]')
  24832. {
  24833. route=url[0] !== undefined ? url[0] : app.defaultController;
  24834. url=app.createUrl(route,php.array_splice(url,1));
  24835. }
  24836. request.redirect(url);
  24837. }
  24838. else {
  24839. throw new Yii.CHttpException(403,Yii.t('yii','Login Required'));
  24840. }
  24841. };
  24842. /**
  24843. * This method is called before logging in a user.
  24844. * You may override this method to provide additional security check.
  24845. * For example, when the login is cookie-based, you may want to verify
  24846. * that the user ID together with a random token in the states can be found
  24847. * in the database. This will prevent hackers from faking arbitrary
  24848. * identity cookies even if they crack down the server private key.
  24849. * @param {Mixed} id the user ID. This is the same as returned by {@link getId()}.
  24850. * @param {Array} states a set of name-value pairs that are provided by the user identity.
  24851. * @param {Boolean} fromCookie whether the login is based on cookie
  24852. * @returns {Boolean} whether the user should be logged in
  24853. * @since 1.1.3
  24854. */
  24855. Yii.CWebUser.prototype.beforeLogin = function (id, states, fromCookie) {
  24856. return true;
  24857. };
  24858. /**
  24859. * This method is called after the user is successfully logged in.
  24860. * You may override this method to do some postprocessing (e.g. log the user
  24861. * login IP and time; load the user permission information).
  24862. * @param {Boolean} fromCookie whether the login is based on cookie.
  24863. * @since 1.1.3
  24864. */
  24865. Yii.CWebUser.prototype.afterLogin = function (fromCookie) {
  24866. };
  24867. /**
  24868. * This method is invoked when calling {@link logout} to log out a user.
  24869. * If this method return false, the logout action will be cancelled.
  24870. * You may override this method to provide additional check before
  24871. * logging out a user.
  24872. * @returns {Boolean} whether to log out the user
  24873. * @since 1.1.3
  24874. */
  24875. Yii.CWebUser.prototype.beforeLogout = function () {
  24876. return true;
  24877. };
  24878. /**
  24879. * This method is invoked right after a user is logged out.
  24880. * You may override this method to do some extra cleanup work for the user.
  24881. * @since 1.1.3
  24882. */
  24883. Yii.CWebUser.prototype.afterLogout = function () {
  24884. };
  24885. /**
  24886. * Populates the current user object with the information obtained from cookie.
  24887. * This method is used when automatic login ({@link allowAutoLogin}) is enabled.
  24888. * The user identity information is recovered from cookie.
  24889. * Sufficient security measures are used to prevent cookie data from being tampered.
  24890. * @see saveToCookie
  24891. */
  24892. Yii.CWebUser.prototype.restoreFromCookie = function () {
  24893. var app, cookie, data, id, name, duration, states;
  24894. app=Yii.app();
  24895. cookie=app.getRequest().getCookies().itemAt(this.getStateKeyPrefix());
  24896. if(cookie && !php.empty(cookie.value) && (data=app.getSecurityManager().validateData(cookie.value))!==false) {
  24897. data=Yii.CJSON.decode(data);
  24898. if(Object.prototype.toString.call(data) === '[object Array]' && data[0] !== undefined) {
  24899. id = data[0];
  24900. name = data[1];
  24901. duration = data[2];
  24902. states = data[3];
  24903. if(this.beforeLogin(id,states,true)) {
  24904. this.changeIdentity(id,name,states);
  24905. if(this.autoRenewCookie) {
  24906. cookie.expire=php.time()+duration;
  24907. app.getRequest().getCookies().add(cookie.name,cookie);
  24908. }
  24909. this.afterLogin(true);
  24910. }
  24911. }
  24912. }
  24913. };
  24914. /**
  24915. * Renews the identity cookie.
  24916. * This method will set the expiration time of the identity cookie to be the current time
  24917. * plus the originally specified cookie duration.
  24918. * @since 1.1.3
  24919. */
  24920. Yii.CWebUser.prototype.renewCookie = function () {
  24921. var cookies, cookie, data;
  24922. cookies=Yii.app().getRequest().getCookies();
  24923. cookie=cookies.itemAt(this.getStateKeyPrefix());
  24924. if(cookie && !php.empty(cookie.value) && (data=Yii.app().getSecurityManager().validateData(cookie.value))!==false) {
  24925. data=Yii.CJSON.decode(data);
  24926. if(Object.prototype.toString.call(data) === '[object Array]' && data[0] !== undefined) {
  24927. cookie.expire=php.time()+data[2];
  24928. cookies.add(cookie.name,cookie);
  24929. }
  24930. }
  24931. };
  24932. /**
  24933. * Saves necessary user data into a cookie.
  24934. * This method is used when automatic login ({@link allowAutoLogin}) is enabled.
  24935. * This method saves user ID, username, other identity states and a validation key to cookie.
  24936. * These information are used to do authentication next time when user visits the application.
  24937. * @param {Integer} duration number of seconds that the user can remain in logged-in status. Defaults to 0, meaning login till the user closes the browser.
  24938. * @see restoreFromCookie
  24939. */
  24940. Yii.CWebUser.prototype.saveToCookie = function (duration) {
  24941. var app, cookie, data;
  24942. app=Yii.app();
  24943. cookie=this.createIdentityCookie(this.getStateKeyPrefix());
  24944. cookie.expire=php.time()+duration;
  24945. data=[
  24946. this.getId(),
  24947. this.getName(),
  24948. duration,
  24949. this.saveIdentityStates()
  24950. ];
  24951. cookie.value=app.getSecurityManager().hashData(Yii.CJSON.encode(data));
  24952. app.getRequest().getCookies().add(cookie.name,cookie);
  24953. };
  24954. /**
  24955. * Creates a cookie to store identity information.
  24956. * @param {String} cookieName the cookie name
  24957. * @returns {Yii.CHttpCookie} the cookie used to store identity information
  24958. * @since 1.0.5
  24959. */
  24960. Yii.CWebUser.prototype.createIdentityCookie = function (cookieName) {
  24961. var name, cookie, value;
  24962. cookie=new Yii.CHttpCookie(cookieName,'');
  24963. if(Object.prototype.toString.call(this.identityCookie) === '[object Array]') {
  24964. for (name in this.identityCookie) {
  24965. if (this.identityCookie.hasOwnProperty(name)) {
  24966. value = this.identityCookie[name];
  24967. cookie.name=value;
  24968. }
  24969. }
  24970. }
  24971. return cookie;
  24972. };
  24973. /**
  24974. * @returns {String} a prefix for the name of the session variables storing user session data.
  24975. */
  24976. Yii.CWebUser.prototype.getStateKeyPrefix = function () {
  24977. if(this._keyPrefix!==null) {
  24978. return this._keyPrefix;
  24979. }
  24980. else {
  24981. return (this._keyPrefix=php.md5('Yii.'+php.get_class(this)+'.'+Yii.app().getId()));
  24982. }
  24983. };
  24984. /**
  24985. * @param {String} value a prefix for the name of the session variables storing user session data.
  24986. * @since 1.0.9
  24987. */
  24988. Yii.CWebUser.prototype.setStateKeyPrefix = function (value) {
  24989. this._keyPrefix=value;
  24990. };
  24991. /**
  24992. * Returns the value of a variable that is stored in user session.
  24993. *
  24994. * This function is designed to be used by CWebUser descendant classes
  24995. * who want to store additional user information in user session.
  24996. * A variable, if stored in user session using {@link setState} can be
  24997. * retrieved back using this function.
  24998. *
  24999. * @param {String} key variable name
  25000. * @param {Mixed} defaultValue default value
  25001. * @returns {Mixed} the value of the variable. If it doesn't exist in the session,
  25002. * the provided default value will be returned
  25003. * @see setState
  25004. */
  25005. Yii.CWebUser.prototype.getState = function (key, defaultValue) {
  25006. // TODO: Fix this !
  25007. var _SESSION = {};
  25008. if (defaultValue === undefined) {
  25009. defaultValue = null;
  25010. }
  25011. key=this.getStateKeyPrefix()+key;
  25012. return _SESSION[key] !== undefined ? _SESSION[key] : defaultValue;
  25013. };
  25014. /**
  25015. * Stores a variable in user session.
  25016. *
  25017. * This function is designed to be used by CWebUser descendant classes
  25018. * who want to store additional user information in user session.
  25019. * By storing a variable using this function, the variable may be retrieved
  25020. * back later using {@link getState}. The variable will be persistent
  25021. * across page requests during a user session.
  25022. *
  25023. * @param {String} key variable name
  25024. * @param {Mixed} value variable value
  25025. * @param {Mixed} defaultValue default value. If $value===$defaultValue, the variable will be
  25026. * removed from the session
  25027. * @see getState
  25028. */
  25029. Yii.CWebUser.prototype.setState = function (key, value, defaultValue) {
  25030. // TODO: Fix this!
  25031. var _SESSION = {};
  25032. if (defaultValue === undefined) {
  25033. defaultValue = null;
  25034. }
  25035. key=this.getStateKeyPrefix()+key;
  25036. if(value===defaultValue) {
  25037. delete _SESSION[key];
  25038. }
  25039. else {
  25040. _SESSION[key]=value;
  25041. }
  25042. };
  25043. /**
  25044. * Returns a value indicating whether there is a state of the specified name.
  25045. * @param {String} key state name
  25046. * @returns {Boolean} whether there is a state of the specified name.
  25047. * @since 1.0.3
  25048. */
  25049. Yii.CWebUser.prototype.hasState = function (key) {
  25050. // TODO: Fix this!
  25051. var _SESSION = {};
  25052. key=this.getStateKeyPrefix()+key;
  25053. return _SESSION[key] !== undefined;
  25054. };
  25055. /**
  25056. * Clears all user identity information from persistent storage.
  25057. * This will remove the data stored via {@link setState}.
  25058. */
  25059. Yii.CWebUser.prototype.clearStates = function () {
  25060. // TODO: Fix this!
  25061. var keys, _SESSION = {}, prefix, n, i, key;
  25062. keys=php.array_keys(_SESSION);
  25063. prefix=this.getStateKeyPrefix();
  25064. n=php.strlen(prefix);
  25065. for (i in keys) {
  25066. if (keys.hasOwnProperty(i)) {
  25067. key = keys[i];
  25068. if(!php.strncmp(key,prefix,n)) {
  25069. delete _SESSION[key];
  25070. }
  25071. }
  25072. }
  25073. };
  25074. /**
  25075. * Returns all flash messages.
  25076. * This method is similar to {@link getFlash} except that it returns all
  25077. * currently available flash messages.
  25078. * @param {Boolean} deleteVar whether to delete the flash messages after calling this method.
  25079. * @returns {Array} flash messages (key => message).
  25080. * @since 1.1.3
  25081. */
  25082. Yii.CWebUser.prototype.getFlashes = function (deleteVar) {
  25083. var flashes, prefix, keys, _SESSION = {}, n, i, key;
  25084. if (deleteVar === undefined) {
  25085. deleteVar = true;
  25086. }
  25087. flashes=[];
  25088. prefix=this.getStateKeyPrefix()+this.FLASH_KEY_PREFIX;
  25089. keys=php.array_keys(_SESSION);
  25090. n=php.strlen(prefix);
  25091. for (i in keys)
  25092. {
  25093. if (keys.hasOwnProperty(i)) {
  25094. key = keys[i];
  25095. if(!php.strncmp(key,prefix,n))
  25096. {
  25097. flashes[key.slice(n)]=_SESSION[key];
  25098. if(deleteVar) {
  25099. delete _SESSION[key];
  25100. }
  25101. }
  25102. }
  25103. }
  25104. if(deleteVar) {
  25105. this.setState(this.FLASH_COUNTERS,[]);
  25106. }
  25107. return flashes;
  25108. };
  25109. /**
  25110. * Returns a flash message.
  25111. * A flash message is available only in the current and the next requests.
  25112. * @param {String} key key identifying the flash message
  25113. * @param {Mixed} defaultValue value to be returned if the flash message is not available.
  25114. * @param {Boolean} deleteVar whether to delete this flash message after accessing it.
  25115. * Defaults to true. This parameter has been available since version 1.0.2.
  25116. * @returns {Mixed} the message message
  25117. */
  25118. Yii.CWebUser.prototype.getFlash = function (key, defaultValue, deleteVar) {
  25119. var value;
  25120. if (defaultValue === undefined) {
  25121. defaultValue = null;
  25122. }
  25123. if (deleteVar === undefined) {
  25124. deleteVar = true;
  25125. }
  25126. value=this.getState(this.FLASH_KEY_PREFIX+key,defaultValue);
  25127. if(deleteVar) {
  25128. this.setFlash(key,null);
  25129. }
  25130. return value;
  25131. };
  25132. /**
  25133. * Stores a flash message.
  25134. * A flash message is available only in the current and the next requests.
  25135. * @param {String} key key identifying the flash message
  25136. * @param {Mixed} value flash message
  25137. * @param {Mixed} defaultValue if this value is the same as the flash message, the flash message
  25138. * will be removed. (Therefore, you can use setFlash('key',null) to remove a flash message.)
  25139. */
  25140. Yii.CWebUser.prototype.setFlash = function (key, value, defaultValue) {
  25141. var counters;
  25142. if (defaultValue === undefined) {
  25143. defaultValue = null;
  25144. }
  25145. this.setState(this.FLASH_KEY_PREFIX+key,value,defaultValue);
  25146. counters=this.getState(this.FLASH_COUNTERS,[]);
  25147. if(value===defaultValue) {
  25148. delete counters[key];
  25149. }
  25150. else {
  25151. counters[key]=0;
  25152. }
  25153. this.setState(this.FLASH_COUNTERS,counters,[]);
  25154. };
  25155. /**
  25156. * @param {String} key key identifying the flash message
  25157. * @returns {Boolean} whether the specified flash message exists
  25158. */
  25159. Yii.CWebUser.prototype.hasFlash = function (key) {
  25160. return this.getFlash(key, null, false)!==null;
  25161. };
  25162. /**
  25163. * Changes the current user with the specified identity information.
  25164. * This method is called by {@link login} and {@link restoreFromCookie}
  25165. * when the current user needs to be populated with the corresponding
  25166. * identity information. Derived classes may override this method
  25167. * by retrieving additional user-related information. Make sure the
  25168. * parent implementation is called first.
  25169. * @param {Mixed} id a unique identifier for the user
  25170. * @param {String} name the display name for the user
  25171. * @param {Array} states identity states
  25172. */
  25173. Yii.CWebUser.prototype.changeIdentity = function (id, name, states) {
  25174. Yii.app().getSession().regenerateID();
  25175. this.setId(id);
  25176. this.setName(name);
  25177. this.loadIdentityStates(states);
  25178. };
  25179. /**
  25180. * Retrieves identity states from persistent storage and saves them as an array.
  25181. * @returns {Array} the identity states
  25182. */
  25183. Yii.CWebUser.prototype.saveIdentityStates = function () {
  25184. var states, nameDummy, name, dummy;
  25185. states=[];
  25186. nameDummy = this.getState(this.STATES_VAR,[]);
  25187. for (name in nameDummy) {
  25188. if (nameDummy.hasOwnProperty(name)) {
  25189. dummy = nameDummy[name];
  25190. states[name]=this.getState(name);
  25191. }
  25192. }
  25193. return states;
  25194. };
  25195. /**
  25196. * Loads identity states from an array and saves them to persistent storage.
  25197. * @param {Array} states the identity states
  25198. */
  25199. Yii.CWebUser.prototype.loadIdentityStates = function (states) {
  25200. var names, name, value;
  25201. names=[];
  25202. if(Object.prototype.toString.call(states) === '[object Array]') {
  25203. for (name in states) {
  25204. if (states.hasOwnProperty(name)) {
  25205. value = states[name];
  25206. this.setState(name,value);
  25207. names[name]=true;
  25208. }
  25209. }
  25210. }
  25211. this.setState(this.STATES_VAR,names);
  25212. };
  25213. /**
  25214. * Updates the internal counters for flash messages.
  25215. * This method is internally used by {@link CWebApplication}
  25216. * to maintain the availability of flash messages.
  25217. */
  25218. Yii.CWebUser.prototype.updateFlash = function () {
  25219. var counters, count, key;
  25220. counters=this.getState(this.FLASH_COUNTERS);
  25221. if(Object.prototype.toString.call(counters) !== '[object Array]') {
  25222. return;
  25223. }
  25224. for (key in counters) {
  25225. if (counters.hasOwnProperty(key)) {
  25226. count = counters[key];
  25227. if(count)
  25228. {
  25229. delete counters[key];
  25230. this.setState(this.FLASH_KEY_PREFIX+key,null);
  25231. }
  25232. else {
  25233. counters[key]++;
  25234. }
  25235. }
  25236. }
  25237. this.setState(this.FLASH_COUNTERS,counters,[]);
  25238. };
  25239. /**
  25240. * Updates the authentication status according to {@link authTimeout}.
  25241. * If the user has been inactive for {@link authTimeout} seconds,
  25242. * he will be automatically logged out.
  25243. * @since 1.1.7
  25244. */
  25245. Yii.CWebUser.prototype.updateAuthStatus = function () {
  25246. var expires;
  25247. if(this.authTimeout!==null && !this.getIsGuest()) {
  25248. expires=this.getState(this.AUTH_TIMEOUT_VAR);
  25249. if (expires!==null && expires < php.time()) {
  25250. this.logout(false);
  25251. }
  25252. else {
  25253. this.setState(this.AUTH_TIMEOUT_VAR,php.time()+this.authTimeout);
  25254. }
  25255. }
  25256. };
  25257. /**
  25258. * Performs access check for this user.
  25259. * @param {String} operation the name of the operation that need access check.
  25260. * @param {Array} params name-value pairs that would be passed to business rules associated
  25261. * with the tasks and roles assigned to the user.
  25262. * @param {Boolean} allowCaching whether to allow caching the result of access check.
  25263. * This parameter has been available since version 1.0.5. When this parameter
  25264. * is true (default), if the access check of an operation was performed before,
  25265. * its result will be directly returned when calling this method to check the same operation.
  25266. * If this parameter is false, this method will always call {@link CAuthManager::checkAccess}
  25267. * to obtain the up-to-date access result. Note that this caching is effective
  25268. * only within the same request.
  25269. * @returns {Boolean} whether the operations can be performed by this user.
  25270. */
  25271. Yii.CWebUser.prototype.checkAccess = function (operation, params, allowCaching) {
  25272. if (params === undefined) {
  25273. params = [];
  25274. }
  25275. if (allowCaching === undefined) {
  25276. allowCaching = true;
  25277. }
  25278. if(allowCaching && params===[] && this._access[operation] !== undefined) {
  25279. return this._access[operation];
  25280. }
  25281. else {
  25282. return (this._access[operation]=Yii.app().getAuthManager().checkAccess(operation,this.getId(),params));
  25283. }
  25284. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  25285. /**
  25286. * CFilterChain represents a list of filters being applied to an action.
  25287. *
  25288. * CFilterChain executes the filter list by {@link run()}.
  25289. *
  25290. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  25291. * @version $Id: CFilterChain.php 3001 2011-02-24 16:42:44Z alexander.makarow $
  25292. * @package system.web.filters
  25293. * @since 1.0
  25294. * @author Charles Pick
  25295. * @class
  25296. * @extends Yii.CList
  25297. */
  25298. Yii.CFilterChain = function CFilterChain (data, readOnly) {
  25299. if (data !== false) {
  25300. this.construct(data, readOnly);
  25301. }
  25302. };
  25303. Yii.CFilterChain.prototype = new Yii.CList(false);
  25304. Yii.CFilterChain.prototype.constructor = Yii.CFilterChain;
  25305. /**
  25306. * @var {Yii.CController} the controller who executes the action.
  25307. */
  25308. Yii.CFilterChain.prototype.controller = null;
  25309. /**
  25310. * @var {Yii.CAction} the action being filtered by this chain.
  25311. */
  25312. Yii.CFilterChain.prototype.action = null;
  25313. /**
  25314. * @var {Integer} the index of the filter that is to be executed when calling {@link run()}.
  25315. */
  25316. Yii.CFilterChain.prototype.filterIndex = 0;
  25317. /**
  25318. * Constructor.
  25319. * @param {Yii.CController} controller the controller who executes the action.
  25320. * @param {Yii.CAction} action the action being filtered by this chain.
  25321. */
  25322. Yii.CFilterChain.prototype.construct = function (controller, action) {
  25323. this.controller=controller;
  25324. this.action=action;
  25325. };
  25326. /**
  25327. * CFilterChain factory method.
  25328. * This method creates a CFilterChain instance.
  25329. * @param {Yii.CController} controller the controller who executes the action.
  25330. * @param {Yii.CAction} action the action being filtered by this chain.
  25331. * @param {Array} filters list of filters to be applied to the action.
  25332. */
  25333. Yii.CFilterChain.prototype.create = function (controller, action, filters) {
  25334. var chain, actionID, i, filter, pos, matched, filterClass;
  25335. chain=new Yii.CFilterChain(controller,action);
  25336. actionID=action.getId();
  25337. for (i in filters) {
  25338. if (filters.hasOwnProperty(i)) {
  25339. filter = filters[i];
  25340. if(typeof(filter) === 'string') {
  25341. // filterName [+|- action1 action2]
  25342. if((pos=php.strpos(filter,'+'))!==false || (pos=php.strpos(filter,'-'))!==false) {
  25343. matched=/\b{actionID}\b/i.exec(filter.slice(pos+1))>0;
  25344. if((filter[pos]==='+')===matched) {
  25345. filter=Yii.CInlineFilter.create(controller,php.trim(filter.slice(0, pos)));
  25346. }
  25347. }
  25348. else {
  25349. filter=Yii.CInlineFilter.create(controller,filter);
  25350. }
  25351. }
  25352. }
  25353. else if(typeof(filter) === "object") {
  25354. // array('path.to.class [+|- action1, action2]','param1'=>'value1',...)
  25355. if(filter[0] === undefined) {
  25356. throw new Yii.CException(Yii.t('yii','The first element in a filter configuration must be the filter class.'));
  25357. }
  25358. filterClass=filter[0];
  25359. delete filter[0];
  25360. if((pos=php.strpos(filterClass,'+'))!==false || (pos=php.strpos(filterClass,'-'))!==false) {
  25361. matched=((new RegExp("\\b" + actionID + "\\b","i")).exec(filterClass.slice(pos+1))>0);
  25362. if((filterClass[pos]==='+')===matched) {
  25363. filterClass=php.trim(filterClass.slice(0, pos));
  25364. }
  25365. else {
  25366. continue;
  25367. }
  25368. }
  25369. filter['class']=filterClass;
  25370. filter=Yii.createComponent(filter);
  25371. }
  25372. if (typeof filter === "object") {
  25373. filter.init();
  25374. chain.add(filter);
  25375. }
  25376. }
  25377. return chain;
  25378. };
  25379. /**
  25380. * Inserts an item at the specified position.
  25381. * This method overrides the parent implementation by adding
  25382. * additional check for the item to be added. In particular,
  25383. * only objects implementing {@link IFilter} can be added to the list.
  25384. * @param {Integer} index the specified position.
  25385. * @param {Mixed} item new item
  25386. * @throws {Yii.CException} If the index specified exceeds the bound or the list is read-only, or the item is not an {@link IFilter} instance.
  25387. */
  25388. Yii.CFilterChain.prototype.insertAt = function (index, item) {
  25389. if(item instanceof Yii.CFilter) {
  25390. Yii.CList.prototype.insertAt.call(this,index,item);
  25391. }
  25392. else {
  25393. throw new Yii.CException(Yii.t('yii','CFilterChain can only take objects implementing the IFilter interface.'));
  25394. }
  25395. };
  25396. /**
  25397. * Executes the filter indexed at {@link filterIndex}.
  25398. * After this method is called, {@link filterIndex} will be automatically incremented by one.
  25399. * This method is usually invoked in filters so that the filtering process
  25400. * can continue and the action can be executed.
  25401. */
  25402. Yii.CFilterChain.prototype.run = function () {
  25403. var filter;
  25404. if(this.offsetExists(this.filterIndex)) {
  25405. filter=this.itemAt(this.filterIndex++);
  25406. Yii.trace('Running filter '+(filter instanceof Yii.CInlineFilter ? this.controller.getClassName()+'.filter'+filter.name+'()':filter.getClassName()+'.filter()'),'system.web.filters.CFilterChain');
  25407. filter.filter(this);
  25408. }
  25409. else {
  25410. this.controller.runAction(this.action);
  25411. }
  25412. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  25413. /**
  25414. * CInlineFilter represents a filter defined as a controller method.
  25415. *
  25416. * CInlineFilter executes the 'filterXYZ($action)' method defined
  25417. * in the controller, where the name 'XYZ' can be retrieved from the {@link name} property.
  25418. *
  25419. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  25420. * @version $Id: CInlineFilter.php 3026 2011-03-06 10:41:56Z haertl.mike $
  25421. * @package system.web.filters
  25422. * @since 1.0
  25423. * @author Charles Pick
  25424. * @class
  25425. * @extends Yii.CFilter
  25426. */
  25427. Yii.CInlineFilter = function CInlineFilter () {
  25428. };
  25429. Yii.CInlineFilter.prototype = new Yii.CFilter();
  25430. Yii.CInlineFilter.prototype.constructor = Yii.CInlineFilter;
  25431. /**
  25432. * @var {String} name of the filter. It stands for 'XYZ' in the filter method name 'filterXYZ'.
  25433. */
  25434. Yii.CInlineFilter.prototype.name = null;
  25435. /**
  25436. * Creates an inline filter instance.
  25437. * The creation is based on a string describing the inline method name
  25438. * and action names that the filter shall or shall not apply to.
  25439. * @param {Yii.CController} controller the controller who hosts the filter methods
  25440. * @param {String} filterName the filter name
  25441. * @returns {Yii.CInlineFilter} the created instance
  25442. * @throws {Yii.CException} if the filter method does not exist
  25443. */
  25444. Yii.CInlineFilter.prototype.create = function (controller, filterName) {
  25445. var filter;
  25446. if(controller['filter'+php.ucfirst(filterName)] !== undefined) {
  25447. filter=new Yii.CInlineFilter();
  25448. filter.name=filterName;
  25449. return filter;
  25450. }
  25451. else {
  25452. throw new Yii.CException(Yii.t('yii','Filter "{filter}" is invalid. Controller "{class}" does not have the filter method "filter{filter}".',
  25453. {'{filter}':filterName, '{class}':controller.getClassName()}));
  25454. }
  25455. };
  25456. /**
  25457. * Performs the filtering.
  25458. * This method calls the filter method defined in the controller class.
  25459. * @param {Yii.CFilterChain} filterChain the filter chain that the filter is on.
  25460. */
  25461. Yii.CInlineFilter.prototype.filter = function (filterChain) {
  25462. var method;
  25463. method='filter'+php.ucfirst(this.name);
  25464. filterChain.controller[method](filterChain);
  25465. };/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  25466. /**
  25467. * CForm represents a form object that contains form input specifications.
  25468. *
  25469. * The main purpose of introducing the abstraction of form objects is to enhance the
  25470. * reusability of forms. In particular, we can divide a form in two parts: those
  25471. * that specify each individual form inputs, and those that decorate the form inputs.
  25472. * A CForm object represents the former part. It relies on the rendering process to
  25473. * accomplish form input decoration. Reusability is mainly achieved in the rendering process.
  25474. * That is, a rendering process can be reused to render different CForm objects.
  25475. *
  25476. * A form can be rendered in different ways. One can call the {@link render} method
  25477. * to get a quick form rendering without writing any HTML code; one can also override
  25478. * {@link render} to render the form in a different layout; and one can use an external
  25479. * view template to render each form element explicitly. In these ways, the {@link render}
  25480. * method can be applied to all kinds of forms and thus achieves maximum reusability;
  25481. * while the external view template keeps maximum flexibility in rendering complex forms.
  25482. *
  25483. * Form input specifications are organized in terms of a form element hierarchy.
  25484. * At the root of the hierarchy, it is the root CForm object. The root form object maintains
  25485. * its children in two collections: {@link elements} and {@link buttons}.
  25486. * The former contains non-button form elements ({@link CFormStringElement},
  25487. * {@link CFormInputElement} and CForm); while the latter mainly contains
  25488. * button elements ({@link CFormButtonElement}). When a CForm object is embedded in the
  25489. * {@link elements} collection, it is called a sub-form which can have its own {@link elements}
  25490. * and {@link buttons} collections and thus form the whole form hierarchy.
  25491. *
  25492. * Sub-forms are mainly used to handle multiple models. For example, in a user
  25493. * registration form, we can have the root form to collect input for the user
  25494. * table while a sub-form to collect input for the profile table. Sub-form is also
  25495. * a good way to partition a lengthy form into shorter ones, even though all inputs
  25496. * may belong to the same model.
  25497. *
  25498. * Form input specifications are given in terms of a configuration array which is
  25499. * used to initialize the property values of a CForm object. The {@link elements} and
  25500. * {@link buttons} properties need special attention as they are the main properties
  25501. * to be configured. To configure {@link elements}, we should give it an array like
  25502. * the following:
  25503. * <pre>
  25504. * 'elements':{
  25505. * 'username':{'type':'text', 'maxlength':80},
  25506. * 'password':{'type':'password', 'maxlength':80},
  25507. * }
  25508. * </pre>
  25509. * The above code specifies two input elements: 'username' and 'password'. Note the model
  25510. * object must have exactly the same attributes 'username' and 'password'. Each element
  25511. * has a type which specifies what kind of input should be used. The rest of the array elements
  25512. * (e.g. 'maxlength') in an input specification are rendered as HTML element attributes
  25513. * when the input field is rendered. The {@link buttons} property is configured similarly.
  25514. *
  25515. * For more details about configuring form elements, please refer to {@link CFormInputElement}
  25516. * and {@link CFormButtonElement}.
  25517. *
  25518. * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
  25519. * @version $Id: CForm.php 3076 2011-03-14 13:16:43Z qiang.xue $
  25520. * @package system.web.form
  25521. * @since 1.1
  25522. * @author Charles Pick
  25523. * @class
  25524. * @extends Yii.CFormElement
  25525. */
  25526. Yii.CForm = function CForm (config, model, parent) {
  25527. if (config !== false) {
  25528. this.construct(config, model, parent);
  25529. }
  25530. };
  25531. Yii.CForm.prototype = new Yii.CFormElement(false);
  25532. Yii.CForm.prototype.constructor = Yii.CForm;
  25533. /**
  25534. * @var {String} the title for this form. By default, if this is set, a fieldset may be rendered
  25535. * around the form body using the title as its legend. Defaults to null.
  25536. */
  25537. Yii.CForm.prototype.title = null;
  25538. /**
  25539. * @var {String} the description of this form.
  25540. */
  25541. Yii.CForm.prototype.description = null;
  25542. /**
  25543. * @var {String} the submission method of this form. Defaults to 'post'.
  25544. * This property is ignored when this form is a sub-form.
  25545. */
  25546. Yii.CForm.prototype.method = 'post';
  25547. /**
  25548. * @var {Mixed} the form action URL (see {@link CHtml::normalizeUrl} for details about this parameter.)
  25549. * Defaults to an empty string, meaning the current request URL.
  25550. * This property is ignored when this form is a sub-form.
  25551. */
  25552. Yii.CForm.prototype.action = '';
  25553. /**
  25554. * @var {String} the name of the class for representing a form input element. Defaults to 'CFormInputElement'.
  25555. */
  25556. Yii.CForm.prototype.inputElementClass = 'CFormInputElement';
  25557. /**
  25558. * @var {String} the name of the class for representing a form button element. Defaults to 'CFormButtonElement'.
  25559. */
  25560. Yii.CForm.prototype.buttonElementClass = 'CFormButtonElement';
  25561. /**
  25562. * @var {Array} HTML attribute values for the form tag. When the form is embedded within another form,
  25563. * this property will be used to render the HTML attribute values for the fieldset enclosing the child form.
  25564. */
  25565. Yii.CForm.prototype.attributes = {};
  25566. /**
  25567. * @var {Boolean} whether to show error summary. Defaults to false.
  25568. */
  25569. Yii.CForm.prototype.showErrorSummary = false;
  25570. /**
  25571. * @var {Array} the configuration used to create the active form widget.
  25572. * The widget will be used to render the form tag and the error messages.
  25573. * The 'class' option is required, which specifies the class of the widget.
  25574. * The rest of the options will be passed to {@link CBaseController::beginWidget()} call.
  25575. * Defaults to array('class'=>'CActiveForm').
  25576. * @since 1.1.1
  25577. */
  25578. Yii.CForm.prototype.activeForm = {'class':'CActiveForm'};
  25579. Yii.CForm.prototype._model = null;
  25580. Yii.CForm.prototype._elements = null;
  25581. Yii.CForm.prototype._buttons = null;
  25582. Yii.CForm.prototype._activeForm = null;
  25583. /**
  25584. * Constructor.
  25585. * If you override this method, make sure you do not modify the method
  25586. * signature, and also make sure you call the parent implementation.
  25587. * @param {Mixed} config the configuration for this form. It can be a configuration array
  25588. * or the path alias of a PHP script file that returns a configuration array.
  25589. * The configuration array consists of name-value pairs that are used to initialize
  25590. * the properties of this form.
  25591. * @param {Yii.CModel} model the model object associated with this form. If it is null,
  25592. * the parent's model will be used instead.
  25593. * @param {Mixed} parent the direct parent of this form. This could be either a {@link CBaseController}
  25594. * object (a controller or a widget), or a {@link CForm} object.
  25595. * If the former, it means the form is a top-level form; if the latter, it means this form is a sub-form.
  25596. */
  25597. Yii.CForm.prototype.construct = function (config, model, parent) {
  25598. if (model === undefined) {
  25599. model = null;
  25600. }
  25601. if (parent === undefined) {
  25602. parent = null;
  25603. }
  25604. this.setModel(model);
  25605. if(parent===null) {
  25606. parent=Yii.app().getController();
  25607. }
  25608. Yii.CFormElement.prototype.construct.call(this,config,parent);
  25609. this.init();
  25610. };
  25611. /**
  25612. * Initializes this form.
  25613. * This method is invoked at the end of the constructor.
  25614. * You may override this method to provide customized initialization (such as
  25615. * configuring the form object).
  25616. */
  25617. Yii.CForm.prototype.init = function () {
  25618. };
  25619. /**
  25620. * Returns a value indicating whether this form is submitted.
  25621. * @param {String} buttonName the name of the submit button
  25622. * @param {Boolean} loadData whether to call {@link loadData} if the form is submitted so that
  25623. * the submitted data can be populated to the associated models.
  25624. * @returns {Boolean} whether this form is submitted.
  25625. * @see loadData
  25626. */
  25627. Yii.CForm.prototype.submitted = function (buttonName, loadData) {
  25628. var ret;
  25629. if (buttonName === undefined) {
  25630. buttonName = 'submit';
  25631. }
  25632. if (loadData === undefined) {
  25633. loadData = true;
  25634. }
  25635. ret=this.clicked(this.getUniqueId()) && this.clicked(buttonName);
  25636. if(ret && loadData) {
  25637. this.loadData();
  25638. }
  25639. return ret;
  25640. };
  25641. /**
  25642. * Returns a value indicating whether the specified button is clicked.
  25643. * @param {String} name the button name
  25644. * @returns {Boolean} whether the button is clicked.
  25645. */
  25646. Yii.CForm.prototype.clicked = function (name) {
  25647. return Yii.app().getRequest().getParam(name) !== undefined;
  25648. };
  25649. /**
  25650. * Validates the models associated with this form.
  25651. * All models, including those associated with sub-forms, will perform
  25652. * the validation. You may use {@link CModel::getErrors()} to retrieve the validation
  25653. * error messages.
  25654. * @returns {Boolean} whether all models are valid
  25655. */
  25656. Yii.CForm.prototype.validate = function () {
  25657. var ret, i, modelList, model;
  25658. ret=true;
  25659. modelList = this.getModels();
  25660. for (i in modelList) {
  25661. if (modelList.hasOwnProperty(i)) {
  25662. model = modelList[i];
  25663. ret=model.validate() && ret;
  25664. }
  25665. }
  25666. return ret;
  25667. };
  25668. /**
  25669. * Loads the submitted data into the associated model(s) to the form.
  25670. * This method will go through all models associated with this form and its sub-forms
  25671. * and massively assign the submitted data to the models.
  25672. * @see submitted
  25673. */
  25674. Yii.CForm.prototype.loadData = function () {
  25675. var classVar;
  25676. if(this._model!==null) {
  25677. classVar=this._model.getClassName();
  25678. if(Yii.app().getRequest().params[classVar] !== undefined) {
  25679. this._model.setAttributes(Yii.app().getRequest().params[classVar]);
  25680. }
  25681. }
  25682. this.getElements().forEach(function(i, element) {
  25683. if(element instanceof Yii.CForm) {
  25684. element.loadData();
  25685. }
  25686. });
  25687. };
  25688. /**
  25689. * @returns {Yii.CForm} the top-level form object
  25690. */
  25691. Yii.CForm.prototype.getRoot = function () {
  25692. var root;
  25693. root=this;
  25694. while(root.getParent() instanceof Yii.CForm) {
  25695. root=root.getParent();
  25696. }
  25697. return root;
  25698. };
  25699. /**
  25700. * @returns {Yii.CActiveForm} the active form widget associated with this form.
  25701. * This method will return the active form widget as specified by {@link activeForm}.
  25702. * @since 1.1.1
  25703. */
  25704. Yii.CForm.prototype.getActiveFormWidget = function () {
  25705. if(this._activeForm!==null) {
  25706. return this._activeForm;
  25707. }
  25708. else {
  25709. return this.getRoot()._activeForm;
  25710. }
  25711. };
  25712. /**
  25713. * @returns {Yii.CBaseController} the owner of this form. This refers to either a controller or a widget
  25714. * by which the form is created and rendered.
  25715. */
  25716. Yii.CForm.prototype.getOwner = function () {
  25717. var owner;
  25718. owner=this.getParent();
  25719. while(owner instanceof Yii.CForm) {
  25720. owner=owner.getParent();
  25721. }
  25722. return owner;
  25723. };
  25724. /**
  25725. * Returns the model that this form is associated with.
  25726. * @param {Boolean} checkParent whether to return parent's model if this form doesn't have model by itself.
  25727. * @returns {Yii.CModel} the model associated with this form. If this form does not have a model,
  25728. * it will look for a model in its ancestors.
  25729. */
  25730. Yii.CForm.prototype.getModel = function (checkParent) {
  25731. var form;
  25732. if (checkParent === undefined) {
  25733. checkParent = true;
  25734. }
  25735. if(!checkParent) {
  25736. return this._model;
  25737. }
  25738. form=this;
  25739. while(form._model===null && form.getParent() instanceof Yii.CForm) {
  25740. form=form.getParent();
  25741. }
  25742. return form._model;
  25743. };
  25744. /**
  25745. * @param {Yii.CModel} model the model to be associated with this form
  25746. */
  25747. Yii.CForm.prototype.setModel = function (model) {
  25748. this._model=model;
  25749. };
  25750. /**
  25751. * Returns all models that are associated with this form or its sub-forms.
  25752. * @returns {Array} the models that are associated with this form or its sub-forms.
  25753. */
  25754. Yii.CForm.prototype.getModels = function () {
  25755. var models, i, elementList, element;
  25756. models=[];
  25757. if(this._model!==null) {
  25758. models.push(this._model);
  25759. }
  25760. this.getElements().forEach(function(i, element) {
  25761. if(element instanceof Yii.CForm) {
  25762. models=php.array_merge(models,element.getModels());
  25763. }
  25764. });
  25765. return models;
  25766. };
  25767. /**
  25768. * Returns the input elements of this form.
  25769. * This includes text strings, input elements and sub-forms.
  25770. * Note that the returned result is a {@link CFormElementCollection} object, which
  25771. * means you can use it like an array. For more details, see {@link CMap}.
  25772. * @returns {Yii.CFormElementCollection} the form elements.
  25773. */
  25774. Yii.CForm.prototype.getElements = function () {
  25775. if(this._elements===null) {
  25776. this._elements=new Yii.CFormElementCollection(this,false);
  25777. }
  25778. return this._elements;
  25779. };
  25780. /**
  25781. * Configures the input elements of this form.
  25782. * The configuration must be an array of input configuration array indexed by input name.
  25783. * Each input configuration array consists of name-value pairs that are used to initialize
  25784. * a {@link CFormStringElement} object (when 'type' is 'string'), a {@link CFormElement} object
  25785. * (when 'type' is a string ending with 'Form'), or a {@link CFormInputElement} object in
  25786. * all other cases.
  25787. * @param {Array} elements the button configurations
  25788. */
  25789. Yii.CForm.prototype.setElements = function (elements) {
  25790. var collection, name, config;
  25791. collection=this.getElements();
  25792. Yii.forEach(elements,function (name, config) {
  25793. collection.add(name,config);
  25794. });
  25795. };
  25796. /**
  25797. * Returns the button elements of this form.
  25798. * Note that the returned result is a {@link CFormElementCollection} object, which
  25799. * means you can use it like an array. For more details, see {@link CMap}.
  25800. * @returns {Yii.CFormElementCollection} the form elements.
  25801. */
  25802. Yii.CForm.prototype.getButtons = function () {
  25803. if(this._buttons===null) {
  25804. this._buttons=new Yii.CFormElementCollection(this,true);
  25805. }
  25806. return this._buttons;
  25807. };
  25808. /**
  25809. * Configures the buttons of this form.
  25810. * The configuration must be an array of button configuration array indexed by button name.
  25811. * Each button configuration array consists of name-value pairs that are used to initialize
  25812. * a {@link CFormButtonElement} object.
  25813. * @param {Array} buttons the button configurations
  25814. */
  25815. Yii.CForm.prototype