From 90de6081224723aaea97522290a80e764a6b0900 Mon Sep 17 00:00:00 2001 From: carl <> Date: Sun, 5 Aug 2007 14:37:09 +0000 Subject: #677 - Improved error reporting for the TInvalidDataValueException --- framework/Exceptions/messages.txt | 844 +++++++++---------- framework/TComponent.php | 1682 ++++++++++++++++++------------------- 2 files changed, 1263 insertions(+), 1263 deletions(-) diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 24bb417a..372b8501 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -1,423 +1,423 @@ -prado_application_singleton_required = Prado.Application must only be set once. -prado_component_unknown = Unknown component type '{0}'. This may be caused by following parsing error in the {0} class file: {1} -prado_using_invalid = '{0}' is not a valid namespace to be used. Make sure '.*' is appended if you want to use a namespace referring to a directory. -prado_alias_redefined = Alias '{0}' cannot be redefined. -prado_alias_invalid = Alias '{0}' refers to an invalid path '{1}'. Only existing directories can be aliased. -prado_aliasname_invalid = Alias '{0}' contains invalid character '.'. - -component_property_undefined = Component property '{0}.{1}' is not defined. -component_property_readonly = Component property '{0}.{1}' is read-only. -component_event_undefined = Component event '{0}.{1}' is not defined. -component_eventhandler_invalid = Component event '{0}.{1}' is attached with an invalid event handler. -component_expression_invalid = Component '{0}' is evaluating an invalid expression '{1}' : {2}. -component_statements_invalid = Component '{0}' is evaluating invalid PHP statements '{1}' : {2}. - -propertyvalue_enumvalue_invalid = Value '{0}' is a not valid enumeration value ({1}). - -list_index_invalid = Index '{0}' is out of range. -list_item_inexistent = The item cannot be found in the list. -list_data_not_iterable = Data must be either an array or an object implementing Traversable interface. -list_readonly = {0} is read-only. - -map_addition_disallowed = The new item cannot be added to the map. -map_item_unremovable = The item cannot be removed from the map. -map_data_not_iterable = Data must be either an array or an object implementing Traversable interface. -map_readonly = {0} is read-only. - -application_includefile_invalid = Unable to find application configuration {0}. Make sure it is in namespace format and the file ends with ".xml". -application_basepath_invalid = Application base path '{0}' does not exist or is not a directory. -application_runtimepath_invalid = Application runtime path '{0}' does not exist or is not writable by Web server process. -application_service_invalid = Service '{0}' must implement IService interface. -application_service_unknown = Requested service '{0}' is not defined. -application_unavailable = Application is unavailable at this time. -application_service_unavailable = Service '{0}' is unavailable at this time. -application_moduleid_duplicated = Application module ID '{0}' is not unique. -application_runtimepath_failed = Unable to create runtime path '{0}'. Make sure the parent directory exists and is writable by the Web process. - -appconfig_aliaspath_invalid = Application configuration uses an invalid file path "{1}". -appconfig_alias_invalid = Application configuration element must have an "id" attribute and a "path" attribute. -appconfig_alias_redefined = Application configuration cannot be redefined. -appconfig_using_invalid = Application configuration element must have a "namespace" attribute. -appconfig_moduleid_required = Application configuration element must have an "id" attribute. -appconfig_moduletype_required = Application configuration must have a "class" attribute. -appconfig_serviceid_required = Application configuration element must have an "id" attribute. -appconfig_servicetype_required = Application configuration must have a "class" attribute. -appconfig_parameterid_required = Application configuration element must have an "id" attribute. -appconfig_includefile_required = Application configuration element must have a "file" attribute. - -securitymanager_validationkey_invalid = TSecurityManager.ValidationKey must not be empty. -securitymanager_encryptionkey_invalid = TSecurityManager.EncryptionKey must not be empty. -securitymanager_mcryptextension_required = Mcrypt PHP extension is required in order to use TSecurityManager's encryption feature. - -uri_format_invalid = '{0}' is not a valid URI. - -httprequest_separator_invalid = THttpRequest.UrlParamSeparator can only contain a single character. -httprequest_urlmanager_inexist = THttpRequest.UrlManager '{0}' does not point to an existing module. -httprequest_urlmanager_invalid = THttpRequest.UrlManager '{0}' must point to a module extending from TUrlManager. - -httpcookiecollection_httpcookie_required = THttpCookieCollection can only accept THttpCookie objects. - -httpresponse_bufferoutput_unchangeable = THttpResponse.BufferOutput cannot be modified after THttpResponse is initialized. -httpresponse_file_inexistent = THttpResponse cannot send file '{0}'. The file does not exist. - -httpsession_sessionid_unchangeable = THttpSession.SessionID cannot be modified after the session is started. -httpsession_sessionname_unchangeable = THttpSession.SessionName cannot be modified after the session is started. -httpsession_sessionname_invalid = THttpSession.SessionName must contain alphanumeric characters only. -httpsession_savepath_unchangeable = THttpSession.SavePath cannot be modified after the session is started. -httpsession_savepath_invalid = THttpSession.SavePath '{0}' is invalid. -httpsession_storage_unchangeable = THttpSession.Storage cannot be modified after the session is started. -httpsession_cookiemode_unchangeable = THttpSession.CookieMode cannot be modified after the session is started. -httpsession_autostart_unchangeable = THttpSession.AutoStart cannot be modified after the session module is initialized. -httpsession_gcprobability_unchangeable = THttpSession.GCProbability cannot be modified after the session is started. -httpsession_gcprobability_invalid = THttpSession.GCProbability must be an integer between 0 and 100. -httpsession_transid_unchangeable = THttpSession.UseTransparentSessionID cannot be modified after the session is started. -httpsession_maxlifetime_unchangeable = THttpSession.Timeout cannot be modified after the session is started. - -assetmanager_basepath_invalid = TAssetManager.BasePath '{0}' is invalid. Make sure it is in namespace form and points to a directory writable by the Web server process. -assetmanager_basepath_unchangeable = TAssetManager.BasePath cannot be modified after the module is initialized. -assetmanager_baseurl_unchangeable = TAssetManager.BaseUrl cannot be modified after the module is initialized. -assetmanager_filepath_invalid = TAssetManager is publishing an invalid file '{0}'. -assetmanager_tarchecksum_invalid = TAssetManager is publishing a tar file with invalid checksum '{0}'. -assetmanager_tarfile_invalid = TAssetManager is publishing an invalid tar file '{0}'. -assetmanager_source_directory_invalid = TAssetManager is copying an invalid directory '{0}'. - -cache_primary_duplicated = At most one primary cache module is allowed. {0} is trying to register as another primary cache. -sqlitecache_extension_required = TSqliteCache requires SQLite PHP extension. -sqlitecache_dbfile_required = TSqliteCache.DbFile is required. -sqlitecache_connection_failed = TSqliteCache database connection failed. {0}. -sqlitecache_table_creation_failed = TSqliteCache failed to create cache database. {0}. -sqlitecache_dbfile_unchangeable = TSqliteCache.DbFile cannot be modified after the module is initialized. -sqlitecache_dbfile_invalid = TSqliteCache.DbFile is invalid. Make sure it is in a proper namespace format. - -memcache_extension_required = TMemCache requires memcache PHP extension. -memcache_connection_failed = TMemCache failed to connect to memcache server {0}:{1}. -memcache_host_unchangeable = TMemCache.Host cannot be modified after the module is initialized. -memcache_port_unchangeable = TMemCache.Port cannot be modified after the module is initialized. - -apccache_extension_required = TAPCCache requires APC PHP extension. -apccache_add_unsupported = TAPCCache.add() is not supported. -apccache_replace_unsupported = TAPCCache.replace() is not supported. -apccache_extension_not_enabled = TAPCCache need apc.enabled = 1 in php.ini in order to work. -apccache_extension_not_enabled_cli = TAPCCache need apc.enable_cli = 1 in php.ini in order to work with PHP from the command line. - -errorhandler_errortemplatepath_invalid = TErrorHandler.ErrorTemplatePath '{0}' is invalid. Make sure it is in namespace form and points to a valid directory containing error template files. - -pageservice_page_unknown = Page '{0}' Not Found -pageservice_pageclass_unknown = Page class '{0}' is unknown. -pageservice_basepath_invalid = TPageService.BasePath '{0}' is not a valid directory. -pageservice_page_required = Page Name Required -pageservice_defaultpage_unchangeable = TPageService.DefaultPage cannot be modified after the service is initialized. -pageservice_basepath_unchangeable = TPageService.BasePath cannot be modified after the service is initialized. -pageservice_pageclass_invalid = Page class {0} is invalid. It should be TPage or extend from TPage. -pageservice_includefile_invalid = Unable to find page service configuration {0}. Make sure it is in namespace format and the file ends with ".xml". - -pageserviceconf_file_invalid = Unable to open page directory configuration file '{0}'. -pageserviceconf_aliaspath_invalid = uses an invalid file path "{1}" in page directory configuration file '{2}'. -pageserviceconf_alias_invalid = element must have an "id" attribute and a "path" attribute in page directory configuration file '{0}'. -pageserviceconf_using_invalid = element must have a "namespace" attribute in page directory configuration file '{0}'. -pageserviceconf_module_invalid = element must have an "id" attribute in page directory configuration file '{0}'. -pageserviceconf_moduletype_required = must have a "class" attribute in page directory configuration file '{1}'. -pageserviceconf_parameter_invalid = element must have an "id" attribute in page directory configuration file '{0}'. -pageserviceconf_page_invalid = element must have an "id" attribute in page directory configuration file '{0}'. -pageserviceconf_includefile_required = Page configuration element must have a "file" attribute. - -template_closingtag_unexpected = Unexpected closing tag '{0}' is found. -template_closingtag_expected = Closing tag '{0}' is expected. -template_directive_nonunique = Directive '<%@ ... %>' must appear at the beginning of the template and can appear at most once. -template_comments_forbidden = Template comments are not allowed within property tags. -template_matching_unexpected = Unexpected matching. -template_property_unknown = {0} has no property called '{1}'. -template_event_unknown = {0} has no event called '{1}'. -template_property_readonly = {0} has a read-only property '{1}'. -template_event_forbidden = {0} is a non-control component. No handler can be attached to its event '{1}' in a template. -template_databind_forbidden = {0} is a non-control component. Expressions cannot be bound to its property '{1}'. -template_component_required = '{0}' is not a component. Only components can appear in a template. -template_format_invalid = Invalid template syntax: {0} -template_property_duplicated = Property {0} is configured twice or more. -template_eventhandler_invalid = {0}.{1} can only accept a static string. -template_controlid_invalid = {0}.ID can only accept a static text string. -template_controlskinid_invalid = {0}.SkinID can only accept a static text string. -template_content_unexpected = Unexpected content is encountered when instantiating template: {0}. -template_include_invalid = Invalid template inclusion. Make sure {0} is a valid namespace pointing to an existing template file whose extension is .tpl. -template_tag_unexpected = Initialization for property {0} contains an unknown tag type {1}. - -xmldocument_file_read_failed = TXmlDocument is unable to read file '{0}'. -xmldocument_file_write_failed = TXmlDocument is unable to write file '{0}'. - -xmlelementlist_xmlelement_required = TXmlElementList can only accept TXmlElement objects. - -authorizationrule_action_invalid = TAuthorizationRule.Action can only take 'allow' or 'deny' as the value. -authorizationrule_verb_invalid = TAuthorizationRule.Verb can only take 'get' or 'post' as the value. - -authorizationrulecollection_authorizationrule_required = TAuthorizationRuleCollection can only accept TAuthorizationRule objects. - -usermanager_userfile_invalid = TUserManager.UserFile '{0}' is not a valid file. -usermanager_userfile_unchangeable = TUserManager.UserFile cannot be modified. The user module has been initialized already. - -authmanager_usermanager_required = TAuthManager.UserManager must be assigned a value. -authmanager_usermanager_inexistent = TAuthManager.UserManager '{0}' does not refer to an ID of application module. -authmanager_usermanager_invalid = TAuthManager.UserManager '{0}' does not refer to a valid TUserManager application module. -authmanager_usermanager_unchangeable = TAuthManager.UserManager cannot be modified after the module is initialized. -authmanager_session_required = TAuthManager requires a session application module. - -thememanager_service_unavailable = TThemeManager requires TPageService to be available. This error often occurs when you configure TThemeManager outside of the page service configuration. -thememanager_basepath_invalid = TThemeManager.BasePath '{0}' is not a valid path alias. Make sure you have defined this alias in configuration and it points to a valid directory. -thememanager_basepath_invalid2 = TThemeManager.BasePath '{0}' is not a valid directory. -thememanager_basepath_unchangeable = TThemeManager.BasePath cannot be modified after the module is initialized. - -theme_baseurl_required = TThemeManager.BasePath is required. By default, a directory named 'themes' under the directory containing the application entry script is assumed. -theme_path_inexistent = Theme path '{0}' does not exist. -theme_control_nested = Skin for control type '{0}' in theme '{1}' cannot be within another skin. -theme_skinid_duplicated = SkinID '{0}.{1}' is duplicated in theme '{2}'. -theme_databind_forbidden = Databind cannot be used in theme '{0}' for control skin '{1}.{2}' about property '{3}'. -theme_property_readonly = Skin is being applied to a read-only control property '{0}.{1}'. -theme_property_undefined = Skin is being applied to an inexistent control property '{0}.{1}'. -theme_tag_unexpected = Initialization for property {0} contains an unknown tag type {1}. - -control_object_reregistered = Duplicated object ID '{0}' found. -control_id_invalid = {0}.ID '{1}' is invalid. Only alphanumeric and underline characters are allowed. The first character must be an alphabetic or underline character. -control_skinid_unchangeable = {0}.SkinID cannot be modified after a skin has been applied to the control or the child controls have been created. -control_enabletheming_unchangeable = {0}.EnableTheming cannot be modified after the child controls have been created. -control_stylesheet_applied = StyleSheet skin has already been applied to {0}. -control_id_nonunique = {0}.ID '{1}' is not unique among all controls under the same naming container. - -templatecontrol_mastercontrol_invalid = Master control must be of type TTemplateControl or a child class. -templatecontrol_mastercontrol_required = Control '{0}' requires a master control since the control uses TContent. -templatecontrol_contentid_duplicated = TContent ID '{0}' is duplicated. -templatecontrol_placeholderid_duplicated= TContentPlaceHolder ID '{0}' is duplicated. -templatecontrol_directive_invalid = {0}.{1} can only accept a static text string through a template directive. -templatecontrol_placeholder_inexistent = TContent '{0}' does not have a matching TContentPlaceHolder. - -page_form_duplicated = A page can contain at most one TForm. Use regular HTML form tags for the rest forms. -page_isvalid_unknown = TPage.IsValid has not been evaluated yet. -page_postbackcontrol_invalid = Unable to determine postback control '{0}'. -page_control_outofform = {0} '{1}' must be enclosed within TForm. -page_head_duplicated = A page can contain at most one THead. -page_head_required = A THead control is needed in page template in order to render CSS and js in the HTML head section. -page_statepersister_invalid = Page state persister must implement IPageStatePersister interface. - -csmanager_pradoscript_invalid = Unknown Prado script library name '{0}'. -csmanager_invalid_packages = Unkownn packages '{1}' for javascript packages defined in '{0}'. Valid packages are '{2}'. - -contentplaceholder_id_required = TContentPlaceHolder must have an ID. - -content_id_required = TContent must have an ID. - -controlcollection_control_required = TControlList can only accept strings or TControl objects. - -webcontrol_accesskey_invalid = {0}.AccessKey '{1}' is invalid. It must be a single character only. -webcontrol_style_invalid = {0}.Style must take string value only. - -listcontrol_selection_invalid = {0} has an invalid selection that is set before performing databinding. -listcontrol_selectedindex_invalid = {0}.SelectedIndex has an invalid value {1}. -listcontrol_selectedvalue_invalid = {0}.SelectedValue has an invalid value '{1}'. -listcontrol_expression_invalid = {0} is evaluating an invalid expression '{1}' : {2} -listcontrol_multiselect_unsupported = {0} does not support multiselection. - -label_associatedcontrol_invalid = TLabel.AssociatedControl '{0}' cannot be found. - -hiddenfield_focus_unsupported = THiddenField does not support setting input focus. -hiddenfield_theming_unsupported = THiddenField does not support theming. -hiddenfield_skinid_unsupported = THiddenField does not support control skin. - -panel_defaultbutton_invalid = TPanel.DefaultButton '{0}' does not refer to an existing button control. - -tablestyle_cellpadding_invalid = TTableStyle.CellPadding must take an integer equal to or greater than -1. -tablestyle_cellspacing_invalid = TTableStyle.CellSpacing must take an integer equal to or greater than -1. - -pagestatepersister_pagestate_corrupted = Page state is corrupted. - -sessionpagestatepersister_pagestate_corrupted = Page state is corrupted. -sessionpagestatepersister_historysize_invalid = TSessionPageStatePersister.History must be an integer greater than 0. - -listitemcollection_item_invalid = TListItemCollection can only take strings or TListItem objects. - -dropdownlist_selectedindices_unsupported= TDropDownList.SelectedIndices is read-only. - -bulletedlist_autopostback_unsupported = TBulletedList.AutoPostBack is read-only. -bulletedlist_selectedindex_unsupported = TBulletedList.SelectedIndex is read-only. -bulletedlist_selectedindices_unsupported= TBulletedList.SelectedIndices is read-only. -bulletedlist_selectedvalue_unsupported = TBulletedList.SelectedValue is read-only. - -radiobuttonlist_selectedindices_unsupported = TRadioButtonList.SelectedIndices is read-only. - -logrouter_configfile_invalid = TLogRouter.ConfigFile '{0}' does not exist. -logrouter_routeclass_required = Class attribute is required in configuration. -logrouter_routetype_required = Log route must be an instance of TLogRoute or its derived class. - -filelogroute_logpath_invalid = TFileLogRoute.LogPath '{0}' must be a directory in namespace format and must be writable by the Web server process. -filelogroute_maxfilesize_invalid = TFileLogRoute.MaxFileSize must be greater than 0. -filelogroute_maxlogfiles_invalid = TFileLogRoute.MaxLogFiles must be greater than 0. - -emaillogroute_sentfrom_required = TEmailLogRoute.SentFrom cannot be empty. - -repeatinfo_repeatcolumns_invalid = TRepeatInfo.RepeatColumns must be no less than 0. - -basevalidator_controltovalidate_invalid = {0}.ControlToValidate is empty or contains an invalid control ID path. -basevalidator_validatable_required = {0}.ControlToValidate must point to a control implementing IValidatable interface. -basevalidator_forcontrol_unsupported = {0}.ForControl is not supported. - -comparevalidator_controltocompare_invalid = TCompareValidator.ControlToCompare contains an invalid control ID path. - -listcontrolvalidator_invalid_control = {0}.ControlToValidate contains an invalid TListControl ID path, "{1}" is a {2}. - -repeater_template_required = TRepeater.{0} requires a template instance implementing ITemplate interface. -repeater_itemtype_unknown = Unknow repeater item type {0}. -repeateritemcollection_item_invalid = TRepeaterItemCollection can only accept objects that are instance of TControl or its descendant class. - -datalist_template_required = TDataList.{0} requires a template instance implementing ITemplate interface. -datalistitemcollection_datalistitem_required = TDataListItemCollection can only accept TDataListItem objects. - -datagrid_template_required = TDataGrid.{0} requires a template instance implementing ITemplate interface. -templatecolumn_template_required = TTemplateColumn.{0} requires a template instance implementing ITemplate interface. -datagrid_currentpageindex_invalid = TDataGrid.CurrentPageIndex must be no less than 0. -datagrid_pagesize_invalid = TDataGrid.PageSize must be greater than 0. -datagrid_virtualitemcount_invalid = TDataGrid.VirtualItemCount must be no less than 0. -datagriditemcollection_datagriditem_required = TDataGridItemCollection can only accept TDataGridItem objects. -datagridcolumncollection_datagridcolumn_required = TDataGridColumnCollection can only accept TDataGridColumn objects. -datagridpagerstyle_pagebuttoncount_invalid = TDataGridPagerStyle.PageButtonCount must be greater than 0. - -datafieldaccessor_data_invalid = TDataFieldAccessor is trying to evaluate a field value of an invalid data. Make sure the data is an array, TMap, TList, or object that contains the specified field '{0}'. -datafieldaccessor_datafield_invalid = TDataFieldAccessor is trying to evaluate data value of an unknown field '{0}'. - -tablerowcollection_tablerow_required = TTableRowCollection can only accept TTableRow objects. - -tablecellcollection_tablerow_required = TTableCellCollection can only accept TTableCell objects. - -multiview_view_required = TMultiView can only accept TView as child. -multiview_activeviewindex_invalid = TMultiView.ActiveViewIndex has an invalid index '{0}'. -multiview_view_inexistent = TMultiView cannot find the specified view. -multiview_viewid_invalid = TMultiView cannot find the view '{0}' to switch to. - -viewcollection_view_required = TViewCollection can only accept TView as its element. - -view_visible_readonly = TView.Visible is read-only. Use TView.Active to toggle its visibility. - -wizard_step_invalid = The step to be activated cannot be found in wizard step collection. -wizard_command_invalid = Invalid wizard navigation command '{0}'. - -table_tablesection_outoforder = TTable table sections must be in the order of: Header, Body and Footer. - -completewizardstep_steptype_readonly = TCompleteWizardStep.StepType is read-only. - -wizardstepcollection_wizardstep_required = TWizardStepCollection can only accept objects of TWizardStep or its derived classes. - -texthighlighter_stylesheet_invalid = Unable to find the stylesheet file for TTextHighlighter. - -hotspotcollection_hotspot_required = THotSpotCollection can only accept instance of THotSpot or its derived classes. - -htmlarea_textmode_readonly = THtmlArea.TextMode is read-only. -htmlarea_tarfile_invalid = THtmlArea is unable to locate the TinyMCE tar file. - -parametermodule_parameterfile_unchangeable = TParameterModule.ParameterFile is not changeable because the module is already initialized. -parametermodule_parameterfile_invalid = TParameterModule.ParameterFile '{0}' is invalid. Make sure it is in namespace format and the file extension is '.xml'. -parametermodule_parameterid_required = Parameter element must have 'id' attribute. - -datagridcolumn_id_invalid = {0}.ID '{1}' is invalid. Only alphanumeric and underline characters are allowed. The first character must be an alphabetic or underline character. -datagridcolumn_expression_invalid = {0} is evaluating an invalid expression '{1}' : {2} - -outputcache_cachemoduleid_invalid = TOutputCache.CacheModuleID is set with an invalid cache module ID {0}. Either the module does not exist or does not implement ICache interface. -outputcache_duration_invalid = {0}.Duration must be an integer no less than 0. - -stack_data_not_iterable = TStack can only fetch data from an array or a traversable object. -stack_empty = TStack is empty. - -queue_data_not_iterable = TQueue can only fetch data from an array or a traversable object. -queue_empty = TQueue is empty. - -pager_pagebuttoncount_invalid = TPager.PageButtonCount must be an integer no less than 1. -pager_currentpageindex_invalid = TPager.CurrentPageIndex is out of range. -pager_pagecount_invalid = TPager.PageCount cannot be smaller than 0. -pager_controltopaginate_invalid = TPager.ControlToPaginate {0} must be a valid ID path pointing to a TDataBoundControl-derived control. - -databoundcontrol_pagesize_invalid = {0}.PageSize must be an integer no smaller than 1. -databoundcontrol_virtualitemcount_invalid = {0}.VirtualItemCount must be an integer no smaller than 0. -databoundcontrol_currentpageindex_invalid = {0}.CurrentPageIndex is out of range. -databoundcontrol_datasource_invalid = {0}.DataSource is not valid. -databoundcontrol_datasourceid_inexistent = databoundcontrol_datasourceid_inexistent. -databoundcontrol_datasourceid_invalid = databoundcontrol_datasourceid_invalid -databoundcontrol_datamember_invalid = databoundcontrol_datamember_invalid - -clientscript_invalid_file_position = Invalid file position '{1}' for TClientScript control '{0}', must be 'Head', 'Here' or 'Begin'. -clientscript_invalid_package_path = Invalid PackagePath '{0}' for TClientScript control '{1}'. - -tdatepicker_autopostback_unsupported = '{0}' does not support AutoPostBack. -globalization_cache_path_failed = Unable to create translation message cache path '{0}'. Make sure the parent directory exists and is writable by the Web process. -globalization_source_path_failed = Unable to create translation message path '{0}'. Make sure the parent directory exists and is writable by the Web process. -callback_not_support_no_priority_state_update = Callback request does not support unprioritized pagestate update. -callback_invalid_callback_options = '{1}' is not a valid TCallbackOptions control for Callback control '{0}'. -callback_invalid_clientside_options = Callback ClientSide property must be either a string that is the ID of a TCallbackOptions control or an instance of TCallbackClientSideOptions.======= -callback_not_support_no_priority_state_update = Callback request does not support unprioritized pagestate update. -callback_invalid_handler = Invalid callback handler, control {0} must implement ICallbackEventHandler. -callback_invalid_target = Invalid callback target, no such control with ID {0}. - -callback_interval_be_positive = Interval for TCallbackTimer "{0}" must be strictly greater than zero seconds. -callback_decay_be_not_negative = Decay rate for TCallbackTimer "{0}" must be not negative. - -callback_no_autopostback = Control "{0}" can not enable AutoPostBack. - -xmltransform_xslextension_required = TXmlTransform requires the PHP's XSL extension. -xmltransform_transformpath_invalid = TXmlTransform.TransformPath '{0}' is invalid. -xmltransform_documentpath_invalid = TXmlTransform.DocumentPath '{0}' is invalid. -xmltransform_transform_required = Either TransformContent or TransformPath property must be set for TXmlTransform. - -ttriggeredcallback_invalid_controlid = ControlID property for '{0}' must not be empty. -tactivecustomvalidator_clientfunction_unsupported = {0} does not support client side validator function. - -dbconnection_open_failed = TDbConnection failed to establish DB connection: {0} -dbconnection_connection_inactive = TDbConnection is inactive. - -dbcommand_prepare_failed = TDbCommand failed to prepare the SQL statement "{1}": {0} -dbcommand_execute_failed = TDbCommand failed to execute the SQL statement "{1}": {0} -dbcommand_query_failed = TDbCommand failed to execute the query SQL "{1}": {0} -dbcommand_column_empty = TDbCommand returned an empty result and could not obtain the scalar. -dbdatareader_rewind_invalid = TDbDataReader is a forward-only stream. It can only be traversed once. -dbtransaction_transaction_inactive = TDbTransaction is inactive. - -dbcommandbuilder_value_must_not_be_null = Property {0} must not be null as defined by column '{2}' in table '{1}'. - -dbcommon_invalid_table_name = Database table '{0}' not found. Error message: {1}. -dbcommon_invalid_identifier_name = Invalid database identifier name '{0}', see {1} for details. -dbtableinfo_invalid_column_name = Invalid column name '{0}' for database table '{1}'. -dbmetadata_invalid_table_view = Invalid table/view name '{0}', or that table/view '{0}' contains no accessible column/field definitions. -dbmetadata_requires_php_version = PHP version {1} or later is required for using {0} database. - -dbtablegateway_invalid_criteria = Invalid criteria object, must be a string or instance of TSqlCriteria. -dbtablegateway_no_primary_key_found = Table '{0}' does not contain any primary key fields. -dbtablegateway_missing_pk_values = Missing primary key values in forming IN(key1, key2, ...) for table '{0}'. -dbtablegateway_pk_value_count_mismatch = Composite key value count mismatch in forming IN( (key1, key2, ..), (key3, key4, ..)) for table '{0}'. -dbtablegateway_mismatch_args_exception = TTableGateway finder method '{0}' expects {1} parameters but found only {2} parameters instead. -dbtablegateway_mismatch_column_name = In dynamic __call() method '{0}', no matching columns were found, valid columns for table '{2}' are '{1}'. -dbtablegateway_invalid_table_info = Table must be a string or an instanceof TDbTableInfo. - -directorycachedependency_directory_invalid = TDirectoryCacheDependency.Directory {0} does not refer to a valid directory. -cachedependencylist_cachedependency_required = Only objects implementing ICacheDependency can be added into TCacheDependencyList. - -soapservice_configfile_invalid = TSoapService.ConfigFile '{0}' does not exist. Note, it has to be specified in a namespace format and the file extension must be '.xml'. -soapservice_request_invalid = SOAP server '{0}' not found. -soapservice_serverid_required = element must have 'id' attribute. -soapservice_serverid_duplicated = SOAP server ID '{0}' is duplicated. -soapserver_id_invalid = Invalid SOAP server ID '{0}'. It should not end with '.wsdl'. -soapserver_version_invalid = Invalid SOAP version '{0}'. It must be either '1.1' or '1.2'. - -dbusermanager_userclass_required = TDbUserManager.UserClass is required. -dbusermanager_userclass_invalid = TDbUserManager.UserClass '{0}' is not a valid user class. The class must extend TDbUser. -dbusermanager_connectionid_invalid = TDbUserManager.ConnectionID '{0}' does not point to a valid TDataSourceConfig module. -dbusermanager_connectionid_required = TDbUserManager.ConnectionID is required. - -feedservice_id_required = TFeedService requires 'id' attribute in its feed elements. -feedservice_feedtype_invalid = The class feed '{0}' must implement IFeedContentProvider interface. -feedservice_class_required = TFeedService requires 'class' attribute in its feed elements. -feedservice_feed_unknown = Unknown feed '{0}' requested. - -tabviewcollection_tabview_required = TTabPanel can only accept TTabView as child. -tabpanel_activeviewid_invalid = TTabPanel.ActiveViewID has an invalid ID '{0}'. -tabpanel_activeviewindex_invalid = TTabPanel.ActiveViewIndex has an invalid Index '{0}'. -tabpanel_view_inexistent = TTabPanel cannot find the specified view. - -cachesession_cachemoduleid_required = TCacheHttpSession.CacheModuleID is required. -cachesession_cachemodule_inexistent = TCacheHttpSession.CacheModuleID '{0}' points to a non-existent module. -cachesession_cachemodule_invalid = TCacheHttpSession.CacheModuleID '{0}' points to a module that does not implement ICache interface. - -urlmapping_urlmappingpattern_required = TUrlMapping can only contain TUrlMappingPattern or its child classes. +prado_application_singleton_required = Prado.Application must only be set once. +prado_component_unknown = Unknown component type '{0}'. This may be caused by following parsing error in the {0} class file: {1} +prado_using_invalid = '{0}' is not a valid namespace to be used. Make sure '.*' is appended if you want to use a namespace referring to a directory. +prado_alias_redefined = Alias '{0}' cannot be redefined. +prado_alias_invalid = Alias '{0}' refers to an invalid path '{1}'. Only existing directories can be aliased. +prado_aliasname_invalid = Alias '{0}' contains invalid character '.'. + +component_property_undefined = Component property '{0}.{1}' is not defined. +component_property_readonly = Component property '{0}.{1}' is read-only. +component_event_undefined = Component event '{0}.{1}' is not defined. +component_eventhandler_invalid = Component event '{0}.{1}' is attached with an invalid event handler '{2}'. +component_expression_invalid = Component '{0}' is evaluating an invalid expression '{1}' : {2}. +component_statements_invalid = Component '{0}' is evaluating invalid PHP statements '{1}' : {2}. + +propertyvalue_enumvalue_invalid = Value '{0}' is a not valid enumeration value ({1}). + +list_index_invalid = Index '{0}' is out of range. +list_item_inexistent = The item cannot be found in the list. +list_data_not_iterable = Data must be either an array or an object implementing Traversable interface. +list_readonly = {0} is read-only. + +map_addition_disallowed = The new item cannot be added to the map. +map_item_unremovable = The item cannot be removed from the map. +map_data_not_iterable = Data must be either an array or an object implementing Traversable interface. +map_readonly = {0} is read-only. + +application_includefile_invalid = Unable to find application configuration {0}. Make sure it is in namespace format and the file ends with ".xml". +application_basepath_invalid = Application base path '{0}' does not exist or is not a directory. +application_runtimepath_invalid = Application runtime path '{0}' does not exist or is not writable by Web server process. +application_service_invalid = Service '{0}' must implement IService interface. +application_service_unknown = Requested service '{0}' is not defined. +application_unavailable = Application is unavailable at this time. +application_service_unavailable = Service '{0}' is unavailable at this time. +application_moduleid_duplicated = Application module ID '{0}' is not unique. +application_runtimepath_failed = Unable to create runtime path '{0}'. Make sure the parent directory exists and is writable by the Web process. + +appconfig_aliaspath_invalid = Application configuration uses an invalid file path "{1}". +appconfig_alias_invalid = Application configuration element must have an "id" attribute and a "path" attribute. +appconfig_alias_redefined = Application configuration cannot be redefined. +appconfig_using_invalid = Application configuration element must have a "namespace" attribute. +appconfig_moduleid_required = Application configuration element must have an "id" attribute. +appconfig_moduletype_required = Application configuration must have a "class" attribute. +appconfig_serviceid_required = Application configuration element must have an "id" attribute. +appconfig_servicetype_required = Application configuration must have a "class" attribute. +appconfig_parameterid_required = Application configuration element must have an "id" attribute. +appconfig_includefile_required = Application configuration element must have a "file" attribute. + +securitymanager_validationkey_invalid = TSecurityManager.ValidationKey must not be empty. +securitymanager_encryptionkey_invalid = TSecurityManager.EncryptionKey must not be empty. +securitymanager_mcryptextension_required = Mcrypt PHP extension is required in order to use TSecurityManager's encryption feature. + +uri_format_invalid = '{0}' is not a valid URI. + +httprequest_separator_invalid = THttpRequest.UrlParamSeparator can only contain a single character. +httprequest_urlmanager_inexist = THttpRequest.UrlManager '{0}' does not point to an existing module. +httprequest_urlmanager_invalid = THttpRequest.UrlManager '{0}' must point to a module extending from TUrlManager. + +httpcookiecollection_httpcookie_required = THttpCookieCollection can only accept THttpCookie objects. + +httpresponse_bufferoutput_unchangeable = THttpResponse.BufferOutput cannot be modified after THttpResponse is initialized. +httpresponse_file_inexistent = THttpResponse cannot send file '{0}'. The file does not exist. + +httpsession_sessionid_unchangeable = THttpSession.SessionID cannot be modified after the session is started. +httpsession_sessionname_unchangeable = THttpSession.SessionName cannot be modified after the session is started. +httpsession_sessionname_invalid = THttpSession.SessionName must contain alphanumeric characters only. +httpsession_savepath_unchangeable = THttpSession.SavePath cannot be modified after the session is started. +httpsession_savepath_invalid = THttpSession.SavePath '{0}' is invalid. +httpsession_storage_unchangeable = THttpSession.Storage cannot be modified after the session is started. +httpsession_cookiemode_unchangeable = THttpSession.CookieMode cannot be modified after the session is started. +httpsession_autostart_unchangeable = THttpSession.AutoStart cannot be modified after the session module is initialized. +httpsession_gcprobability_unchangeable = THttpSession.GCProbability cannot be modified after the session is started. +httpsession_gcprobability_invalid = THttpSession.GCProbability must be an integer between 0 and 100. +httpsession_transid_unchangeable = THttpSession.UseTransparentSessionID cannot be modified after the session is started. +httpsession_maxlifetime_unchangeable = THttpSession.Timeout cannot be modified after the session is started. + +assetmanager_basepath_invalid = TAssetManager.BasePath '{0}' is invalid. Make sure it is in namespace form and points to a directory writable by the Web server process. +assetmanager_basepath_unchangeable = TAssetManager.BasePath cannot be modified after the module is initialized. +assetmanager_baseurl_unchangeable = TAssetManager.BaseUrl cannot be modified after the module is initialized. +assetmanager_filepath_invalid = TAssetManager is publishing an invalid file '{0}'. +assetmanager_tarchecksum_invalid = TAssetManager is publishing a tar file with invalid checksum '{0}'. +assetmanager_tarfile_invalid = TAssetManager is publishing an invalid tar file '{0}'. +assetmanager_source_directory_invalid = TAssetManager is copying an invalid directory '{0}'. + +cache_primary_duplicated = At most one primary cache module is allowed. {0} is trying to register as another primary cache. +sqlitecache_extension_required = TSqliteCache requires SQLite PHP extension. +sqlitecache_dbfile_required = TSqliteCache.DbFile is required. +sqlitecache_connection_failed = TSqliteCache database connection failed. {0}. +sqlitecache_table_creation_failed = TSqliteCache failed to create cache database. {0}. +sqlitecache_dbfile_unchangeable = TSqliteCache.DbFile cannot be modified after the module is initialized. +sqlitecache_dbfile_invalid = TSqliteCache.DbFile is invalid. Make sure it is in a proper namespace format. + +memcache_extension_required = TMemCache requires memcache PHP extension. +memcache_connection_failed = TMemCache failed to connect to memcache server {0}:{1}. +memcache_host_unchangeable = TMemCache.Host cannot be modified after the module is initialized. +memcache_port_unchangeable = TMemCache.Port cannot be modified after the module is initialized. + +apccache_extension_required = TAPCCache requires APC PHP extension. +apccache_add_unsupported = TAPCCache.add() is not supported. +apccache_replace_unsupported = TAPCCache.replace() is not supported. +apccache_extension_not_enabled = TAPCCache need apc.enabled = 1 in php.ini in order to work. +apccache_extension_not_enabled_cli = TAPCCache need apc.enable_cli = 1 in php.ini in order to work with PHP from the command line. + +errorhandler_errortemplatepath_invalid = TErrorHandler.ErrorTemplatePath '{0}' is invalid. Make sure it is in namespace form and points to a valid directory containing error template files. + +pageservice_page_unknown = Page '{0}' Not Found +pageservice_pageclass_unknown = Page class '{0}' is unknown. +pageservice_basepath_invalid = TPageService.BasePath '{0}' is not a valid directory. +pageservice_page_required = Page Name Required +pageservice_defaultpage_unchangeable = TPageService.DefaultPage cannot be modified after the service is initialized. +pageservice_basepath_unchangeable = TPageService.BasePath cannot be modified after the service is initialized. +pageservice_pageclass_invalid = Page class {0} is invalid. It should be TPage or extend from TPage. +pageservice_includefile_invalid = Unable to find page service configuration {0}. Make sure it is in namespace format and the file ends with ".xml". + +pageserviceconf_file_invalid = Unable to open page directory configuration file '{0}'. +pageserviceconf_aliaspath_invalid = uses an invalid file path "{1}" in page directory configuration file '{2}'. +pageserviceconf_alias_invalid = element must have an "id" attribute and a "path" attribute in page directory configuration file '{0}'. +pageserviceconf_using_invalid = element must have a "namespace" attribute in page directory configuration file '{0}'. +pageserviceconf_module_invalid = element must have an "id" attribute in page directory configuration file '{0}'. +pageserviceconf_moduletype_required = must have a "class" attribute in page directory configuration file '{1}'. +pageserviceconf_parameter_invalid = element must have an "id" attribute in page directory configuration file '{0}'. +pageserviceconf_page_invalid = element must have an "id" attribute in page directory configuration file '{0}'. +pageserviceconf_includefile_required = Page configuration element must have a "file" attribute. + +template_closingtag_unexpected = Unexpected closing tag '{0}' is found. +template_closingtag_expected = Closing tag '{0}' is expected. +template_directive_nonunique = Directive '<%@ ... %>' must appear at the beginning of the template and can appear at most once. +template_comments_forbidden = Template comments are not allowed within property tags. +template_matching_unexpected = Unexpected matching. +template_property_unknown = {0} has no property called '{1}'. +template_event_unknown = {0} has no event called '{1}'. +template_property_readonly = {0} has a read-only property '{1}'. +template_event_forbidden = {0} is a non-control component. No handler can be attached to its event '{1}' in a template. +template_databind_forbidden = {0} is a non-control component. Expressions cannot be bound to its property '{1}'. +template_component_required = '{0}' is not a component. Only components can appear in a template. +template_format_invalid = Invalid template syntax: {0} +template_property_duplicated = Property {0} is configured twice or more. +template_eventhandler_invalid = {0}.{1} can only accept a static string. +template_controlid_invalid = {0}.ID can only accept a static text string. +template_controlskinid_invalid = {0}.SkinID can only accept a static text string. +template_content_unexpected = Unexpected content is encountered when instantiating template: {0}. +template_include_invalid = Invalid template inclusion. Make sure {0} is a valid namespace pointing to an existing template file whose extension is .tpl. +template_tag_unexpected = Initialization for property {0} contains an unknown tag type {1}. + +xmldocument_file_read_failed = TXmlDocument is unable to read file '{0}'. +xmldocument_file_write_failed = TXmlDocument is unable to write file '{0}'. + +xmlelementlist_xmlelement_required = TXmlElementList can only accept TXmlElement objects. + +authorizationrule_action_invalid = TAuthorizationRule.Action can only take 'allow' or 'deny' as the value. +authorizationrule_verb_invalid = TAuthorizationRule.Verb can only take 'get' or 'post' as the value. + +authorizationrulecollection_authorizationrule_required = TAuthorizationRuleCollection can only accept TAuthorizationRule objects. + +usermanager_userfile_invalid = TUserManager.UserFile '{0}' is not a valid file. +usermanager_userfile_unchangeable = TUserManager.UserFile cannot be modified. The user module has been initialized already. + +authmanager_usermanager_required = TAuthManager.UserManager must be assigned a value. +authmanager_usermanager_inexistent = TAuthManager.UserManager '{0}' does not refer to an ID of application module. +authmanager_usermanager_invalid = TAuthManager.UserManager '{0}' does not refer to a valid TUserManager application module. +authmanager_usermanager_unchangeable = TAuthManager.UserManager cannot be modified after the module is initialized. +authmanager_session_required = TAuthManager requires a session application module. + +thememanager_service_unavailable = TThemeManager requires TPageService to be available. This error often occurs when you configure TThemeManager outside of the page service configuration. +thememanager_basepath_invalid = TThemeManager.BasePath '{0}' is not a valid path alias. Make sure you have defined this alias in configuration and it points to a valid directory. +thememanager_basepath_invalid2 = TThemeManager.BasePath '{0}' is not a valid directory. +thememanager_basepath_unchangeable = TThemeManager.BasePath cannot be modified after the module is initialized. + +theme_baseurl_required = TThemeManager.BasePath is required. By default, a directory named 'themes' under the directory containing the application entry script is assumed. +theme_path_inexistent = Theme path '{0}' does not exist. +theme_control_nested = Skin for control type '{0}' in theme '{1}' cannot be within another skin. +theme_skinid_duplicated = SkinID '{0}.{1}' is duplicated in theme '{2}'. +theme_databind_forbidden = Databind cannot be used in theme '{0}' for control skin '{1}.{2}' about property '{3}'. +theme_property_readonly = Skin is being applied to a read-only control property '{0}.{1}'. +theme_property_undefined = Skin is being applied to an inexistent control property '{0}.{1}'. +theme_tag_unexpected = Initialization for property {0} contains an unknown tag type {1}. + +control_object_reregistered = Duplicated object ID '{0}' found. +control_id_invalid = {0}.ID '{1}' is invalid. Only alphanumeric and underline characters are allowed. The first character must be an alphabetic or underline character. +control_skinid_unchangeable = {0}.SkinID cannot be modified after a skin has been applied to the control or the child controls have been created. +control_enabletheming_unchangeable = {0}.EnableTheming cannot be modified after the child controls have been created. +control_stylesheet_applied = StyleSheet skin has already been applied to {0}. +control_id_nonunique = {0}.ID '{1}' is not unique among all controls under the same naming container. + +templatecontrol_mastercontrol_invalid = Master control must be of type TTemplateControl or a child class. +templatecontrol_mastercontrol_required = Control '{0}' requires a master control since the control uses TContent. +templatecontrol_contentid_duplicated = TContent ID '{0}' is duplicated. +templatecontrol_placeholderid_duplicated= TContentPlaceHolder ID '{0}' is duplicated. +templatecontrol_directive_invalid = {0}.{1} can only accept a static text string through a template directive. +templatecontrol_placeholder_inexistent = TContent '{0}' does not have a matching TContentPlaceHolder. + +page_form_duplicated = A page can contain at most one TForm. Use regular HTML form tags for the rest forms. +page_isvalid_unknown = TPage.IsValid has not been evaluated yet. +page_postbackcontrol_invalid = Unable to determine postback control '{0}'. +page_control_outofform = {0} '{1}' must be enclosed within TForm. +page_head_duplicated = A page can contain at most one THead. +page_head_required = A THead control is needed in page template in order to render CSS and js in the HTML head section. +page_statepersister_invalid = Page state persister must implement IPageStatePersister interface. + +csmanager_pradoscript_invalid = Unknown Prado script library name '{0}'. +csmanager_invalid_packages = Unkownn packages '{1}' for javascript packages defined in '{0}'. Valid packages are '{2}'. + +contentplaceholder_id_required = TContentPlaceHolder must have an ID. + +content_id_required = TContent must have an ID. + +controlcollection_control_required = TControlList can only accept strings or TControl objects. + +webcontrol_accesskey_invalid = {0}.AccessKey '{1}' is invalid. It must be a single character only. +webcontrol_style_invalid = {0}.Style must take string value only. + +listcontrol_selection_invalid = {0} has an invalid selection that is set before performing databinding. +listcontrol_selectedindex_invalid = {0}.SelectedIndex has an invalid value {1}. +listcontrol_selectedvalue_invalid = {0}.SelectedValue has an invalid value '{1}'. +listcontrol_expression_invalid = {0} is evaluating an invalid expression '{1}' : {2} +listcontrol_multiselect_unsupported = {0} does not support multiselection. + +label_associatedcontrol_invalid = TLabel.AssociatedControl '{0}' cannot be found. + +hiddenfield_focus_unsupported = THiddenField does not support setting input focus. +hiddenfield_theming_unsupported = THiddenField does not support theming. +hiddenfield_skinid_unsupported = THiddenField does not support control skin. + +panel_defaultbutton_invalid = TPanel.DefaultButton '{0}' does not refer to an existing button control. + +tablestyle_cellpadding_invalid = TTableStyle.CellPadding must take an integer equal to or greater than -1. +tablestyle_cellspacing_invalid = TTableStyle.CellSpacing must take an integer equal to or greater than -1. + +pagestatepersister_pagestate_corrupted = Page state is corrupted. + +sessionpagestatepersister_pagestate_corrupted = Page state is corrupted. +sessionpagestatepersister_historysize_invalid = TSessionPageStatePersister.History must be an integer greater than 0. + +listitemcollection_item_invalid = TListItemCollection can only take strings or TListItem objects. + +dropdownlist_selectedindices_unsupported= TDropDownList.SelectedIndices is read-only. + +bulletedlist_autopostback_unsupported = TBulletedList.AutoPostBack is read-only. +bulletedlist_selectedindex_unsupported = TBulletedList.SelectedIndex is read-only. +bulletedlist_selectedindices_unsupported= TBulletedList.SelectedIndices is read-only. +bulletedlist_selectedvalue_unsupported = TBulletedList.SelectedValue is read-only. + +radiobuttonlist_selectedindices_unsupported = TRadioButtonList.SelectedIndices is read-only. + +logrouter_configfile_invalid = TLogRouter.ConfigFile '{0}' does not exist. +logrouter_routeclass_required = Class attribute is required in configuration. +logrouter_routetype_required = Log route must be an instance of TLogRoute or its derived class. + +filelogroute_logpath_invalid = TFileLogRoute.LogPath '{0}' must be a directory in namespace format and must be writable by the Web server process. +filelogroute_maxfilesize_invalid = TFileLogRoute.MaxFileSize must be greater than 0. +filelogroute_maxlogfiles_invalid = TFileLogRoute.MaxLogFiles must be greater than 0. + +emaillogroute_sentfrom_required = TEmailLogRoute.SentFrom cannot be empty. + +repeatinfo_repeatcolumns_invalid = TRepeatInfo.RepeatColumns must be no less than 0. + +basevalidator_controltovalidate_invalid = {0}.ControlToValidate is empty or contains an invalid control ID path. +basevalidator_validatable_required = {0}.ControlToValidate must point to a control implementing IValidatable interface. +basevalidator_forcontrol_unsupported = {0}.ForControl is not supported. + +comparevalidator_controltocompare_invalid = TCompareValidator.ControlToCompare contains an invalid control ID path. + +listcontrolvalidator_invalid_control = {0}.ControlToValidate contains an invalid TListControl ID path, "{1}" is a {2}. + +repeater_template_required = TRepeater.{0} requires a template instance implementing ITemplate interface. +repeater_itemtype_unknown = Unknow repeater item type {0}. +repeateritemcollection_item_invalid = TRepeaterItemCollection can only accept objects that are instance of TControl or its descendant class. + +datalist_template_required = TDataList.{0} requires a template instance implementing ITemplate interface. +datalistitemcollection_datalistitem_required = TDataListItemCollection can only accept TDataListItem objects. + +datagrid_template_required = TDataGrid.{0} requires a template instance implementing ITemplate interface. +templatecolumn_template_required = TTemplateColumn.{0} requires a template instance implementing ITemplate interface. +datagrid_currentpageindex_invalid = TDataGrid.CurrentPageIndex must be no less than 0. +datagrid_pagesize_invalid = TDataGrid.PageSize must be greater than 0. +datagrid_virtualitemcount_invalid = TDataGrid.VirtualItemCount must be no less than 0. +datagriditemcollection_datagriditem_required = TDataGridItemCollection can only accept TDataGridItem objects. +datagridcolumncollection_datagridcolumn_required = TDataGridColumnCollection can only accept TDataGridColumn objects. +datagridpagerstyle_pagebuttoncount_invalid = TDataGridPagerStyle.PageButtonCount must be greater than 0. + +datafieldaccessor_data_invalid = TDataFieldAccessor is trying to evaluate a field value of an invalid data. Make sure the data is an array, TMap, TList, or object that contains the specified field '{0}'. +datafieldaccessor_datafield_invalid = TDataFieldAccessor is trying to evaluate data value of an unknown field '{0}'. + +tablerowcollection_tablerow_required = TTableRowCollection can only accept TTableRow objects. + +tablecellcollection_tablerow_required = TTableCellCollection can only accept TTableCell objects. + +multiview_view_required = TMultiView can only accept TView as child. +multiview_activeviewindex_invalid = TMultiView.ActiveViewIndex has an invalid index '{0}'. +multiview_view_inexistent = TMultiView cannot find the specified view. +multiview_viewid_invalid = TMultiView cannot find the view '{0}' to switch to. + +viewcollection_view_required = TViewCollection can only accept TView as its element. + +view_visible_readonly = TView.Visible is read-only. Use TView.Active to toggle its visibility. + +wizard_step_invalid = The step to be activated cannot be found in wizard step collection. +wizard_command_invalid = Invalid wizard navigation command '{0}'. + +table_tablesection_outoforder = TTable table sections must be in the order of: Header, Body and Footer. + +completewizardstep_steptype_readonly = TCompleteWizardStep.StepType is read-only. + +wizardstepcollection_wizardstep_required = TWizardStepCollection can only accept objects of TWizardStep or its derived classes. + +texthighlighter_stylesheet_invalid = Unable to find the stylesheet file for TTextHighlighter. + +hotspotcollection_hotspot_required = THotSpotCollection can only accept instance of THotSpot or its derived classes. + +htmlarea_textmode_readonly = THtmlArea.TextMode is read-only. +htmlarea_tarfile_invalid = THtmlArea is unable to locate the TinyMCE tar file. + +parametermodule_parameterfile_unchangeable = TParameterModule.ParameterFile is not changeable because the module is already initialized. +parametermodule_parameterfile_invalid = TParameterModule.ParameterFile '{0}' is invalid. Make sure it is in namespace format and the file extension is '.xml'. +parametermodule_parameterid_required = Parameter element must have 'id' attribute. + +datagridcolumn_id_invalid = {0}.ID '{1}' is invalid. Only alphanumeric and underline characters are allowed. The first character must be an alphabetic or underline character. +datagridcolumn_expression_invalid = {0} is evaluating an invalid expression '{1}' : {2} + +outputcache_cachemoduleid_invalid = TOutputCache.CacheModuleID is set with an invalid cache module ID {0}. Either the module does not exist or does not implement ICache interface. +outputcache_duration_invalid = {0}.Duration must be an integer no less than 0. + +stack_data_not_iterable = TStack can only fetch data from an array or a traversable object. +stack_empty = TStack is empty. + +queue_data_not_iterable = TQueue can only fetch data from an array or a traversable object. +queue_empty = TQueue is empty. + +pager_pagebuttoncount_invalid = TPager.PageButtonCount must be an integer no less than 1. +pager_currentpageindex_invalid = TPager.CurrentPageIndex is out of range. +pager_pagecount_invalid = TPager.PageCount cannot be smaller than 0. +pager_controltopaginate_invalid = TPager.ControlToPaginate {0} must be a valid ID path pointing to a TDataBoundControl-derived control. + +databoundcontrol_pagesize_invalid = {0}.PageSize must be an integer no smaller than 1. +databoundcontrol_virtualitemcount_invalid = {0}.VirtualItemCount must be an integer no smaller than 0. +databoundcontrol_currentpageindex_invalid = {0}.CurrentPageIndex is out of range. +databoundcontrol_datasource_invalid = {0}.DataSource is not valid. +databoundcontrol_datasourceid_inexistent = databoundcontrol_datasourceid_inexistent. +databoundcontrol_datasourceid_invalid = databoundcontrol_datasourceid_invalid +databoundcontrol_datamember_invalid = databoundcontrol_datamember_invalid + +clientscript_invalid_file_position = Invalid file position '{1}' for TClientScript control '{0}', must be 'Head', 'Here' or 'Begin'. +clientscript_invalid_package_path = Invalid PackagePath '{0}' for TClientScript control '{1}'. + +tdatepicker_autopostback_unsupported = '{0}' does not support AutoPostBack. +globalization_cache_path_failed = Unable to create translation message cache path '{0}'. Make sure the parent directory exists and is writable by the Web process. +globalization_source_path_failed = Unable to create translation message path '{0}'. Make sure the parent directory exists and is writable by the Web process. +callback_not_support_no_priority_state_update = Callback request does not support unprioritized pagestate update. +callback_invalid_callback_options = '{1}' is not a valid TCallbackOptions control for Callback control '{0}'. +callback_invalid_clientside_options = Callback ClientSide property must be either a string that is the ID of a TCallbackOptions control or an instance of TCallbackClientSideOptions.======= +callback_not_support_no_priority_state_update = Callback request does not support unprioritized pagestate update. +callback_invalid_handler = Invalid callback handler, control {0} must implement ICallbackEventHandler. +callback_invalid_target = Invalid callback target, no such control with ID {0}. + +callback_interval_be_positive = Interval for TCallbackTimer "{0}" must be strictly greater than zero seconds. +callback_decay_be_not_negative = Decay rate for TCallbackTimer "{0}" must be not negative. + +callback_no_autopostback = Control "{0}" can not enable AutoPostBack. + +xmltransform_xslextension_required = TXmlTransform requires the PHP's XSL extension. +xmltransform_transformpath_invalid = TXmlTransform.TransformPath '{0}' is invalid. +xmltransform_documentpath_invalid = TXmlTransform.DocumentPath '{0}' is invalid. +xmltransform_transform_required = Either TransformContent or TransformPath property must be set for TXmlTransform. + +ttriggeredcallback_invalid_controlid = ControlID property for '{0}' must not be empty. +tactivecustomvalidator_clientfunction_unsupported = {0} does not support client side validator function. + +dbconnection_open_failed = TDbConnection failed to establish DB connection: {0} +dbconnection_connection_inactive = TDbConnection is inactive. + +dbcommand_prepare_failed = TDbCommand failed to prepare the SQL statement "{1}": {0} +dbcommand_execute_failed = TDbCommand failed to execute the SQL statement "{1}": {0} +dbcommand_query_failed = TDbCommand failed to execute the query SQL "{1}": {0} +dbcommand_column_empty = TDbCommand returned an empty result and could not obtain the scalar. +dbdatareader_rewind_invalid = TDbDataReader is a forward-only stream. It can only be traversed once. +dbtransaction_transaction_inactive = TDbTransaction is inactive. + +dbcommandbuilder_value_must_not_be_null = Property {0} must not be null as defined by column '{2}' in table '{1}'. + +dbcommon_invalid_table_name = Database table '{0}' not found. Error message: {1}. +dbcommon_invalid_identifier_name = Invalid database identifier name '{0}', see {1} for details. +dbtableinfo_invalid_column_name = Invalid column name '{0}' for database table '{1}'. +dbmetadata_invalid_table_view = Invalid table/view name '{0}', or that table/view '{0}' contains no accessible column/field definitions. +dbmetadata_requires_php_version = PHP version {1} or later is required for using {0} database. + +dbtablegateway_invalid_criteria = Invalid criteria object, must be a string or instance of TSqlCriteria. +dbtablegateway_no_primary_key_found = Table '{0}' does not contain any primary key fields. +dbtablegateway_missing_pk_values = Missing primary key values in forming IN(key1, key2, ...) for table '{0}'. +dbtablegateway_pk_value_count_mismatch = Composite key value count mismatch in forming IN( (key1, key2, ..), (key3, key4, ..)) for table '{0}'. +dbtablegateway_mismatch_args_exception = TTableGateway finder method '{0}' expects {1} parameters but found only {2} parameters instead. +dbtablegateway_mismatch_column_name = In dynamic __call() method '{0}', no matching columns were found, valid columns for table '{2}' are '{1}'. +dbtablegateway_invalid_table_info = Table must be a string or an instanceof TDbTableInfo. + +directorycachedependency_directory_invalid = TDirectoryCacheDependency.Directory {0} does not refer to a valid directory. +cachedependencylist_cachedependency_required = Only objects implementing ICacheDependency can be added into TCacheDependencyList. + +soapservice_configfile_invalid = TSoapService.ConfigFile '{0}' does not exist. Note, it has to be specified in a namespace format and the file extension must be '.xml'. +soapservice_request_invalid = SOAP server '{0}' not found. +soapservice_serverid_required = element must have 'id' attribute. +soapservice_serverid_duplicated = SOAP server ID '{0}' is duplicated. +soapserver_id_invalid = Invalid SOAP server ID '{0}'. It should not end with '.wsdl'. +soapserver_version_invalid = Invalid SOAP version '{0}'. It must be either '1.1' or '1.2'. + +dbusermanager_userclass_required = TDbUserManager.UserClass is required. +dbusermanager_userclass_invalid = TDbUserManager.UserClass '{0}' is not a valid user class. The class must extend TDbUser. +dbusermanager_connectionid_invalid = TDbUserManager.ConnectionID '{0}' does not point to a valid TDataSourceConfig module. +dbusermanager_connectionid_required = TDbUserManager.ConnectionID is required. + +feedservice_id_required = TFeedService requires 'id' attribute in its feed elements. +feedservice_feedtype_invalid = The class feed '{0}' must implement IFeedContentProvider interface. +feedservice_class_required = TFeedService requires 'class' attribute in its feed elements. +feedservice_feed_unknown = Unknown feed '{0}' requested. + +tabviewcollection_tabview_required = TTabPanel can only accept TTabView as child. +tabpanel_activeviewid_invalid = TTabPanel.ActiveViewID has an invalid ID '{0}'. +tabpanel_activeviewindex_invalid = TTabPanel.ActiveViewIndex has an invalid Index '{0}'. +tabpanel_view_inexistent = TTabPanel cannot find the specified view. + +cachesession_cachemoduleid_required = TCacheHttpSession.CacheModuleID is required. +cachesession_cachemodule_inexistent = TCacheHttpSession.CacheModuleID '{0}' points to a non-existent module. +cachesession_cachemodule_invalid = TCacheHttpSession.CacheModuleID '{0}' points to a module that does not implement ICache interface. + +urlmapping_urlmappingpattern_required = TUrlMapping can only contain TUrlMappingPattern or its child classes. urlmappingpattern_serviceparameter_required = TUrlMappingPattern.ServiceParameter is required for pattern '{0}'. \ No newline at end of file diff --git a/framework/TComponent.php b/framework/TComponent.php index edf72af6..5b751ff3 100644 --- a/framework/TComponent.php +++ b/framework/TComponent.php @@ -1,842 +1,842 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System - */ - -/** - * TComponent class - * - * TComponent is the base class for all PRADO components. - * TComponent implements the protocol of defining, using properties and events. - * - * A property is defined by a getter method, and/or a setter method. - * Properties can be accessed in the way like accessing normal object members. - * Reading or writing a property will cause the invocation of the corresponding - * getter or setter method, e.g., - * - * $a=$this->Text; // equivalent to $a=$this->getText(); - * $this->Text='abc'; // equivalent to $this->setText('abc'); - * - * The signatures of getter and setter methods are as follows, - * - * // getter, defines a readable property 'Text' - * function getText() { ... } - * // setter, defines a writable property 'Text', with $value being the value to be set to the property - * function setText($value) { ... } - * - * Property names are case-insensitive. It is recommended that they are written - * in the format of concatenated words, with the first letter of each word - * capitalized (e.g. DisplayMode, ItemStyle). - * - * An event is defined by the presence of a method whose name starts with 'on'. - * The event name is the method name and is thus case-insensitive. - * An event can be attached with one or several methods (called event handlers). - * An event can be raised by calling {@link raiseEvent} method, upon which - * the attached event handlers will be invoked automatically in the order they - * are attached to the event. Event handlers must have the following signature, - * - * function eventHandlerFuncName($sender,$param) { ... } - * - * where $sender refers to the object who is responsible for the raising of the event, - * and $param refers to a structure that may contain event-specific information. - * To raise an event (assuming named as 'Click') of a component, use - * - * $component->raiseEvent('OnClick'); - * - * To attach an event handler to an event, use one of the following ways, - * - * $component->OnClick=$callback; // or $component->OnClick->add($callback); - * $$component->attachEventHandler('OnClick',$callback); - * - * The first two ways make use of the fact that $component->OnClick refers to - * the event handler list {@link TList} for the 'OnClick' event. - * The variable $callback contains the definition of the event handler that can - * be either a string referring to a global function name, or an array whose - * first element refers to an object and second element a method name/path that - * is reachable by the object, e.g. - * - 'buttonClicked' : buttonClicked($sender,$param); - * - array($object,'buttonClicked') : $object->buttonClicked($sender,$param); - * - array($object,'MainContent.SubmitButton.buttonClicked') : - * $object->MainContent->SubmitButton->buttonClicked($sender,$param); - * - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class TComponent -{ - /** - * @var array event handler lists - */ - private $_e=array(); - - /** - * Returns a property value or an event handler list by property or event name. - * Do not call this method. This is a PHP magic method that we override - * to allow using the following syntax to read a property: - * - * $value=$component->PropertyName; - * - * and to obtain the event handler list for an event, - * - * $eventHandlerList=$component->EventName; - * - * @param string the property name or the event name - * @return mixed the property value or the event handler list - * @throws TInvalidOperationException if the property/event is not defined. - */ - public function __get($name) - { - $getter='get'.$name; - if(method_exists($this,$getter)) - { - // getting a property - return $this->$getter(); - } - else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) - { - // getting an event (handler list) - $name=strtolower($name); - if(!isset($this->_e[$name])) - $this->_e[$name]=new TList; - return $this->_e[$name]; - } - else - { - throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); - } - } - - /** - * Sets value of a component property. - * Do not call this method. This is a PHP magic method that we override - * to allow using the following syntax to set a property or attach an event handler. - * - * $this->PropertyName=$value; - * $this->EventName=$handler; - * - * @param string the property name or event name - * @param mixed the property value or event handler - * @throws TInvalidOperationException If the property is not defined or read-only. - */ - public function __set($name,$value) - { - $setter='set'.$name; - if(method_exists($this,$setter)) - { - $this->$setter($value); - } - else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) - { - $this->attachEventHandler($name,$value); - } - else if(method_exists($this,'get'.$name)) - { - throw new TInvalidOperationException('component_property_readonly',get_class($this),$name); - } - else - { - throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); - } - } - - /** - * Determines whether a property is defined. - * A property is defined if there is a getter or setter method - * defined in the class. Note, property names are case-insensitive. - * @param string the property name - * @return boolean whether the property is defined - */ - public function hasProperty($name) - { - return method_exists($this,'get'.$name) || method_exists($this,'set'.$name); - } - - /** - * Determines whether a property can be read. - * A property can be read if the class has a getter method - * for the property name. Note, property name is case-insensitive. - * @param string the property name - * @return boolean whether the property can be read - */ - public function canGetProperty($name) - { - return method_exists($this,'get'.$name); - } - - /** - * Determines whether a property can be set. - * A property can be written if the class has a setter method - * for the property name. Note, property name is case-insensitive. - * @param string the property name - * @return boolean whether the property can be written - */ - public function canSetProperty($name) - { - return method_exists($this,'set'.$name); - } - - /** - * Evaluates a property path. - * A property path is a sequence of property names concatenated by '.' character. - * For example, 'Parent.Page' refers to the 'Page' property of the component's - * 'Parent' property value (which should be a component also). - * @param string property path - * @return mixed the property path value - */ - public function getSubProperty($path) - { - $object=$this; - foreach(explode('.',$path) as $property) - $object=$object->$property; - return $object; - } - - /** - * Sets a value to a property path. - * A property path is a sequence of property names concatenated by '.' character. - * For example, 'Parent.Page' refers to the 'Page' property of the component's - * 'Parent' property value (which should be a component also). - * @param string property path - * @param mixed the property path value - */ - public function setSubProperty($path,$value) - { - $object=$this; - if(($pos=strrpos($path,'.'))===false) - $property=$path; - else - { - $object=$this->getSubProperty(substr($path,0,$pos)); - $property=substr($path,$pos+1); - } - $object->$property=$value; - } - - /** - * Determines whether an event is defined. - * An event is defined if the class has a method whose name is the event name prefixed with 'on'. - * Note, event name is case-insensitive. - * @param string the event name - * @return boolean - */ - public function hasEvent($name) - { - return strncasecmp($name,'on',2)===0 && method_exists($this,$name); - } - - /** - * @return boolean whether an event has been attached one or several handlers - */ - public function hasEventHandler($name) - { - $name=strtolower($name); - return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0; - } - - /** - * Returns the list of attached event handlers for an event. - * @return TList list of attached event handlers for an event - * @throws TInvalidOperationException if the event is not defined - */ - public function getEventHandlers($name) - { - if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) - { - $name=strtolower($name); - if(!isset($this->_e[$name])) - $this->_e[$name]=new TList; - return $this->_e[$name]; - } - else - throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); - } - - /** - * Attaches an event handler to an event. - * - * The handler must be a valid PHP callback, i.e., a string referring to - * a global function name, or an array containing two elements with - * the first element being an object and the second element a method name - * of the object. In Prado, you can also use method path to refer to - * an event handler. For example, array($object,'Parent.buttonClicked') - * uses a method path that refers to the method $object->Parent->buttonClicked(...). - * - * The event handler must be of the following signature, - * - * function handlerName($sender,$param) {} - * - * where $sender represents the object that raises the event, - * and $param is the event parameter. - * - * This is a convenient method to add an event handler. - * It is equivalent to {@link getEventHandlers}($name)->add($handler). - * For complete management of event handlers, use {@link getEventHandlers} - * to get the event handler list first, and then do various - * {@link TList} operations to append, insert or remove - * event handlers. You may also do these operations like - * getting and setting properties, e.g., - * - * $component->OnClick[]=array($object,'buttonClicked'); - * $component->OnClick->insertAt(0,array($object,'buttonClicked')); - * - * which are equivalent to the following - * - * $component->getEventHandlers('OnClick')->add(array($object,'buttonClicked')); - * $component->getEventHandlers('OnClick')->insertAt(0,array($object,'buttonClicked')); - * - * - * @param string the event name - * @param callback the event handler - * @throws TInvalidOperationException if the event does not exist - */ - public function attachEventHandler($name,$handler) - { - $this->getEventHandlers($name)->add($handler); - } - - /** - * Detaches an existing event handler. - * This method is the opposite of {@link attachEventHandler}. - * @param string event name - * @param callback the event handler to be removed - * @return boolean if the removal is successful - */ - public function detachEventHandler($name,$handler) - { - if($this->hasEventHandler($name)) - { - try - { - $this->getEventHandlers($name)->remove($handler); - return true; - } - catch(Exception $e) - { - } - } - return false; - } - - /** - * Raises an event. - * This method represents the happening of an event and will - * invoke all attached event handlers for the event. - * @param string the event name - * @param mixed the event sender object - * @param TEventParameter the event parameter - * @throws TInvalidOperationException if the event is undefined - * @throws TInvalidDataValueException If an event handler is invalid - */ - public function raiseEvent($name,$sender,$param) - { - $name=strtolower($name); - if(isset($this->_e[$name])) - { - foreach($this->_e[$name] as $handler) - { - if(is_string($handler)) - { - if(($pos=strrpos($handler,'.'))!==false) - { - $object=$this->getSubProperty(substr($handler,0,$pos)); - $method=substr($handler,$pos+1); - if(method_exists($object,$method)) - $object->$method($sender,$param); - else - throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name); - } - else - call_user_func($handler,$sender,$param); - } - else if(is_callable($handler,true)) - { - // an array: 0 - object, 1 - method name/path - list($object,$method)=$handler; - if(is_string($object)) // static method call - call_user_func($handler,$sender,$param); - else - { - if(($pos=strrpos($method,'.'))!==false) - { - $object=$this->getSubProperty(substr($method,0,$pos)); - $method=substr($method,$pos+1); - } - if(method_exists($object,$method)) - $object->$method($sender,$param); - else - throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name); - } - } - else - throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name); - } - } - else if(!$this->hasEvent($name)) - throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); - } - - /** - * Evaluates a PHP expression in the context of this control. - * @return mixed the expression result - * @throws TInvalidOperationException if the expression is invalid - */ - public function evaluateExpression($expression) - { - try - { - if(eval("\$result=$expression;")===false) - throw new Exception(''); - return $result; - } - catch(Exception $e) - { - throw new TInvalidOperationException('component_expression_invalid',get_class($this),$expression,$e->getMessage()); - } - } - - /** - * Evaluates a list of PHP statements. - * @param string PHP statements - * @return string content echoed or printed by the PHP statements - * @throws TInvalidOperationException if the statements are invalid - */ - public function evaluateStatements($statements) - { - try - { - ob_start(); - if(eval($statements)===false) - throw new Exception(''); - $content=ob_get_contents(); - ob_end_clean(); - return $content; - } - catch(Exception $e) - { - throw new TInvalidOperationException('component_statements_invalid',get_class($this),$statements,$e->getMessage()); - } - } - - /** - * This method is invoked after the component is instantiated by a template. - * When this method is invoked, the component's properties have been initialized. - * The default implementation of this method will invoke - * the potential parent component's {@link addParsedObject}. - * This method can be overridden. - * @param TComponent potential parent of this control - * @see addParsedObject - */ - public function createdOnTemplate($parent) - { - $parent->addParsedObject($this); - } - - /** - * Processes an object that is created during parsing template. - * The object can be either a component or a static text string. - * This method can be overridden to customize the handling of newly created objects in template. - * Only framework developers and control developers should use this method. - * @param string|TComponent text string or component parsed and instantiated in template - * @see createdOnTemplate - */ - public function addParsedObject($object) - { - } -} - -/** - * TEnumerable class. - * TEnumerable is the base class for all enumerable types. - * To define an enumerable type, extend TEnumberable and define string constants. - * Each constant represents an enumerable value. - * The constant name must be the same as the constant value. - * For example, - * - * class TTextAlign extends TEnumerable - * { - * const Left='Left'; - * const Right='Right'; - * } - * - * Then, one can use the enumerable values such as TTextAlign::Left and - * TTextAlign::Right. - * - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class TEnumerable -{ -} - -/** - * TPropertyValue class - * - * TPropertyValue is a utility class that provides static methods - * to convert component property values to specific types. - * - * TPropertyValue is commonly used in component setter methods to ensure - * the new property value is of specific type. - * For example, a boolean-typed property setter method would be as follows, - * - * function setPropertyName($value) { - * $value=TPropertyValue::ensureBoolean($value); - * // $value is now of boolean type - * } - * - * - * Properties can be of the following types with specific type conversion rules: - * - string: a boolean value will be converted to 'true' or 'false'. - * - boolean: string 'true' (case-insensitive) will be converted to true, - * string 'false' (case-insensitive) will be converted to false. - * - integer - * - float - * - array: string starting with '(' and ending with ')' will be considered as - * as an array expression and will be evaluated. Otherwise, an array - * with the value to be ensured is returned. - * - object - * - enum: enumerable type, represented by an array of strings. - * - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class TPropertyValue -{ - /** - * Converts a value to boolean type. - * Note, string 'true' (case-insensitive) will be converted to true, - * string 'false' (case-insensitive) will be converted to false. - * If a string represents a non-zero number, it will be treated as true. - * @param mixed the value to be converted. - * @return boolean - */ - public static function ensureBoolean($value) - { - if (is_string($value)) - return strcasecmp($value,'true')==0 || $value!=0; - else - return (boolean)$value; - } - - /** - * Converts a value to string type. - * Note, a boolean value will be converted to 'true' if it is true - * and 'false' if it is false. - * @param mixed the value to be converted. - * @return string - */ - public static function ensureString($value) - { - if (is_bool($value)) - return $value?'true':'false'; - else - return (string)$value; - } - - /** - * Converts a value to integer type. - * @param mixed the value to be converted. - * @return integer - */ - public static function ensureInteger($value) - { - return (integer)$value; - } - - /** - * Converts a value to float type. - * @param mixed the value to be converted. - * @return float - */ - public static function ensureFloat($value) - { - return (float)$value; - } - - /** - * Converts a value to array type. If the value is a string and it is - * in the form (a,b,c) then an array consisting of each of the elements - * will be returned. If the value is a string and it is not in this form - * then an array consisting of just the string will be returned. If the value - * is not a string then - * @param mixed the value to be converted. - * @return array - */ - public static function ensureArray($value) - { - if(is_string($value)) - { - $trimmed = trim($value); - $len = strlen($value); - if ($len >= 2 && $trimmed[0] == '(' && $trimmed[$len-1] == ')') - { - eval('$array=array'.$trimmed.';'); - return $array; - } - else - return $len>0?array($value):array(); - } - else - return (array)$value; - } - - /** - * Converts a value to object type. - * @param mixed the value to be converted. - * @return object - */ - public static function ensureObject($value) - { - return (object)$value; - } - - /** - * Converts a value to enum type. - * - * This method checks if the value is of the specified enumerable type. - * A value is a valid enumerable value if it is equal to the name of a constant - * in the specified enumerable type (class). - * For more details about enumerable, see {@link TEnumerable}. - * - * For backward compatibility, this method also supports sanity - * check of a string value to see if it is among the given list of strings. - * @param mixed the value to be converted. - * @param mixed class name of the enumerable type, or array of valid enumeration values. If this is not an array, - * the method considers its parameters are of variable length, and the second till the last parameters are enumeration values. - * @return string the valid enumeration value - * @throws TInvalidDataValueException if the original value is not in the string array. - */ - public static function ensureEnum($value,$enums) - { - static $types=array(); - if(func_num_args()===2 && is_string($enums)) - { - if(!isset($types[$enums])) - $types[$enums]=new ReflectionClass($enums); - if($types[$enums]->hasConstant($value)) - return $value; - else - throw new TInvalidDataValueException( - 'propertyvalue_enumvalue_invalid',$value, - implode(' | ',$types[$enums]->getConstants())); - } - else if(!is_array($enums)) - { - $enums=func_get_args(); - array_shift($enums); - } - if(in_array($value,$enums,true)) - return $value; - else - throw new TInvalidDataValueException('propertyvalue_enumvalue_invalid',$value,implode(' | ',$enums)); - } -} - -/** - * TEventParameter class. - * TEventParameter is the base class for all event parameter classes. - * - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class TEventParameter extends TComponent -{ -} - -/** - * TComponentReflection class. - * - * TComponentReflection provides functionalities to inspect the public/protected - * properties, events and methods defined in a class. - * - * The following code displays the properties and events defined in {@link TDataGrid}, - * - * $reflection=new TComponentReflection('TDataGrid'); - * Prado::varDump($reflection->getProperties()); - * Prado::varDump($reflection->getEvents()); - * - * - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class TComponentReflection extends TComponent -{ - private $_className; - private $_properties=array(); - private $_events=array(); - private $_methods=array(); - - /** - * Constructor. - * @param object|string the component instance or the class name - * @throws TInvalidDataTypeException if the object is not a component - */ - public function __construct($component) - { - if(is_string($component) && class_exists($component,false)) - $this->_className=$component; - else if(is_object($component)) - $this->_className=get_class($component); - else - throw new TInvalidDataTypeException('componentreflection_class_invalid'); - $this->reflect(); - } - - private function isPropertyMethod($method) - { - $methodName=$method->getName(); - return $method->getNumberOfRequiredParameters()===0 - && strncasecmp($methodName,'get',3)===0 - && isset($methodName[3]); - } - - private function isEventMethod($method) - { - $methodName=$method->getName(); - return strncasecmp($methodName,'on',2)===0 - && isset($methodName[2]); - } - - private function reflect() - { - $class=new TReflectionClass($this->_className); - $properties=array(); - $events=array(); - $methods=array(); - $isComponent=is_subclass_of($this->_className,'TComponent') || strcasecmp($this->_className,'TComponent')===0; - foreach($class->getMethods() as $method) - { - if($method->isPublic() || $method->isProtected()) - { - $methodName=$method->getName(); - if(!$method->isStatic() && $isComponent) - { - if($this->isPropertyMethod($method)) - $properties[substr($methodName,3)]=$method; - else if($this->isEventMethod($method)) - { - $methodName[0]='O'; - $events[$methodName]=$method; - } - } - if(strncmp($methodName,'__',2)!==0) - $methods[$methodName]=$method; - } - } - $reserved=array(); - ksort($properties); - foreach($properties as $name=>$method) - { - $this->_properties[$name]=array( - 'type'=>$this->determinePropertyType($method), - 'readonly'=>!$class->hasMethod('set'.$name), - 'protected'=>$method->isProtected(), - 'class'=>$method->getDeclaringClass()->getName(), - 'comments'=>$method->getDocComment() - ); - $reserved['get'.strtolower($name)]=1; - $reserved['set'.strtolower($name)]=1; - } - ksort($events); - foreach($events as $name=>$method) - { - $this->_events[$name]=array( - 'class'=>$method->getDeclaringClass()->getName(), - 'protected'=>$method->isProtected(), - 'comments'=>$method->getDocComment() - ); - $reserved[strtolower($name)]=1; - } - ksort($methods); - foreach($methods as $name=>$method) - { - if(!isset($reserved[strtolower($name)])) - $this->_methods[$name]=array( - 'class'=>$method->getDeclaringClass()->getName(), - 'protected'=>$method->isProtected(), - 'static'=>$method->isStatic(), - 'comments'=>$method->getDocComment() - ); - } - } - - /** - * Determines the property type. - * This method uses the doc comment to determine the property type. - * @param ReflectionMethod - * @return string the property type, '{unknown}' if type cannot be determined from comment - */ - protected function determinePropertyType($method) - { - $comment=$method->getDocComment(); - if(preg_match('/@return\\s+(.*?)\\s+/',$comment,$matches)) - return $matches[1]; - else - return '{unknown}'; - } - - /** - * @return string class name of the component - */ - public function getClassName() - { - return $this->_className; - } - - /** - * @return array list of component properties. Array keys are property names. - * Each array element is of the following structure: - * [type]=>property type, - * [readonly]=>whether the property is read-only, - * [protected]=>whether the method is protected or not - * [class]=>the class where the property is inherited from, - * [comments]=>comments associated with the property. - */ - public function getProperties() - { - return $this->_properties; - } - - /** - * @return array list of component events. Array keys are event names. - * Each array element is of the following structure: - * [protected]=>whether the event is protected or not - * [class]=>the class where the event is inherited from. - * [comments]=>comments associated with the event. - */ - public function getEvents() - { - return $this->_events; - } - - /** - * @return array list of public/protected methods. Array keys are method names. - * Each array element is of the following structure: - * [protected]=>whether the method is protected or not - * [static]=>whether the method is static or not - * [class]=>the class where the property is inherited from, - * [comments]=>comments associated with the event. - */ - public function getMethods() - { - return $this->_methods; - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System + */ + +/** + * TComponent class + * + * TComponent is the base class for all PRADO components. + * TComponent implements the protocol of defining, using properties and events. + * + * A property is defined by a getter method, and/or a setter method. + * Properties can be accessed in the way like accessing normal object members. + * Reading or writing a property will cause the invocation of the corresponding + * getter or setter method, e.g., + * + * $a=$this->Text; // equivalent to $a=$this->getText(); + * $this->Text='abc'; // equivalent to $this->setText('abc'); + * + * The signatures of getter and setter methods are as follows, + * + * // getter, defines a readable property 'Text' + * function getText() { ... } + * // setter, defines a writable property 'Text', with $value being the value to be set to the property + * function setText($value) { ... } + * + * Property names are case-insensitive. It is recommended that they are written + * in the format of concatenated words, with the first letter of each word + * capitalized (e.g. DisplayMode, ItemStyle). + * + * An event is defined by the presence of a method whose name starts with 'on'. + * The event name is the method name and is thus case-insensitive. + * An event can be attached with one or several methods (called event handlers). + * An event can be raised by calling {@link raiseEvent} method, upon which + * the attached event handlers will be invoked automatically in the order they + * are attached to the event. Event handlers must have the following signature, + * + * function eventHandlerFuncName($sender,$param) { ... } + * + * where $sender refers to the object who is responsible for the raising of the event, + * and $param refers to a structure that may contain event-specific information. + * To raise an event (assuming named as 'Click') of a component, use + * + * $component->raiseEvent('OnClick'); + * + * To attach an event handler to an event, use one of the following ways, + * + * $component->OnClick=$callback; // or $component->OnClick->add($callback); + * $$component->attachEventHandler('OnClick',$callback); + * + * The first two ways make use of the fact that $component->OnClick refers to + * the event handler list {@link TList} for the 'OnClick' event. + * The variable $callback contains the definition of the event handler that can + * be either a string referring to a global function name, or an array whose + * first element refers to an object and second element a method name/path that + * is reachable by the object, e.g. + * - 'buttonClicked' : buttonClicked($sender,$param); + * - array($object,'buttonClicked') : $object->buttonClicked($sender,$param); + * - array($object,'MainContent.SubmitButton.buttonClicked') : + * $object->MainContent->SubmitButton->buttonClicked($sender,$param); + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class TComponent +{ + /** + * @var array event handler lists + */ + private $_e=array(); + + /** + * Returns a property value or an event handler list by property or event name. + * Do not call this method. This is a PHP magic method that we override + * to allow using the following syntax to read a property: + * + * $value=$component->PropertyName; + * + * and to obtain the event handler list for an event, + * + * $eventHandlerList=$component->EventName; + * + * @param string the property name or the event name + * @return mixed the property value or the event handler list + * @throws TInvalidOperationException if the property/event is not defined. + */ + public function __get($name) + { + $getter='get'.$name; + if(method_exists($this,$getter)) + { + // getting a property + return $this->$getter(); + } + else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) + { + // getting an event (handler list) + $name=strtolower($name); + if(!isset($this->_e[$name])) + $this->_e[$name]=new TList; + return $this->_e[$name]; + } + else + { + throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); + } + } + + /** + * Sets value of a component property. + * Do not call this method. This is a PHP magic method that we override + * to allow using the following syntax to set a property or attach an event handler. + * + * $this->PropertyName=$value; + * $this->EventName=$handler; + * + * @param string the property name or event name + * @param mixed the property value or event handler + * @throws TInvalidOperationException If the property is not defined or read-only. + */ + public function __set($name,$value) + { + $setter='set'.$name; + if(method_exists($this,$setter)) + { + $this->$setter($value); + } + else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) + { + $this->attachEventHandler($name,$value); + } + else if(method_exists($this,'get'.$name)) + { + throw new TInvalidOperationException('component_property_readonly',get_class($this),$name); + } + else + { + throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); + } + } + + /** + * Determines whether a property is defined. + * A property is defined if there is a getter or setter method + * defined in the class. Note, property names are case-insensitive. + * @param string the property name + * @return boolean whether the property is defined + */ + public function hasProperty($name) + { + return method_exists($this,'get'.$name) || method_exists($this,'set'.$name); + } + + /** + * Determines whether a property can be read. + * A property can be read if the class has a getter method + * for the property name. Note, property name is case-insensitive. + * @param string the property name + * @return boolean whether the property can be read + */ + public function canGetProperty($name) + { + return method_exists($this,'get'.$name); + } + + /** + * Determines whether a property can be set. + * A property can be written if the class has a setter method + * for the property name. Note, property name is case-insensitive. + * @param string the property name + * @return boolean whether the property can be written + */ + public function canSetProperty($name) + { + return method_exists($this,'set'.$name); + } + + /** + * Evaluates a property path. + * A property path is a sequence of property names concatenated by '.' character. + * For example, 'Parent.Page' refers to the 'Page' property of the component's + * 'Parent' property value (which should be a component also). + * @param string property path + * @return mixed the property path value + */ + public function getSubProperty($path) + { + $object=$this; + foreach(explode('.',$path) as $property) + $object=$object->$property; + return $object; + } + + /** + * Sets a value to a property path. + * A property path is a sequence of property names concatenated by '.' character. + * For example, 'Parent.Page' refers to the 'Page' property of the component's + * 'Parent' property value (which should be a component also). + * @param string property path + * @param mixed the property path value + */ + public function setSubProperty($path,$value) + { + $object=$this; + if(($pos=strrpos($path,'.'))===false) + $property=$path; + else + { + $object=$this->getSubProperty(substr($path,0,$pos)); + $property=substr($path,$pos+1); + } + $object->$property=$value; + } + + /** + * Determines whether an event is defined. + * An event is defined if the class has a method whose name is the event name prefixed with 'on'. + * Note, event name is case-insensitive. + * @param string the event name + * @return boolean + */ + public function hasEvent($name) + { + return strncasecmp($name,'on',2)===0 && method_exists($this,$name); + } + + /** + * @return boolean whether an event has been attached one or several handlers + */ + public function hasEventHandler($name) + { + $name=strtolower($name); + return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0; + } + + /** + * Returns the list of attached event handlers for an event. + * @return TList list of attached event handlers for an event + * @throws TInvalidOperationException if the event is not defined + */ + public function getEventHandlers($name) + { + if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) + { + $name=strtolower($name); + if(!isset($this->_e[$name])) + $this->_e[$name]=new TList; + return $this->_e[$name]; + } + else + throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); + } + + /** + * Attaches an event handler to an event. + * + * The handler must be a valid PHP callback, i.e., a string referring to + * a global function name, or an array containing two elements with + * the first element being an object and the second element a method name + * of the object. In Prado, you can also use method path to refer to + * an event handler. For example, array($object,'Parent.buttonClicked') + * uses a method path that refers to the method $object->Parent->buttonClicked(...). + * + * The event handler must be of the following signature, + * + * function handlerName($sender,$param) {} + * + * where $sender represents the object that raises the event, + * and $param is the event parameter. + * + * This is a convenient method to add an event handler. + * It is equivalent to {@link getEventHandlers}($name)->add($handler). + * For complete management of event handlers, use {@link getEventHandlers} + * to get the event handler list first, and then do various + * {@link TList} operations to append, insert or remove + * event handlers. You may also do these operations like + * getting and setting properties, e.g., + * + * $component->OnClick[]=array($object,'buttonClicked'); + * $component->OnClick->insertAt(0,array($object,'buttonClicked')); + * + * which are equivalent to the following + * + * $component->getEventHandlers('OnClick')->add(array($object,'buttonClicked')); + * $component->getEventHandlers('OnClick')->insertAt(0,array($object,'buttonClicked')); + * + * + * @param string the event name + * @param callback the event handler + * @throws TInvalidOperationException if the event does not exist + */ + public function attachEventHandler($name,$handler) + { + $this->getEventHandlers($name)->add($handler); + } + + /** + * Detaches an existing event handler. + * This method is the opposite of {@link attachEventHandler}. + * @param string event name + * @param callback the event handler to be removed + * @return boolean if the removal is successful + */ + public function detachEventHandler($name,$handler) + { + if($this->hasEventHandler($name)) + { + try + { + $this->getEventHandlers($name)->remove($handler); + return true; + } + catch(Exception $e) + { + } + } + return false; + } + + /** + * Raises an event. + * This method represents the happening of an event and will + * invoke all attached event handlers for the event. + * @param string the event name + * @param mixed the event sender object + * @param TEventParameter the event parameter + * @throws TInvalidOperationException if the event is undefined + * @throws TInvalidDataValueException If an event handler is invalid + */ + public function raiseEvent($name,$sender,$param) + { + $name=strtolower($name); + if(isset($this->_e[$name])) + { + foreach($this->_e[$name] as $handler) + { + if(is_string($handler)) + { + if(($pos=strrpos($handler,'.'))!==false) + { + $object=$this->getSubProperty(substr($handler,0,$pos)); + $method=substr($handler,$pos+1); + if(method_exists($object,$method)) + $object->$method($sender,$param); + else + throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,get_class($object).'::'.$method.'()'); + } + else + call_user_func($handler,$sender,$param); + } + else if(is_callable($handler,true)) + { + // an array: 0 - object, 1 - method name/path + list($object,$method)=$handler; + if(is_string($object)) // static method call + call_user_func($handler,$sender,$param); + else + { + if(($pos=strrpos($method,'.'))!==false) + { + $object=$this->getSubProperty(substr($method,0,$pos)); + $method=substr($method,$pos+1); + } + if(method_exists($object,$method)) + $object->$method($sender,$param); + else + throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,get_class($object).'::'.$method.'()'); + } + } + else + throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,get_class($object).'::'.$method.'()'); + } + } + else if(!$this->hasEvent($name)) + throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); + } + + /** + * Evaluates a PHP expression in the context of this control. + * @return mixed the expression result + * @throws TInvalidOperationException if the expression is invalid + */ + public function evaluateExpression($expression) + { + try + { + if(eval("\$result=$expression;")===false) + throw new Exception(''); + return $result; + } + catch(Exception $e) + { + throw new TInvalidOperationException('component_expression_invalid',get_class($this),$expression,$e->getMessage()); + } + } + + /** + * Evaluates a list of PHP statements. + * @param string PHP statements + * @return string content echoed or printed by the PHP statements + * @throws TInvalidOperationException if the statements are invalid + */ + public function evaluateStatements($statements) + { + try + { + ob_start(); + if(eval($statements)===false) + throw new Exception(''); + $content=ob_get_contents(); + ob_end_clean(); + return $content; + } + catch(Exception $e) + { + throw new TInvalidOperationException('component_statements_invalid',get_class($this),$statements,$e->getMessage()); + } + } + + /** + * This method is invoked after the component is instantiated by a template. + * When this method is invoked, the component's properties have been initialized. + * The default implementation of this method will invoke + * the potential parent component's {@link addParsedObject}. + * This method can be overridden. + * @param TComponent potential parent of this control + * @see addParsedObject + */ + public function createdOnTemplate($parent) + { + $parent->addParsedObject($this); + } + + /** + * Processes an object that is created during parsing template. + * The object can be either a component or a static text string. + * This method can be overridden to customize the handling of newly created objects in template. + * Only framework developers and control developers should use this method. + * @param string|TComponent text string or component parsed and instantiated in template + * @see createdOnTemplate + */ + public function addParsedObject($object) + { + } +} + +/** + * TEnumerable class. + * TEnumerable is the base class for all enumerable types. + * To define an enumerable type, extend TEnumberable and define string constants. + * Each constant represents an enumerable value. + * The constant name must be the same as the constant value. + * For example, + * + * class TTextAlign extends TEnumerable + * { + * const Left='Left'; + * const Right='Right'; + * } + * + * Then, one can use the enumerable values such as TTextAlign::Left and + * TTextAlign::Right. + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class TEnumerable +{ +} + +/** + * TPropertyValue class + * + * TPropertyValue is a utility class that provides static methods + * to convert component property values to specific types. + * + * TPropertyValue is commonly used in component setter methods to ensure + * the new property value is of specific type. + * For example, a boolean-typed property setter method would be as follows, + * + * function setPropertyName($value) { + * $value=TPropertyValue::ensureBoolean($value); + * // $value is now of boolean type + * } + * + * + * Properties can be of the following types with specific type conversion rules: + * - string: a boolean value will be converted to 'true' or 'false'. + * - boolean: string 'true' (case-insensitive) will be converted to true, + * string 'false' (case-insensitive) will be converted to false. + * - integer + * - float + * - array: string starting with '(' and ending with ')' will be considered as + * as an array expression and will be evaluated. Otherwise, an array + * with the value to be ensured is returned. + * - object + * - enum: enumerable type, represented by an array of strings. + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class TPropertyValue +{ + /** + * Converts a value to boolean type. + * Note, string 'true' (case-insensitive) will be converted to true, + * string 'false' (case-insensitive) will be converted to false. + * If a string represents a non-zero number, it will be treated as true. + * @param mixed the value to be converted. + * @return boolean + */ + public static function ensureBoolean($value) + { + if (is_string($value)) + return strcasecmp($value,'true')==0 || $value!=0; + else + return (boolean)$value; + } + + /** + * Converts a value to string type. + * Note, a boolean value will be converted to 'true' if it is true + * and 'false' if it is false. + * @param mixed the value to be converted. + * @return string + */ + public static function ensureString($value) + { + if (is_bool($value)) + return $value?'true':'false'; + else + return (string)$value; + } + + /** + * Converts a value to integer type. + * @param mixed the value to be converted. + * @return integer + */ + public static function ensureInteger($value) + { + return (integer)$value; + } + + /** + * Converts a value to float type. + * @param mixed the value to be converted. + * @return float + */ + public static function ensureFloat($value) + { + return (float)$value; + } + + /** + * Converts a value to array type. If the value is a string and it is + * in the form (a,b,c) then an array consisting of each of the elements + * will be returned. If the value is a string and it is not in this form + * then an array consisting of just the string will be returned. If the value + * is not a string then + * @param mixed the value to be converted. + * @return array + */ + public static function ensureArray($value) + { + if(is_string($value)) + { + $trimmed = trim($value); + $len = strlen($value); + if ($len >= 2 && $trimmed[0] == '(' && $trimmed[$len-1] == ')') + { + eval('$array=array'.$trimmed.';'); + return $array; + } + else + return $len>0?array($value):array(); + } + else + return (array)$value; + } + + /** + * Converts a value to object type. + * @param mixed the value to be converted. + * @return object + */ + public static function ensureObject($value) + { + return (object)$value; + } + + /** + * Converts a value to enum type. + * + * This method checks if the value is of the specified enumerable type. + * A value is a valid enumerable value if it is equal to the name of a constant + * in the specified enumerable type (class). + * For more details about enumerable, see {@link TEnumerable}. + * + * For backward compatibility, this method also supports sanity + * check of a string value to see if it is among the given list of strings. + * @param mixed the value to be converted. + * @param mixed class name of the enumerable type, or array of valid enumeration values. If this is not an array, + * the method considers its parameters are of variable length, and the second till the last parameters are enumeration values. + * @return string the valid enumeration value + * @throws TInvalidDataValueException if the original value is not in the string array. + */ + public static function ensureEnum($value,$enums) + { + static $types=array(); + if(func_num_args()===2 && is_string($enums)) + { + if(!isset($types[$enums])) + $types[$enums]=new ReflectionClass($enums); + if($types[$enums]->hasConstant($value)) + return $value; + else + throw new TInvalidDataValueException( + 'propertyvalue_enumvalue_invalid',$value, + implode(' | ',$types[$enums]->getConstants())); + } + else if(!is_array($enums)) + { + $enums=func_get_args(); + array_shift($enums); + } + if(in_array($value,$enums,true)) + return $value; + else + throw new TInvalidDataValueException('propertyvalue_enumvalue_invalid',$value,implode(' | ',$enums)); + } +} + +/** + * TEventParameter class. + * TEventParameter is the base class for all event parameter classes. + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class TEventParameter extends TComponent +{ +} + +/** + * TComponentReflection class. + * + * TComponentReflection provides functionalities to inspect the public/protected + * properties, events and methods defined in a class. + * + * The following code displays the properties and events defined in {@link TDataGrid}, + * + * $reflection=new TComponentReflection('TDataGrid'); + * Prado::varDump($reflection->getProperties()); + * Prado::varDump($reflection->getEvents()); + * + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class TComponentReflection extends TComponent +{ + private $_className; + private $_properties=array(); + private $_events=array(); + private $_methods=array(); + + /** + * Constructor. + * @param object|string the component instance or the class name + * @throws TInvalidDataTypeException if the object is not a component + */ + public function __construct($component) + { + if(is_string($component) && class_exists($component,false)) + $this->_className=$component; + else if(is_object($component)) + $this->_className=get_class($component); + else + throw new TInvalidDataTypeException('componentreflection_class_invalid'); + $this->reflect(); + } + + private function isPropertyMethod($method) + { + $methodName=$method->getName(); + return $method->getNumberOfRequiredParameters()===0 + && strncasecmp($methodName,'get',3)===0 + && isset($methodName[3]); + } + + private function isEventMethod($method) + { + $methodName=$method->getName(); + return strncasecmp($methodName,'on',2)===0 + && isset($methodName[2]); + } + + private function reflect() + { + $class=new TReflectionClass($this->_className); + $properties=array(); + $events=array(); + $methods=array(); + $isComponent=is_subclass_of($this->_className,'TComponent') || strcasecmp($this->_className,'TComponent')===0; + foreach($class->getMethods() as $method) + { + if($method->isPublic() || $method->isProtected()) + { + $methodName=$method->getName(); + if(!$method->isStatic() && $isComponent) + { + if($this->isPropertyMethod($method)) + $properties[substr($methodName,3)]=$method; + else if($this->isEventMethod($method)) + { + $methodName[0]='O'; + $events[$methodName]=$method; + } + } + if(strncmp($methodName,'__',2)!==0) + $methods[$methodName]=$method; + } + } + $reserved=array(); + ksort($properties); + foreach($properties as $name=>$method) + { + $this->_properties[$name]=array( + 'type'=>$this->determinePropertyType($method), + 'readonly'=>!$class->hasMethod('set'.$name), + 'protected'=>$method->isProtected(), + 'class'=>$method->getDeclaringClass()->getName(), + 'comments'=>$method->getDocComment() + ); + $reserved['get'.strtolower($name)]=1; + $reserved['set'.strtolower($name)]=1; + } + ksort($events); + foreach($events as $name=>$method) + { + $this->_events[$name]=array( + 'class'=>$method->getDeclaringClass()->getName(), + 'protected'=>$method->isProtected(), + 'comments'=>$method->getDocComment() + ); + $reserved[strtolower($name)]=1; + } + ksort($methods); + foreach($methods as $name=>$method) + { + if(!isset($reserved[strtolower($name)])) + $this->_methods[$name]=array( + 'class'=>$method->getDeclaringClass()->getName(), + 'protected'=>$method->isProtected(), + 'static'=>$method->isStatic(), + 'comments'=>$method->getDocComment() + ); + } + } + + /** + * Determines the property type. + * This method uses the doc comment to determine the property type. + * @param ReflectionMethod + * @return string the property type, '{unknown}' if type cannot be determined from comment + */ + protected function determinePropertyType($method) + { + $comment=$method->getDocComment(); + if(preg_match('/@return\\s+(.*?)\\s+/',$comment,$matches)) + return $matches[1]; + else + return '{unknown}'; + } + + /** + * @return string class name of the component + */ + public function getClassName() + { + return $this->_className; + } + + /** + * @return array list of component properties. Array keys are property names. + * Each array element is of the following structure: + * [type]=>property type, + * [readonly]=>whether the property is read-only, + * [protected]=>whether the method is protected or not + * [class]=>the class where the property is inherited from, + * [comments]=>comments associated with the property. + */ + public function getProperties() + { + return $this->_properties; + } + + /** + * @return array list of component events. Array keys are event names. + * Each array element is of the following structure: + * [protected]=>whether the event is protected or not + * [class]=>the class where the event is inherited from. + * [comments]=>comments associated with the event. + */ + public function getEvents() + { + return $this->_events; + } + + /** + * @return array list of public/protected methods. Array keys are method names. + * Each array element is of the following structure: + * [protected]=>whether the method is protected or not + * [static]=>whether the method is static or not + * [class]=>the class where the property is inherited from, + * [comments]=>comments associated with the event. + */ + public function getMethods() + { + return $this->_methods; + } +} + ?> \ No newline at end of file -- cgit v1.2.3