JOOMLA中国
  • Joomla中国首页
  • 社区
  • 教程
  • 应用市场
  • B计划
Joomla! Framework TM
  • Namespace
  • Class
  • Tree
  • Deprecated

Namespaces

  • Composer
    • Autoload
  • Joomla
    • Application
      • Cli
        • Output
          • Processor
      • Web
    • Data
    • DI
      • Exception
    • Event
    • Filter
    • Input
    • Ldap
    • Registry
      • Format
    • Session
      • Storage
    • String
    • Uri
    • Utilities
  • None
  • PasswordCompat
    • binary
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Yaml
        • Exception
    • Polyfill
      • Util

Classes

  • CallbackFilterIterator
  • ComposerAutoloaderInit205c915b9c7d3e718e7c95793ee67ffe
  • easyparse
  • EasyPeasyICS
  • FOFAutoloaderComponent
  • FOFAutoloaderFof
  • FOFConfigDomainDispatcher
  • FOFConfigDomainTables
  • FOFConfigDomainViews
  • FOFConfigProvider
  • FOFController
  • FOFDatabase
  • FOFDatabaseDriver
  • FOFDatabaseDriverJoomla
  • FOFDatabaseDriverMysql
  • FOFDatabaseDriverMysqli
  • FOFDatabaseDriverOracle
  • FOFDatabaseDriverPdo
  • FOFDatabaseDriverPdomysql
  • FOFDatabaseDriverPostgresql
  • FOFDatabaseDriverSqlazure
  • FOFDatabaseDriverSqlite
  • FOFDatabaseDriverSqlsrv
  • FOFDatabaseFactory
  • FOFDatabaseInstaller
  • FOFDatabaseIterator
  • FOFDatabaseIteratorAzure
  • FOFDatabaseIteratorMysql
  • FOFDatabaseIteratorMysqli
  • FOFDatabaseIteratorOracle
  • FOFDatabaseIteratorPdo
  • FOFDatabaseIteratorPdomysql
  • FOFDatabaseIteratorPostgresql
  • FOFDatabaseIteratorSqlite
  • FOFDatabaseIteratorSqlsrv
  • FOFDatabaseQuery
  • FOFDatabaseQueryElement
  • FOFDatabaseQueryMysql
  • FOFDatabaseQueryMysqli
  • FOFDatabaseQueryOracle
  • FOFDatabaseQueryPdo
  • FOFDatabaseQueryPdomysql
  • FOFDatabaseQueryPostgresql
  • FOFDatabaseQuerySqlazure
  • FOFDatabaseQuerySqlite
  • FOFDatabaseQuerySqlsrv
  • FOFDispatcher
  • FOFDownload
  • FOFDownloadAdapterAbstract
  • FOFDownloadAdapterCurl
  • FOFDownloadAdapterFopen
  • FOFEncryptAes
  • FOFEncryptAesAbstract
  • FOFEncryptAesMcrypt
  • FOFEncryptAesOpenssl
  • FOFEncryptBase32
  • FOFEncryptRandval
  • FOFEncryptTotp
  • FOFForm
  • FOFFormFieldAccesslevel
  • FOFFormFieldActions
  • FOFFormFieldButton
  • FOFFormFieldCachehandler
  • FOFFormFieldCalendar
  • FOFFormFieldCaptcha
  • FOFFormFieldCheckbox
  • FOFFormFieldCheckboxes
  • FOFFormFieldComponents
  • FOFFormFieldEditor
  • FOFFormFieldEmail
  • FOFFormFieldGroupedbutton
  • FOFFormFieldGroupedlist
  • FOFFormFieldHidden
  • FOFFormFieldImage
  • FOFFormFieldImagelist
  • FOFFormFieldInteger
  • FOFFormFieldLanguage
  • FOFFormFieldList
  • FOFFormFieldMedia
  • FOFFormFieldModel
  • FOFFormFieldOrdering
  • FOFFormFieldPassword
  • FOFFormFieldPlugins
  • FOFFormFieldPublished
  • FOFFormFieldRadio
  • FOFFormFieldRelation
  • FOFFormFieldRules
  • FOFFormFieldSelectrow
  • FOFFormFieldSessionhandler
  • FOFFormFieldSpacer
  • FOFFormFieldSql
  • FOFFormFieldTag
  • FOFFormFieldTel
  • FOFFormFieldText
  • FOFFormFieldTextarea
  • FOFFormFieldTimezone
  • FOFFormFieldTitle
  • FOFFormFieldUrl
  • FOFFormFieldUser
  • FOFFormFieldUsergroup
  • FOFFormHeader
  • FOFFormHeaderAccesslevel
  • FOFFormHeaderField
  • FOFFormHeaderFielddate
  • FOFFormHeaderFieldfilterable
  • FOFFormHeaderFieldsearchable
  • FOFFormHeaderFieldselectable
  • FOFFormHeaderFieldsql
  • FOFFormHeaderFilterdate
  • FOFFormHeaderFilterfilterable
  • FOFFormHeaderFiltersearchable
  • FOFFormHeaderFilterselectable
  • FOFFormHeaderFiltersql
  • FOFFormHeaderLanguage
  • FOFFormHeaderModel
  • FOFFormHeaderOrdering
  • FOFFormHeaderPublished
  • FOFFormHeaderRowselect
  • FOFFormHelper
  • FOFHalDocument
  • FOFHalLink
  • FOFHalLinks
  • FOFHalRenderJson
  • FOFInflector
  • FOFInput
  • FOFIntegrationJoomlaFilesystem
  • FOFIntegrationJoomlaPlatform
  • FOFLayoutFile
  • FOFLayoutHelper
  • FOFLess
  • FOFLessFormatterClassic
  • FOFLessFormatterCompressed
  • FOFLessFormatterJoomla
  • FOFLessFormatterLessjs
  • FOFLessParser
  • FOFModel
  • FOFModelBehavior
  • FOFModelBehaviorAccess
  • FOFModelBehaviorEmptynonzero
  • FOFModelBehaviorEnabled
  • FOFModelBehaviorFilters
  • FOFModelBehaviorLanguage
  • FOFModelBehaviorPrivate
  • FOFModelDispatcherBehavior
  • FOFModelField
  • FOFModelFieldBoolean
  • FOFModelFieldDate
  • FOFModelFieldNumber
  • FOFModelFieldText
  • FOFPlatform
  • FOFPlatformFilesystem
  • FOFQueryAbstract
  • FOFRenderAbstract
  • FOFRenderJoomla
  • FOFRenderJoomla3
  • FOFRenderStrapper
  • FOFStringUtils
  • FOFTable
  • FOFTableBehavior
  • FOFTableBehaviorAssets
  • FOFTableBehaviorContenthistory
  • FOFTableBehaviorTags
  • FOFTableDispatcherBehavior
  • FOFTableNested
  • FOFTableRelations
  • FOFTemplateUtils
  • FOFToolbar
  • FOFUtilsArray
  • FOFUtilsCacheCleaner
  • FOFUtilsConfigHelper
  • FOFUtilsFilescheck
  • FOFUtilsIniParser
  • FOFUtilsInstallscript
  • FOFUtilsIp
  • FOFUtilsObject
  • FOFUtilsObservableDispatcher
  • FOFUtilsObservableEvent
  • FOFUtilsPhpfunc
  • FOFUtilsTimer
  • FOFUtilsUpdate
  • FOFUtilsUpdateCollection
  • FOFUtilsUpdateExtension
  • FOFUtilsUpdateJoomla
  • FOFView
  • FOFViewCsv
  • FOFViewForm
  • FOFViewHtml
  • FOFViewJson
  • FOFViewRaw
  • idna_convert
  • JAccess
  • JAccessRule
  • JAccessRules
  • JAccessWrapperAccess
  • JAdapter
  • JAdapterInstance
  • JApplication
  • JApplicationAdministrator
  • JApplicationBase
  • JApplicationCli
  • JApplicationCms
  • JApplicationDaemon
  • JApplicationHelper
  • JApplicationSite
  • JApplicationWeb
  • JApplicationWebRouter
  • JApplicationWebRouterBase
  • JApplicationWebRouterRest
  • JArchive
  • JArchiveBzip2
  • JArchiveGzip
  • JArchiveTar
  • JArchiveWrapperArchive
  • JArchiveZip
  • JArrayHelper
  • JAssociationExtensionHelper
  • JAuthentication
  • JAuthenticationHelper
  • JAuthenticationResponse
  • JBrowser
  • JBuffer
  • JButton
  • JCache
  • JCacheController
  • JCacheControllerCallback
  • JCacheControllerOutput
  • JCacheControllerPage
  • JCacheControllerView
  • JCacheStorage
  • JCacheStorageApc
  • JCacheStorageApcu
  • JCacheStorageCachelite
  • JCacheStorageFile
  • JCacheStorageHelper
  • JCacheStorageMemcache
  • JCacheStorageMemcached
  • JCacheStorageRedis
  • JCacheStorageWincache
  • JCacheStorageXcache
  • JCaptcha
  • JCategories
  • JCategoryNode
  • JClassLoader
  • JCli
  • JClientFtp
  • JClientHelper
  • JClientLdap
  • JClientWrapperHelper
  • JComponentHelper
  • JComponentRecord
  • JComponentRouterBase
  • JComponentRouterLegacy
  • JComponentRouterRulesMenu
  • JComponentRouterRulesNomenu
  • JComponentRouterRulesStandard
  • JComponentRouterView
  • JComponentRouterViewconfiguration
  • JControllerAdmin
  • JControllerBase
  • JControllerForm
  • JControllerLegacy
  • JCrypt
  • JCryptCipher3Des
  • JCryptCipherBlowfish
  • JCryptCipherCrypto
  • JCryptCipherMcrypt
  • JCryptCipherRijndael256
  • JCryptCipherSimple
  • JCryptKey
  • JCryptPasswordSimple
  • JDaemon
  • JDatabase
  • JDatabaseDriver
  • JDatabaseDriverMysql
  • JDatabaseDriverMysqli
  • JDatabaseDriverOracle
  • JDatabaseDriverPdo
  • JDatabaseDriverPdomysql
  • JDatabaseDriverPostgresql
  • JDatabaseDriverSqlazure
  • JDatabaseDriverSqlite
  • JDatabaseDriverSqlsrv
  • JDatabaseExporter
  • JDatabaseExporterMysql
  • JDatabaseExporterMysqli
  • JDatabaseExporterPdomysql
  • JDatabaseExporterPostgresql
  • JDatabaseFactory
  • JDatabaseImporter
  • JDatabaseImporterMysql
  • JDatabaseImporterMysqli
  • JDatabaseImporterPdomysql
  • JDatabaseImporterPostgresql
  • JDatabaseInterface
  • JDatabaseIterator
  • JDatabaseIteratorMysql
  • JDatabaseIteratorMysqli
  • JDatabaseIteratorOracle
  • JDatabaseIteratorPdo
  • JDatabaseIteratorPdomysql
  • JDatabaseIteratorPostgresql
  • JDatabaseIteratorSqlazure
  • JDatabaseIteratorSqlite
  • JDatabaseIteratorSqlsrv
  • JDatabaseMysql
  • JDatabaseMysqli
  • JDatabaseQuery
  • JDatabaseQueryElement
  • JDatabaseQueryLimitable
  • JDatabaseQueryMysql
  • JDatabaseQueryMysqli
  • JDatabaseQueryOracle
  • JDatabaseQueryPdo
  • JDatabaseQueryPdomysql
  • JDatabaseQueryPostgresql
  • JDatabaseQueryPreparable
  • JDatabaseQuerySqlazure
  • JDatabaseQuerySqlite
  • JDatabaseQuerySqlsrv
  • JDatabaseSqlazure
  • JDatabaseSqlsrv
  • JDate
  • JDispatcher
  • JDocument
  • JDocumentError
  • JDocumentFeed
  • JDocumentHtml
  • JDocumentImage
  • JDocumentJson
  • JDocumentOpensearch
  • JDocumentRaw
  • JDocumentRenderer
  • JDocumentRendererAtom
  • JDocumentRendererComponent
  • JDocumentRendererFeedAtom
  • JDocumentRendererFeedRss
  • JDocumentRendererHead
  • JDocumentRendererHtmlComponent
  • JDocumentRendererHtmlHead
  • JDocumentRendererHtmlMessage
  • JDocumentRendererHtmlModule
  • JDocumentRendererHtmlModules
  • JDocumentRendererMessage
  • JDocumentRendererModule
  • JDocumentRendererModules
  • JDocumentRendererRSS
  • JDocumentXml
  • JEditor
  • JError
  • JErrorPage
  • JEvent
  • JEventDispatcher
  • JExtension
  • JFacebook
  • JFacebookAlbum
  • JFacebookCheckin
  • JFacebookComment
  • JFacebookEvent
  • JFacebookGroup
  • JFacebookLink
  • JFacebookNote
  • JFacebookOAuth
  • JFacebookObject
  • JFacebookPhoto
  • JFacebookPost
  • JFacebookStatus
  • JFacebookUser
  • JFacebookVideo
  • JFactory
  • JFeed
  • JFeedEnclosure
  • JFeedEntry
  • JFeedFactory
  • JFeedImage
  • JFeedItem
  • JFeedLink
  • JFeedParser
  • JFeedParserAtom
  • JFeedParserRss
  • JFeedParserRssItunes
  • JFeedParserRssMedia
  • JFeedPerson
  • JFile
  • JFilesystemHelper
  • JFilesystemPatcher
  • JFilesystemWrapperFile
  • JFilesystemWrapperFolder
  • JFilesystemWrapperPath
  • JFilterInput
  • JFilterOutput
  • JFilterWrapperOutput
  • JFolder
  • JForm
  • JFormField
  • JFormFieldAccessLevel
  • JFormFieldAliastag
  • JFormFieldAuthor
  • JFormFieldCacheHandler
  • JFormFieldCalendar
  • JFormFieldCaptcha
  • JFormFieldCategory
  • JFormFieldCheckbox
  • JFormFieldCheckboxes
  • JFormFieldChromeStyle
  • JFormFieldColor
  • JFormFieldCombo
  • JFormFieldComponentlayout
  • JFormFieldComponents
  • JFormFieldContenthistory
  • JFormFieldContentlanguage
  • JFormFieldContenttype
  • JFormFieldDatabaseConnection
  • JFormFieldEditor
  • JFormFieldEMail
  • JFormFieldFile
  • JFormFieldFileList
  • JFormFieldFolderList
  • JFormFieldFrontend_Language
  • JFormFieldGroupedList
  • JFormFieldHeadertag
  • JFormFieldHelpsite
  • JFormFieldHidden
  • JFormFieldImageList
  • JFormFieldInteger
  • JFormFieldLanguage
  • JFormFieldLastvisitDateRange
  • JFormFieldLimitbox
  • JFormFieldList
  • JFormFieldMedia
  • JFormFieldMenu
  • JFormFieldMenuitem
  • JFormFieldMeter
  • JFormFieldModulelayout
  • JFormFieldModuleOrder
  • JFormFieldModulePosition
  • JFormFieldModuletag
  • JFormFieldNote
  • JFormFieldNumber
  • JFormFieldOrdering
  • JFormFieldPassword
  • JFormFieldPlugin_Status
  • JFormFieldPlugins
  • JFormFieldPredefinedList
  • JFormFieldRadio
  • JFormFieldRange
  • JFormFieldRegistrationDateRange
  • JFormFieldRepeatable
  • JFormFieldRules
  • JFormFieldSessionHandler
  • JFormFieldSpacer
  • JFormFieldSQL
  • JFormFieldStatus
  • JFormFieldSubform
  • JFormFieldTag
  • JFormFieldTel
  • JFormFieldTemplatestyle
  • JFormFieldText
  • JFormFieldTextarea
  • JFormFieldTimezone
  • JFormFieldUrl
  • JFormFieldUser
  • JFormFieldUserActive
  • JFormFieldUsergroup
  • JFormFieldUserGroupList
  • JFormFieldUserState
  • JFormHelper
  • JFormRule
  • JFormRuleBoolean
  • JFormRuleCalendar
  • JFormRuleCaptcha
  • JFormRuleColor
  • JFormRuleEmail
  • JFormRuleEquals
  • JFormRuleNotequals
  • JFormRuleNumber
  • JFormRuleOptions
  • JFormRulePassword
  • JFormRuleRules
  • JFormRuleTel
  • JFormRuleUrl
  • JFormRuleUsername
  • JFormWrapperHelper
  • JFTP
  • JGithub
  • JGithubAccount
  • JGithubCommits
  • JGithubForks
  • JGithubHooks
  • JGithubHttp
  • JGithubMeta
  • JGithubMilestones
  • JGithubObject
  • JGithubPackage
  • JGithubPackageActivity
  • JGithubPackageActivityEvents
  • JGithubPackageActivityNotifications
  • JGithubPackageActivityStarring
  • JGithubPackageActivityWatching
  • JGithubPackageAuthorization
  • JGithubPackageData
  • JGithubPackageDataBlobs
  • JGithubPackageDataCommits
  • JGithubPackageDataRefs
  • JGithubPackageDataTags
  • JGithubPackageDataTrees
  • JGithubPackageGists
  • JGithubPackageGistsComments
  • JGithubPackageGitignore
  • JGithubPackageIssues
  • JGithubPackageIssuesAssignees
  • JGithubPackageIssuesComments
  • JGithubPackageIssuesEvents
  • JGithubPackageIssuesLabels
  • JGithubPackageIssuesMilestones
  • JGithubPackageMarkdown
  • JGithubPackageOrgs
  • JGithubPackageOrgsMembers
  • JGithubPackageOrgsTeams
  • JGithubPackagePulls
  • JGithubPackagePullsComments
  • JGithubPackageRepositories
  • JGithubPackageRepositoriesCollaborators
  • JGithubPackageRepositoriesComments
  • JGithubPackageRepositoriesCommits
  • JGithubPackageRepositoriesContents
  • JGithubPackageRepositoriesDownloads
  • JGithubPackageRepositoriesForks
  • JGithubPackageRepositoriesHooks
  • JGithubPackageRepositoriesKeys
  • JGithubPackageRepositoriesMerging
  • JGithubPackageRepositoriesStatistics
  • JGithubPackageRepositoriesStatuses
  • JGithubPackageSearch
  • JGithubPackageUsers
  • JGithubPackageUsersEmails
  • JGithubPackageUsersFollowers
  • JGithubPackageUsersKeys
  • JGithubRefs
  • JGithubStatuses
  • JGoogle
  • JGoogleAuth
  • JGoogleAuthOauth2
  • JGoogleData
  • JGoogleDataAdsense
  • JGoogleDataCalendar
  • JGoogleDataPicasa
  • JGoogleDataPicasaAlbum
  • JGoogleDataPicasaPhoto
  • JGoogleDataPlus
  • JGoogleDataPlusActivities
  • JGoogleDataPlusComments
  • JGoogleDataPlusPeople
  • JGoogleEmbed
  • JGoogleEmbedAnalytics
  • JGoogleEmbedMaps
  • JGrid
  • JHelp
  • JHelper
  • JHelperContent
  • JHelperContenthistory
  • JHelperMedia
  • JHelperRoute
  • JHelperTags
  • JHelperUsergroups
  • JHtml
  • JHtmlAccess
  • JHtmlActionsDropdown
  • JHtmlBatch
  • JHtmlBehavior
  • JHtmlBootstrap
  • JHtmlCategory
  • JHtmlContent
  • JHtmlContentLanguage
  • JHtmlDate
  • JHtmlDebug
  • JHtmlDropdown
  • JHtmlEmail
  • JHtmlForm
  • JHtmlFormbehavior
  • JHtmlGrid
  • JHtmlIcons
  • JHtmlJGrid
  • JHtmlJquery
  • JHtmlLinks
  • JHtmlList
  • JHtmlMenu
  • JHtmlNumber
  • JHtmlRules
  • JHtmlSearchtools
  • JHtmlSelect
  • JHtmlSidebar
  • JHtmlSliders
  • JHtmlSortablelist
  • JHtmlString
  • JHtmlTabs
  • JHtmlTag
  • JHtmlTel
  • JHtmlUser
  • JHttp
  • JHttpFactory
  • JHttpResponse
  • JHttpTransportCurl
  • JHttpTransportSocket
  • JHttpTransportStream
  • JHttpWrapperFactory
  • JImage
  • JImageFilter
  • JImageFilterBackgroundfill
  • JImageFilterBrightness
  • JImageFilterContrast
  • JImageFilterEdgedetect
  • JImageFilterEmboss
  • JImageFilterGrayscale
  • JImageFilterNegate
  • JImageFilterSketchy
  • JImageFilterSmooth
  • JInput
  • JInputCli
  • JInputCookie
  • JInputFiles
  • JInputJSON
  • JInstaller
  • JInstallerAdapter
  • JInstallerAdapterComponent
  • JInstallerAdapterFile
  • JInstallerAdapterLanguage
  • JInstallerAdapterLibrary
  • JInstallerAdapterModule
  • JInstallerAdapterPackage
  • JInstallerAdapterPlugin
  • JInstallerAdapterTemplate
  • JInstallerComponent
  • JInstallerExtension
  • JInstallerFile
  • JInstallerHelper
  • JInstallerLanguage
  • JInstallerLibrary
  • JInstallerManifest
  • JInstallerManifestLibrary
  • JInstallerManifestPackage
  • JInstallerModule
  • JInstallerPackage
  • JInstallerPlugin
  • JInstallerScript
  • JInstallerTemplate
  • JKeychain
  • JLanguage
  • JLanguageAssociations
  • JLanguageHelper
  • JLanguageMultilang
  • JLanguageStemmer
  • JLanguageStemmerPorteren
  • JLanguageTransliterate
  • JLanguageWrapperHelper
  • JLanguageWrapperText
  • JLanguageWrapperTransliterate
  • JLayoutBase
  • JLayoutFile
  • JLayoutHelper
  • JLDAP
  • JLess
  • JLessFormatterJoomla
  • JLibraryHelper
  • JLinkedin
  • JLinkedinCommunications
  • JLinkedinCompanies
  • JLinkedinGroups
  • JLinkedinJobs
  • JLinkedinOauth
  • JLinkedinObject
  • JLinkedinPeople
  • JLinkedinStream
  • JLoader
  • JLog
  • JLogEntry
  • JLogger
  • JLogLogger
  • JLogLoggerCallback
  • JLogLoggerDatabase
  • JLogLoggerEcho
  • JLogLoggerFormattedtext
  • JLogLoggerMessagequeue
  • JLogLoggerSyslog
  • JLogLoggerW3c
  • JMail
  • JMailHelper
  • JMailWrapperHelper
  • JMediawiki
  • JMediawikiCategories
  • JMediawikiHttp
  • JMediawikiImages
  • JMediawikiLinks
  • JMediawikiObject
  • JMediawikiPages
  • JMediawikiSearch
  • JMediawikiSites
  • JMediawikiUsers
  • JMenu
  • JMenuAdministrator
  • JMenuItem
  • JMenuSite
  • JMicrodata
  • JModelAdmin
  • JModelBase
  • JModelDatabase
  • JModelForm
  • JModelItem
  • JModelLegacy
  • JModelList
  • JModuleHelper
  • JNode
  • JOAuth1Client
  • JOAuth2Client
  • JObject
  • JObservable
  • JObserver
  • JObserverMapper
  • JObserverUpdater
  • JObserverWrapperMapper
  • JOpenSearchImage
  • JOpenSearchUrl
  • JOpenstreetmap
  • JOpenstreetmapChangesets
  • JOpenstreetmapElements
  • JOpenstreetmapGps
  • JOpenstreetmapInfo
  • JOpenstreetmapOauth
  • JOpenstreetmapObject
  • JOpenstreetmapUser
  • JPagination
  • JPaginationObject
  • JPath
  • JPathway
  • JPathwaySite
  • JPlatform
  • JPlugin
  • JPluginHelper
  • JProfiler
  • JRequest
  • JResponse
  • JResponseJson
  • JRoute
  • JRouter
  • JRouterAdministrator
  • JRouterSite
  • JRouteWrapperRoute
  • JRule
  • JRules
  • JSchemaChangeitem
  • JSchemaChangeitemMysql
  • JSchemaChangeitemPostgresql
  • JSchemaChangeitemSqlsrv
  • JSchemaChangeset
  • JSearchHelper
  • JSession
  • JSessionHandlerJoomla
  • JSessionHandlerNative
  • JSessionStorage
  • JSessionStorageApc
  • JSessionStorageDatabase
  • JSessionStorageMemcache
  • JSessionStorageMemcached
  • JSessionStorageNone
  • JSessionStorageWincache
  • JSessionStorageXcache
  • JSimplecrypt
  • JSimplepieFactory
  • JStream
  • JStreamString
  • JString
  • JStringController
  • JStringPunycode
  • JStringWrapperNormalise
  • JStringWrapperPunycode
  • JTable
  • JTableAsset
  • JTableCategory
  • JTableContent
  • JTableContenthistory
  • JTableContenttype
  • JTableCorecontent
  • JTableExtension
  • JTableInterface
  • JTableLanguage
  • JTableMenu
  • JTableMenuType
  • JTableModule
  • JTableNested
  • JTableObserver
  • JTableObserverContenthistory
  • JTableObserverTags
  • JTableSession
  • JTableUcm
  • JTableUpdate
  • JTableUpdatesite
  • JTableUser
  • JTableUsergroup
  • JTableViewlevel
  • JText
  • JToolbar
  • JToolbarButton
  • JToolbarButtonConfirm
  • JToolbarButtonCustom
  • JToolbarButtonHelp
  • JToolbarButtonLink
  • JToolbarButtonPopup
  • JToolbarButtonSeparator
  • JToolbarButtonSlider
  • JToolbarButtonStandard
  • JTree
  • JTwitter
  • JTwitterBlock
  • JTwitterDirectmessages
  • JTwitterFavorites
  • JTwitterFriends
  • JTwitterHelp
  • JTwitterLists
  • JTwitterOAuth
  • JTwitterObject
  • JTwitterPlaces
  • JTwitterProfile
  • JTwittersearch
  • JTwitterStatuses
  • JTwitterTrends
  • JTwitterUsers
  • JUcmBase
  • JUcmContent
  • JUcmType
  • JUpdate
  • JUpdateAdapter
  • JUpdater
  • JUpdaterCollection
  • JUpdaterExtension
  • JUri
  • JUser
  • JUserHelper
  • JUserWrapperHelper
  • JUtility
  • JVersion
  • JViewBase
  • JViewCategories
  • JViewCategory
  • JViewCategoryfeed
  • JViewHtml
  • JViewLegacy
  • JWeb
  • JWebClient
  • JXMLElement
  • lessc
  • lessc_formatter_classic
  • lessc_formatter_compressed
  • lessc_formatter_lessjs
  • lessc_parser
  • lessify
  • Net_IDNA_php4
  • nodecounter
  • ntlm_sasl_client_class
  • PHPMailer
  • PHPMailerOAuth
  • PHPMailerOAuthGoogle
  • POP3
  • SimplePie
  • SimplePie_Author
  • SimplePie_Autoloader
  • SimplePie_Cache
  • SimplePie_Cache_DB
  • SimplePie_Cache_File
  • SimplePie_Cache_Memcache
  • SimplePie_Cache_MySQL
  • SimplePie_Caption
  • SimplePie_Category
  • SimplePie_Content_Type_Sniffer
  • SimplePie_Copyright
  • SimplePie_Core
  • SimplePie_Credit
  • SimplePie_Decode_HTML_Entities
  • SimplePie_Enclosure
  • SimplePie_File
  • SimplePie_gzdecode
  • SimplePie_HTTP_Parser
  • SimplePie_IRI
  • SimplePie_Item
  • SimplePie_Locator
  • SimplePie_Misc
  • SimplePie_Net_IPv6
  • SimplePie_Parse_Date
  • SimplePie_Parser
  • SimplePie_Rating
  • SimplePie_Registry
  • SimplePie_Restriction
  • SimplePie_Sanitize
  • SimplePie_Source
  • SimplePie_XML_Declaration_Parser
  • SMTP
  • tagparse
  • TypeError

Interfaces

  • FOFConfigDomainInterface
  • FOFDatabaseInterface
  • FOFDatabaseQueryLimitable
  • FOFDatabaseQueryPreparable
  • FOFDownloadInterface
  • FOFEncryptAesInterface
  • FOFEncryptRandvalinterface
  • FOFFormField
  • FOFHalRenderInterface
  • FOFPlatformFilesystemInterface
  • FOFPlatformInterface
  • JArchiveExtractable
  • JAssociationExtensionInterface
  • JCacheException
  • JComponentRouterInterface
  • JComponentRouterRulesInterface
  • JController
  • JCryptCipher
  • JCryptPassword
  • JFeedParserNamespace
  • JHttpTransport
  • JLayout
  • JModel
  • JObservableInterface
  • JObserverInterface
  • JObserverUpdaterInterface
  • JSessionHandlerInterface
  • JsonSerializable
  • JUcm
  • JView
  • SimplePie_Cache_Base

Exceptions

  • Error
  • JAccessExceptionNotallowed
  • JCacheExceptionConnecting
  • JCacheExceptionUnsupported
  • JComponentExceptionMissing
  • JDatabaseException
  • JDatabaseExceptionConnecting
  • JDatabaseExceptionExecuting
  • JDatabaseExceptionUnsupported
  • JException
  • JSessionExceptionUnsupported
  • LogException
  • phpmailerException
  • SimplePie_Exception

Constants

  • JERROR_CALLBACK_NOT_CALLABLE
  • JERROR_ILLEGAL_MODE
  • JERROR_ILLEGAL_OPTIONS
  • JREQUEST_ALLOWHTML
  • JREQUEST_ALLOWRAW
  • JREQUEST_NOTRIM
  • JROUTER_MODE_RAW
  • JROUTER_MODE_SEF

Functions

  • __autoload
  • array_column
  • boolval
  • composerRequire205c915b9c7d3e718e7c95793ee67ffe
  • gzopen
  • gzseek
  • gztell
  • hash_equals
  • hash_pbkdf2
  • HTMLFilter
  • jexit
  • jimport
  • json_last_error_msg
  • ldap_escape
  • password_get_info
  • password_hash
  • password_needs_rehash
  • password_verify
  • PHPMailerAutoload
  • random_bytes
  • random_int
  • RandomCompat_intval
  • RandomCompat_strlen
  • RandomCompat_substr
  • tln_body2div
  • tln_casenormalize
  • tln_deent
  • tln_defang
  • tln_findnxreg
  • tln_findnxstr
  • tln_fixatts
  • tln_fixstyle
  • tln_fixurl
  • tln_getnxtag
  • tln_sanitize
  • tln_skipspace
  • tln_tagprint
  • tln_unspace
  • utf8_accents_to_ascii
  • utf8_bad_explain
  • utf8_bad_find
  • utf8_bad_findall
  • utf8_bad_identify
  • utf8_bad_replace
  • utf8_bad_strip
  • utf8_byte_position
  • utf8_compliant
  • utf8_from_unicode
  • utf8_ireplace
  • utf8_is_ascii
  • utf8_is_ascii_ctrl
  • utf8_is_valid
  • utf8_is_word_chars
  • utf8_locate_current_chr
  • utf8_locate_next_chr
  • utf8_ltrim
  • utf8_ord
  • utf8_rtrim
  • utf8_specials_pattern
  • utf8_str_pad
  • utf8_str_split
  • utf8_strcasecmp
  • utf8_strcspn
  • utf8_strip_ascii_ctrl
  • utf8_strip_non_ascii
  • utf8_strip_non_ascii_ctrl
  • utf8_strip_specials
  • utf8_stristr
  • utf8_strlen
  • utf8_strpos
  • utf8_strrev
  • utf8_strrpos
  • utf8_strspn
  • utf8_strtolower
  • utf8_strtoupper
  • utf8_substr
  • utf8_substr_replace
  • utf8_to_unicode
  • utf8_trim
  • utf8_ucfirst
  • utf8_ucwords
  • utf8_ucwords_callback
   1 <?php
   2 /**
   3  * @package     Joomla.Platform
   4  * @subpackage  Form
   5  *
   6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
   7  * @license     GNU General Public License version 2 or later; see LICENSE
   8  */
   9 
  10 defined('JPATH_PLATFORM') or die;
  11 
  12 use Joomla\Registry\Registry;
  13 use Joomla\Utilities\ArrayHelper;
  14 
  15 jimport('joomla.filesystem.path');
  16 
  17 /**
  18  * Form Class for the Joomla Platform.
  19  *
  20  * This class implements a robust API for constructing, populating, filtering, and validating forms.
  21  * It uses XML definitions to construct form fields and a variety of field and rule classes to
  22  * render and validate the form.
  23  *
  24  * @link   http://www.w3.org/TR/html4/interact/forms.html
  25  * @link   http://www.w3.org/TR/html5/forms.html
  26  * @since  11.1
  27  */
  28 class JForm
  29 {
  30     /**
  31      * The Registry data store for form fields during display.
  32      *
  33      * @var    Registry
  34      * @since  11.1
  35      */
  36     protected $data;
  37 
  38     /**
  39      * The form object errors array.
  40      *
  41      * @var    array
  42      * @since  11.1
  43      */
  44     protected $errors = array();
  45 
  46     /**
  47      * The name of the form instance.
  48      *
  49      * @var    string
  50      * @since  11.1
  51      */
  52     protected $name;
  53 
  54     /**
  55      * The form object options for use in rendering and validation.
  56      *
  57      * @var    array
  58      * @since  11.1
  59      */
  60     protected $options = array();
  61 
  62     /**
  63      * The form XML definition.
  64      *
  65      * @var    SimpleXMLElement
  66      * @since  11.1
  67      */
  68     protected $xml;
  69 
  70     /**
  71      * Form instances.
  72      *
  73      * @var    JForm[]
  74      * @since  11.1
  75      */
  76     protected static $forms = array();
  77 
  78     /**
  79      * Alows extensions to implement repeating elements
  80      *
  81      * @var    boolean
  82      * @since  3.2
  83      */
  84     public $repeat = false;
  85 
  86     /**
  87      * Method to instantiate the form object.
  88      *
  89      * @param   string  $name     The name of the form.
  90      * @param   array   $options  An array of form options.
  91      *
  92      * @since   11.1
  93      */
  94     public function __construct($name, array $options = array())
  95     {
  96         // Set the name for the form.
  97         $this->name = $name;
  98 
  99         // Initialise the Registry data.
 100         $this->data = new Registry;
 101 
 102         // Set the options if specified.
 103         $this->options['control'] = isset($options['control']) ? $options['control'] : false;
 104     }
 105 
 106     /**
 107      * Method to bind data to the form.
 108      *
 109      * @param   mixed  $data  An array or object of data to bind to the form.
 110      *
 111      * @return  boolean  True on success.
 112      *
 113      * @since   11.1
 114      */
 115     public function bind($data)
 116     {
 117         // Make sure there is a valid JForm XML document.
 118         if (!($this->xml instanceof SimpleXMLElement))
 119         {
 120             return false;
 121         }
 122 
 123         // The data must be an object or array.
 124         if (!is_object($data) && !is_array($data))
 125         {
 126             return false;
 127         }
 128 
 129         $this->bindLevel(null, $data);
 130 
 131         return true;
 132     }
 133 
 134     /**
 135      * Method to bind data to the form for the group level.
 136      *
 137      * @param   string  $group  The dot-separated form group path on which to bind the data.
 138      * @param   mixed   $data   An array or object of data to bind to the form for the group level.
 139      *
 140      * @return  void
 141      *
 142      * @since   11.1
 143      */
 144     protected function bindLevel($group, $data)
 145     {
 146         // Ensure the input data is an array.
 147         if (is_object($data))
 148         {
 149             if ($data instanceof Registry)
 150             {
 151                 // Handle a Registry.
 152                 $data = $data->toArray();
 153             }
 154             elseif ($data instanceof JObject)
 155             {
 156                 // Handle a JObject.
 157                 $data = $data->getProperties();
 158             }
 159             else
 160             {
 161                 // Handle other types of objects.
 162                 $data = (array) $data;
 163             }
 164         }
 165 
 166         // Process the input data.
 167         foreach ($data as $k => $v)
 168         {
 169             $level = $group ? $group . '.' . $k : $k;
 170 
 171             if ($this->findField($k, $group))
 172             {
 173                 // If the field exists set the value.
 174                 $this->data->set($level, $v);
 175             }
 176             elseif (is_object($v) || ArrayHelper::isAssociative($v))
 177             {
 178                 // If the value is an object or an associative array, hand it off to the recursive bind level method.
 179                 $this->bindLevel($level, $v);
 180             }
 181         }
 182     }
 183 
 184     /**
 185      * Method to filter the form data.
 186      *
 187      * @param   array   $data   An array of field values to filter.
 188      * @param   string  $group  The dot-separated form group path on which to filter the fields.
 189      *
 190      * @return  mixed  Array or false.
 191      *
 192      * @since   11.1
 193      */
 194     public function filter($data, $group = null)
 195     {
 196         // Make sure there is a valid JForm XML document.
 197         if (!($this->xml instanceof SimpleXMLElement))
 198         {
 199             return false;
 200         }
 201 
 202         $input = new Registry($data);
 203         $output = new Registry;
 204 
 205         // Get the fields for which to filter the data.
 206         $fields = $this->findFieldsByGroup($group);
 207 
 208         if (!$fields)
 209         {
 210             // PANIC!
 211             return false;
 212         }
 213 
 214         // Filter the fields.
 215         foreach ($fields as $field)
 216         {
 217             $name = (string) $field['name'];
 218 
 219             // Get the field groups for the element.
 220             $attrs = $field->xpath('ancestor::fields[@name]/@name');
 221             $groups = array_map('strval', $attrs ? $attrs : array());
 222             $group = implode('.', $groups);
 223 
 224             $key = $group ? $group . '.' . $name : $name;
 225 
 226             // Filter the value if it exists.
 227             if ($input->exists($key))
 228             {
 229                 $output->set($key, $this->filterField($field, $input->get($key, (string) $field['default'])));
 230             }
 231         }
 232 
 233         return $output->toArray();
 234     }
 235 
 236     /**
 237      * Return all errors, if any.
 238      *
 239      * @return  array  Array of error messages or RuntimeException objects.
 240      *
 241      * @since   11.1
 242      */
 243     public function getErrors()
 244     {
 245         return $this->errors;
 246     }
 247 
 248     /**
 249      * Method to get a form field represented as a JFormField object.
 250      *
 251      * @param   string  $name   The name of the form field.
 252      * @param   string  $group  The optional dot-separated form group path on which to find the field.
 253      * @param   mixed   $value  The optional value to use as the default for the field.
 254      *
 255      * @return  JFormField|boolean  The JFormField object for the field or boolean false on error.
 256      *
 257      * @since   11.1
 258      */
 259     public function getField($name, $group = null, $value = null)
 260     {
 261         // Make sure there is a valid JForm XML document.
 262         if (!($this->xml instanceof SimpleXMLElement))
 263         {
 264             return false;
 265         }
 266 
 267         // Attempt to find the field by name and group.
 268         $element = $this->findField($name, $group);
 269 
 270         // If the field element was not found return false.
 271         if (!$element)
 272         {
 273             return false;
 274         }
 275 
 276         return $this->loadField($element, $group, $value);
 277     }
 278 
 279     /**
 280      * Method to get an attribute value from a field XML element.  If the attribute doesn't exist or
 281      * is null then the optional default value will be used.
 282      *
 283      * @param   string  $name       The name of the form field for which to get the attribute value.
 284      * @param   string  $attribute  The name of the attribute for which to get a value.
 285      * @param   mixed   $default    The optional default value to use if no attribute value exists.
 286      * @param   string  $group      The optional dot-separated form group path on which to find the field.
 287      *
 288      * @return  mixed  The attribute value for the field.
 289      *
 290      * @since   11.1
 291      * @throws  UnexpectedValueException
 292      */
 293     public function getFieldAttribute($name, $attribute, $default = null, $group = null)
 294     {
 295         // Make sure there is a valid JForm XML document.
 296         if (!($this->xml instanceof SimpleXMLElement))
 297         {
 298             throw new UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this)));
 299         }
 300 
 301         // Find the form field element from the definition.
 302         $element = $this->findField($name, $group);
 303 
 304         // If the element exists and the attribute exists for the field return the attribute value.
 305         if (($element instanceof SimpleXMLElement) && strlen((string) $element[$attribute]))
 306         {
 307             return (string) $element[$attribute];
 308         }
 309 
 310         // Otherwise return the given default value.
 311         else
 312         {
 313             return $default;
 314         }
 315     }
 316 
 317     /**
 318      * Method to get an array of JFormField objects in a given fieldset by name.  If no name is
 319      * given then all fields are returned.
 320      *
 321      * @param   string  $set  The optional name of the fieldset.
 322      *
 323      * @return  array  The array of JFormField objects in the fieldset.
 324      *
 325      * @since   11.1
 326      */
 327     public function getFieldset($set = null)
 328     {
 329         $fields = array();
 330 
 331         // Get all of the field elements in the fieldset.
 332         if ($set)
 333         {
 334             $elements = $this->findFieldsByFieldset($set);
 335         }
 336 
 337         // Get all fields.
 338         else
 339         {
 340             $elements = $this->findFieldsByGroup();
 341         }
 342 
 343         // If no field elements were found return empty.
 344         if (empty($elements))
 345         {
 346             return $fields;
 347         }
 348 
 349         // Build the result array from the found field elements.
 350         foreach ($elements as $element)
 351         {
 352             // Get the field groups for the element.
 353             $attrs = $element->xpath('ancestor::fields[@name]/@name');
 354             $groups = array_map('strval', $attrs ? $attrs : array());
 355             $group = implode('.', $groups);
 356 
 357             // If the field is successfully loaded add it to the result array.
 358             if ($field = $this->loadField($element, $group))
 359             {
 360                 $fields[$field->id] = $field;
 361             }
 362         }
 363 
 364         return $fields;
 365     }
 366 
 367     /**
 368      * Method to get an array of fieldset objects optionally filtered over a given field group.
 369      *
 370      * @param   string  $group  The dot-separated form group path on which to filter the fieldsets.
 371      *
 372      * @return  array  The array of fieldset objects.
 373      *
 374      * @since   11.1
 375      */
 376     public function getFieldsets($group = null)
 377     {
 378         $fieldsets = array();
 379         $sets = array();
 380 
 381         // Make sure there is a valid JForm XML document.
 382         if (!($this->xml instanceof SimpleXMLElement))
 383         {
 384             return $fieldsets;
 385         }
 386 
 387         if ($group)
 388         {
 389             // Get the fields elements for a given group.
 390             $elements = &$this->findGroup($group);
 391 
 392             foreach ($elements as &$element)
 393             {
 394                 // Get an array of <fieldset /> elements and fieldset attributes within the fields element.
 395                 if ($tmp = $element->xpath('descendant::fieldset[@name] | descendant::field[@fieldset]/@fieldset'))
 396                 {
 397                     $sets = array_merge($sets, (array) $tmp);
 398                 }
 399             }
 400         }
 401         else
 402         {
 403             // Get an array of <fieldset /> elements and fieldset attributes.
 404             $sets = $this->xml->xpath('//fieldset[@name and not(ancestor::field/form/*)] | //field[@fieldset and not(ancestor::field/form/*)]/@fieldset');
 405         }
 406 
 407         // If no fieldsets are found return empty.
 408         if (empty($sets))
 409         {
 410             return $fieldsets;
 411         }
 412 
 413         // Process each found fieldset.
 414         foreach ($sets as $set)
 415         {
 416             if ((string) $set['hidden'] == 'true')
 417             {
 418                 continue;
 419             }
 420 
 421             // Are we dealing with a fieldset element?
 422             if ((string) $set['name'])
 423             {
 424                 // Only create it if it doesn't already exist.
 425                 if (empty($fieldsets[(string) $set['name']]))
 426                 {
 427                     // Build the fieldset object.
 428                     $fieldset = (object) array('name' => '', 'label' => '', 'description' => '');
 429 
 430                     foreach ($set->attributes() as $name => $value)
 431                     {
 432                         $fieldset->$name = (string) $value;
 433                     }
 434 
 435                     // Add the fieldset object to the list.
 436                     $fieldsets[$fieldset->name] = $fieldset;
 437                 }
 438             }
 439 
 440             // Must be dealing with a fieldset attribute.
 441             else
 442             {
 443                 // Only create it if it doesn't already exist.
 444                 if (empty($fieldsets[(string) $set]))
 445                 {
 446                     // Attempt to get the fieldset element for data (throughout the entire form document).
 447                     $tmp = $this->xml->xpath('//fieldset[@name="' . (string) $set . '"]');
 448 
 449                     // If no element was found, build a very simple fieldset object.
 450                     if (empty($tmp))
 451                     {
 452                         $fieldset = (object) array('name' => (string) $set, 'label' => '', 'description' => '');
 453                     }
 454 
 455                     // Build the fieldset object from the element.
 456                     else
 457                     {
 458                         $fieldset = (object) array('name' => '', 'label' => '', 'description' => '');
 459 
 460                         foreach ($tmp[0]->attributes() as $name => $value)
 461                         {
 462                             $fieldset->$name = (string) $value;
 463                         }
 464                     }
 465 
 466                     // Add the fieldset object to the list.
 467                     $fieldsets[$fieldset->name] = $fieldset;
 468                 }
 469             }
 470         }
 471 
 472         return $fieldsets;
 473     }
 474 
 475     /**
 476      * Method to get the form control. This string serves as a container for all form fields. For
 477      * example, if there is a field named 'foo' and a field named 'bar' and the form control is
 478      * empty the fields will be rendered like: `<input name="foo" />` and `<input name="bar" />`.  If
 479      * the form control is set to 'joomla' however, the fields would be rendered like:
 480      * `<input name="joomla[foo]" />` and `<input name="joomla[bar]" />`.
 481      *
 482      * @return  string  The form control string.
 483      *
 484      * @since   11.1
 485      */
 486     public function getFormControl()
 487     {
 488         return (string) $this->options['control'];
 489     }
 490 
 491     /**
 492      * Method to get an array of JFormField objects in a given field group by name.
 493      *
 494      * @param   string   $group   The dot-separated form group path for which to get the form fields.
 495      * @param   boolean  $nested  True to also include fields in nested groups that are inside of the
 496      *                            group for which to find fields.
 497      *
 498      * @return  array    The array of JFormField objects in the field group.
 499      *
 500      * @since   11.1
 501      */
 502     public function getGroup($group, $nested = false)
 503     {
 504         $fields = array();
 505 
 506         // Get all of the field elements in the field group.
 507         $elements = $this->findFieldsByGroup($group, $nested);
 508 
 509         // If no field elements were found return empty.
 510         if (empty($elements))
 511         {
 512             return $fields;
 513         }
 514 
 515         // Build the result array from the found field elements.
 516         foreach ($elements as $element)
 517         {
 518             // Get the field groups for the element.
 519             $attrs  = $element->xpath('ancestor::fields[@name]/@name');
 520             $groups = array_map('strval', $attrs ? $attrs : array());
 521             $group  = implode('.', $groups);
 522 
 523             // If the field is successfully loaded add it to the result array.
 524             if ($field = $this->loadField($element, $group))
 525             {
 526                 $fields[$field->id] = $field;
 527             }
 528         }
 529 
 530         return $fields;
 531     }
 532 
 533     /**
 534      * Method to get a form field markup for the field input.
 535      *
 536      * @param   string  $name   The name of the form field.
 537      * @param   string  $group  The optional dot-separated form group path on which to find the field.
 538      * @param   mixed   $value  The optional value to use as the default for the field.
 539      *
 540      * @return  string  The form field markup.
 541      *
 542      * @since   11.1
 543      */
 544     public function getInput($name, $group = null, $value = null)
 545     {
 546         // Attempt to get the form field.
 547         if ($field = $this->getField($name, $group, $value))
 548         {
 549             return $field->input;
 550         }
 551 
 552         return '';
 553     }
 554 
 555     /**
 556      * Method to get the label for a field input.
 557      *
 558      * @param   string  $name   The name of the form field.
 559      * @param   string  $group  The optional dot-separated form group path on which to find the field.
 560      *
 561      * @return  string  The form field label.
 562      *
 563      * @since   11.1
 564      */
 565     public function getLabel($name, $group = null)
 566     {
 567         // Attempt to get the form field.
 568         if ($field = $this->getField($name, $group))
 569         {
 570             return $field->label;
 571         }
 572 
 573         return '';
 574     }
 575 
 576     /**
 577      * Method to get the form name.
 578      *
 579      * @return  string  The name of the form.
 580      *
 581      * @since   11.1
 582      */
 583     public function getName()
 584     {
 585         return $this->name;
 586     }
 587 
 588     /**
 589      * Method to get the value of a field.
 590      *
 591      * @param   string  $name     The name of the field for which to get the value.
 592      * @param   string  $group    The optional dot-separated form group path on which to get the value.
 593      * @param   mixed   $default  The optional default value of the field value is empty.
 594      *
 595      * @return  mixed  The value of the field or the default value if empty.
 596      *
 597      * @since   11.1
 598      */
 599     public function getValue($name, $group = null, $default = null)
 600     {
 601         // If a group is set use it.
 602         if ($group)
 603         {
 604             $return = $this->data->get($group . '.' . $name, $default);
 605         }
 606         else
 607         {
 608             $return = $this->data->get($name, $default);
 609         }
 610 
 611         return $return;
 612     }
 613 
 614     /**
 615      * Method to get a control group with label and input.
 616      *
 617      * @param   string  $name     The name of the field for which to get the value.
 618      * @param   string  $group    The optional dot-separated form group path on which to get the value.
 619      * @param   mixed   $default  The optional default value of the field value is empty.
 620      *
 621      * @return  string  A string containing the html for the control goup
 622      *
 623      * @since      3.2
 624      * @deprecated 3.2.3  Use renderField() instead of getControlGroup
 625      */
 626     public function getControlGroup($name, $group = null, $default = null)
 627     {
 628         JLog::add('JForm->getControlGroup() is deprecated use JForm->renderField().', JLog::WARNING, 'deprecated');
 629 
 630         return $this->renderField($name, $group, $default);
 631     }
 632 
 633     /**
 634      * Method to get all control groups with label and input of a fieldset.
 635      *
 636      * @param   string  $name  The name of the fieldset for which to get the values.
 637      *
 638      * @return  string  A string containing the html for the control goups
 639      *
 640      * @since      3.2
 641      * @deprecated 3.2.3 Use renderFieldset() instead of getControlGroups
 642      */
 643     public function getControlGroups($name)
 644     {
 645         JLog::add('JForm->getControlGroups() is deprecated use JForm->renderFieldset().', JLog::WARNING, 'deprecated');
 646 
 647         return $this->renderFieldset($name);
 648     }
 649 
 650     /**
 651      * Method to get a control group with label and input.
 652      *
 653      * @param   string  $name     The name of the field for which to get the value.
 654      * @param   string  $group    The optional dot-separated form group path on which to get the value.
 655      * @param   mixed   $default  The optional default value of the field value is empty.
 656      * @param   array   $options  Any options to be passed into the rendering of the field
 657      *
 658      * @return  string  A string containing the html for the control goup
 659      *
 660      * @since   3.2.3
 661      */
 662     public function renderField($name, $group = null, $default = null, $options = array())
 663     {
 664         $field = $this->getField($name, $group, $default);
 665 
 666         if ($field)
 667         {
 668             return $field->renderField($options);
 669         }
 670 
 671         return '';
 672     }
 673 
 674     /**
 675      * Method to get all control groups with label and input of a fieldset.
 676      *
 677      * @param   string  $name     The name of the fieldset for which to get the values.
 678      * @param   array   $options  Any options to be passed into the rendering of the field
 679      *
 680      * @return  string  A string containing the html for the control goups
 681      *
 682      * @since   3.2.3
 683      */
 684     public function renderFieldset($name, $options = array())
 685     {
 686         $fields = $this->getFieldset($name);
 687         $html = array();
 688 
 689         foreach ($fields as $field)
 690         {
 691             $html[] = $field->renderField($options);
 692         }
 693 
 694         return implode('', $html);
 695     }
 696 
 697     /**
 698      * Method to load the form description from an XML string or object.
 699      *
 700      * The replace option works per field.  If a field being loaded already exists in the current
 701      * form definition then the behavior or load will vary depending upon the replace flag.  If it
 702      * is set to true, then the existing field will be replaced in its exact location by the new
 703      * field being loaded.  If it is false, then the new field being loaded will be ignored and the
 704      * method will move on to the next field to load.
 705      *
 706      * @param   string  $data     The name of an XML string or object.
 707      * @param   string  $replace  Flag to toggle whether form fields should be replaced if a field
 708      *                            already exists with the same group/name.
 709      * @param   string  $xpath    An optional xpath to search for the fields.
 710      *
 711      * @return  boolean  True on success, false otherwise.
 712      *
 713      * @since   11.1
 714      */
 715     public function load($data, $replace = true, $xpath = false)
 716     {
 717         // If the data to load isn't already an XML element or string return false.
 718         if ((!($data instanceof SimpleXMLElement)) && (!is_string($data)))
 719         {
 720             return false;
 721         }
 722 
 723         // Attempt to load the XML if a string.
 724         if (is_string($data))
 725         {
 726             try
 727             {
 728                 $data = new SimpleXMLElement($data);
 729             }
 730             catch (Exception $e)
 731             {
 732                 return false;
 733             }
 734 
 735             // Make sure the XML loaded correctly.
 736             if (!$data)
 737             {
 738                 return false;
 739             }
 740         }
 741 
 742         // If we have no XML definition at this point let's make sure we get one.
 743         if (empty($this->xml))
 744         {
 745             // If no XPath query is set to search for fields, and we have a <form />, set it and return.
 746             if (!$xpath && ($data->getName() == 'form'))
 747             {
 748                 $this->xml = $data;
 749 
 750                 // Synchronize any paths found in the load.
 751                 $this->syncPaths();
 752 
 753                 return true;
 754             }
 755 
 756             // Create a root element for the form.
 757             else
 758             {
 759                 $this->xml = new SimpleXMLElement('<form></form>');
 760             }
 761         }
 762 
 763         // Get the XML elements to load.
 764         $elements = array();
 765 
 766         if ($xpath)
 767         {
 768             $elements = $data->xpath($xpath);
 769         }
 770         elseif ($data->getName() == 'form')
 771         {
 772             $elements = $data->children();
 773         }
 774 
 775         // If there is nothing to load return true.
 776         if (empty($elements))
 777         {
 778             return true;
 779         }
 780 
 781         // Load the found form elements.
 782         foreach ($elements as $element)
 783         {
 784             // Get an array of fields with the correct name.
 785             $fields = $element->xpath('descendant-or-self::field');
 786 
 787             foreach ($fields as $field)
 788             {
 789                 // Get the group names as strings for ancestor fields elements.
 790                 $attrs = $field->xpath('ancestor::fields[@name]/@name');
 791                 $groups = array_map('strval', $attrs ? $attrs : array());
 792 
 793                 // Check to see if the field exists in the current form.
 794                 if ($current = $this->findField((string) $field['name'], implode('.', $groups)))
 795                 {
 796                     // If set to replace found fields, replace the data and remove the field so we don't add it twice.
 797                     if ($replace)
 798                     {
 799                         $olddom = dom_import_simplexml($current);
 800                         $loadeddom = dom_import_simplexml($field);
 801                         $addeddom = $olddom->ownerDocument->importNode($loadeddom, true);
 802                         $olddom->parentNode->replaceChild($addeddom, $olddom);
 803                         $loadeddom->parentNode->removeChild($loadeddom);
 804                     }
 805                     else
 806                     {
 807                         unset($field);
 808                     }
 809                 }
 810             }
 811 
 812             // Merge the new field data into the existing XML document.
 813             self::addNode($this->xml, $element);
 814         }
 815 
 816         // Synchronize any paths found in the load.
 817         $this->syncPaths();
 818 
 819         return true;
 820     }
 821 
 822     /**
 823      * Method to load the form description from an XML file.
 824      *
 825      * The reset option works on a group basis. If the XML file references
 826      * groups that have already been created they will be replaced with the
 827      * fields in the new XML file unless the $reset parameter has been set
 828      * to false.
 829      *
 830      * @param   string  $file   The filesystem path of an XML file.
 831      * @param   string  $reset  Flag to toggle whether form fields should be replaced if a field
 832      *                          already exists with the same group/name.
 833      * @param   string  $xpath  An optional xpath to search for the fields.
 834      *
 835      * @return  boolean  True on success, false otherwise.
 836      *
 837      * @since   11.1
 838      */
 839     public function loadFile($file, $reset = true, $xpath = false)
 840     {
 841         // Check to see if the path is an absolute path.
 842         if (!is_file($file))
 843         {
 844             // Not an absolute path so let's attempt to find one using JPath.
 845             $file = JPath::find(self::addFormPath(), strtolower($file) . '.xml');
 846 
 847             // If unable to find the file return false.
 848             if (!$file)
 849             {
 850                 return false;
 851             }
 852         }
 853 
 854         // Attempt to load the XML file.
 855         $xml = simplexml_load_file($file);
 856 
 857         return $this->load($xml, $reset, $xpath);
 858     }
 859 
 860     /**
 861      * Method to remove a field from the form definition.
 862      *
 863      * @param   string  $name   The name of the form field for which remove.
 864      * @param   string  $group  The optional dot-separated form group path on which to find the field.
 865      *
 866      * @return  boolean  True on success, false otherwise.
 867      *
 868      * @since   11.1
 869      * @throws  UnexpectedValueException
 870      */
 871     public function removeField($name, $group = null)
 872     {
 873         // Make sure there is a valid JForm XML document.
 874         if (!($this->xml instanceof SimpleXMLElement))
 875         {
 876             throw new UnexpectedValueException(sprintf('%s::removeField `xml` is not an instance of SimpleXMLElement', get_class($this)));
 877         }
 878 
 879         // Find the form field element from the definition.
 880         $element = $this->findField($name, $group);
 881 
 882         // If the element exists remove it from the form definition.
 883         if ($element instanceof SimpleXMLElement)
 884         {
 885             $dom = dom_import_simplexml($element);
 886             $dom->parentNode->removeChild($dom);
 887 
 888             return true;
 889         }
 890 
 891         return false;
 892     }
 893 
 894     /**
 895      * Method to remove a group from the form definition.
 896      *
 897      * @param   string  $group  The dot-separated form group path for the group to remove.
 898      *
 899      * @return  boolean  True on success.
 900      *
 901      * @since   11.1
 902      * @throws  UnexpectedValueException
 903      */
 904     public function removeGroup($group)
 905     {
 906         // Make sure there is a valid JForm XML document.
 907         if (!($this->xml instanceof SimpleXMLElement))
 908         {
 909             throw new UnexpectedValueException(sprintf('%s::removeGroup `xml` is not an instance of SimpleXMLElement', get_class($this)));
 910         }
 911 
 912         // Get the fields elements for a given group.
 913         $elements = &$this->findGroup($group);
 914 
 915         foreach ($elements as &$element)
 916         {
 917             $dom = dom_import_simplexml($element);
 918             $dom->parentNode->removeChild($dom);
 919         }
 920 
 921         return true;
 922     }
 923 
 924     /**
 925      * Method to reset the form data store and optionally the form XML definition.
 926      *
 927      * @param   boolean  $xml  True to also reset the XML form definition.
 928      *
 929      * @return  boolean  True on success.
 930      *
 931      * @since   11.1
 932      */
 933     public function reset($xml = false)
 934     {
 935         unset($this->data);
 936         $this->data = new Registry;
 937 
 938         if ($xml)
 939         {
 940             unset($this->xml);
 941             $this->xml = new SimpleXMLElement('<form></form>');
 942         }
 943 
 944         return true;
 945     }
 946 
 947     /**
 948      * Method to set a field XML element to the form definition.  If the replace flag is set then
 949      * the field will be set whether it already exists or not.  If it isn't set, then the field
 950      * will not be replaced if it already exists.
 951      *
 952      * @param   SimpleXMLElement  $element   The XML element object representation of the form field.
 953      * @param   string            $group     The optional dot-separated form group path on which to set the field.
 954      * @param   boolean           $replace   True to replace an existing field if one already exists.
 955      * @param   string            $fieldset  The name of the fieldset we are adding the field to.
 956      *
 957      * @return  boolean  True on success.
 958      *
 959      * @since   11.1
 960      * @throws  UnexpectedValueException
 961      */
 962     public function setField(SimpleXMLElement $element, $group = null, $replace = true, $fieldset = 'default')
 963     {
 964         // Make sure there is a valid JForm XML document.
 965         if (!($this->xml instanceof SimpleXMLElement))
 966         {
 967             throw new UnexpectedValueException(sprintf('%s::setField `xml` is not an instance of SimpleXMLElement', get_class($this)));
 968         }
 969 
 970         // Find the form field element from the definition.
 971         $old = $this->findField((string) $element['name'], $group);
 972 
 973         // If an existing field is found and replace flag is false do nothing and return true.
 974         if (!$replace && !empty($old))
 975         {
 976             return true;
 977         }
 978 
 979         // If an existing field is found and replace flag is true remove the old field.
 980         if ($replace && !empty($old) && ($old instanceof SimpleXMLElement))
 981         {
 982             $dom = dom_import_simplexml($old);
 983 
 984             // Get the parent element, this should be the fieldset
 985             $parent   = $dom->parentNode;
 986             $fieldset = $parent->getAttribute('name');
 987 
 988             $parent->removeChild($dom);
 989         }
 990 
 991         // Create the search path
 992         $path = '//';
 993 
 994         if (!empty($group))
 995         {
 996             $path .= 'fields[@name="' . $group . '"]/';
 997         }
 998 
 999         $path .= 'fieldset[@name="' . $fieldset . '"]';
1000 
1001         $fs = $this->xml->xpath($path);
1002 
1003         if (isset($fs[0]) && ($fs[0] instanceof SimpleXMLElement))
1004         {
1005             // Add field to the form.
1006             self::addNode($fs[0], $element);
1007 
1008             // Synchronize any paths found in the load.
1009             $this->syncPaths();
1010 
1011             return true;
1012         }
1013 
1014         // We couldn't find a fieldset to add the field. Now we are checking, if we have set only a group
1015         if (!empty($group))
1016         {
1017             $fields = &$this->findGroup($group);
1018 
1019             // If an appropriate fields element was found for the group, add the element.
1020             if (isset($fields[0]) && ($fields[0] instanceof SimpleXMLElement))
1021             {
1022                 self::addNode($fields[0], $element);
1023             }
1024 
1025             // Synchronize any paths found in the load.
1026             $this->syncPaths();
1027 
1028             return true;
1029         }
1030 
1031         // We couldn't find a parent so we are adding it at root level
1032 
1033         // Add field to the form.
1034         self::addNode($this->xml, $element);
1035 
1036         // Synchronize any paths found in the load.
1037         $this->syncPaths();
1038 
1039         return true;
1040     }
1041 
1042     /**
1043      * Method to set an attribute value for a field XML element.
1044      *
1045      * @param   string  $name       The name of the form field for which to set the attribute value.
1046      * @param   string  $attribute  The name of the attribute for which to set a value.
1047      * @param   mixed   $value      The value to set for the attribute.
1048      * @param   string  $group      The optional dot-separated form group path on which to find the field.
1049      *
1050      * @return  boolean  True on success.
1051      *
1052      * @since   11.1
1053      * @throws  UnexpectedValueException
1054      */
1055     public function setFieldAttribute($name, $attribute, $value, $group = null)
1056     {
1057         // Make sure there is a valid JForm XML document.
1058         if (!($this->xml instanceof SimpleXMLElement))
1059         {
1060             throw new UnexpectedValueException(sprintf('%s::setFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this)));
1061         }
1062 
1063         // Find the form field element from the definition.
1064         $element = $this->findField($name, $group);
1065 
1066         // If the element doesn't exist return false.
1067         if (!($element instanceof SimpleXMLElement))
1068         {
1069             return false;
1070         }
1071 
1072         // Otherwise set the attribute and return true.
1073         else
1074         {
1075             $element[$attribute] = $value;
1076 
1077             // Synchronize any paths found in the load.
1078             $this->syncPaths();
1079 
1080             return true;
1081         }
1082     }
1083 
1084     /**
1085      * Method to set some field XML elements to the form definition.  If the replace flag is set then
1086      * the fields will be set whether they already exists or not.  If it isn't set, then the fields
1087      * will not be replaced if they already exist.
1088      *
1089      * @param   array    &$elements  The array of XML element object representations of the form fields.
1090      * @param   string   $group      The optional dot-separated form group path on which to set the fields.
1091      * @param   boolean  $replace    True to replace existing fields if they already exist.
1092      * @param   string   $fieldset   The name of the fieldset we are adding the field to.
1093      *
1094      * @return  boolean  True on success.
1095      *
1096      * @since   11.1
1097      * @throws  UnexpectedValueException
1098      */
1099     public function setFields(&$elements, $group = null, $replace = true, $fieldset = 'default')
1100     {
1101         // Make sure there is a valid JForm XML document.
1102         if (!($this->xml instanceof SimpleXMLElement))
1103         {
1104             throw new UnexpectedValueException(sprintf('%s::setFields `xml` is not an instance of SimpleXMLElement', get_class($this)));
1105         }
1106 
1107         // Make sure the elements to set are valid.
1108         foreach ($elements as $element)
1109         {
1110             if (!($element instanceof SimpleXMLElement))
1111             {
1112                 throw new UnexpectedValueException(sprintf('$element not SimpleXMLElement in %s::setFields', get_class($this)));
1113             }
1114         }
1115 
1116         // Set the fields.
1117         $return = true;
1118 
1119         foreach ($elements as $element)
1120         {
1121             if (!$this->setField($element, $group, $replace, $fieldset))
1122             {
1123                 $return = false;
1124             }
1125         }
1126 
1127         // Synchronize any paths found in the load.
1128         $this->syncPaths();
1129 
1130         return $return;
1131     }
1132 
1133     /**
1134      * Method to set the value of a field. If the field does not exist in the form then the method
1135      * will return false.
1136      *
1137      * @param   string  $name   The name of the field for which to set the value.
1138      * @param   string  $group  The optional dot-separated form group path on which to find the field.
1139      * @param   mixed   $value  The value to set for the field.
1140      *
1141      * @return  boolean  True on success.
1142      *
1143      * @since   11.1
1144      */
1145     public function setValue($name, $group = null, $value = null)
1146     {
1147         // If the field does not exist return false.
1148         if (!$this->findField($name, $group))
1149         {
1150             return false;
1151         }
1152 
1153         // If a group is set use it.
1154         if ($group)
1155         {
1156             $this->data->set($group . '.' . $name, $value);
1157         }
1158         else
1159         {
1160             $this->data->set($name, $value);
1161         }
1162 
1163         return true;
1164     }
1165 
1166     /**
1167      * Method to validate form data.
1168      *
1169      * Validation warnings will be pushed into JForm::errors and should be
1170      * retrieved with JForm::getErrors() when validate returns boolean false.
1171      *
1172      * @param   array   $data   An array of field values to validate.
1173      * @param   string  $group  The optional dot-separated form group path on which to filter the
1174      *                          fields to be validated.
1175      *
1176      * @return  boolean  True on success.
1177      *
1178      * @since   11.1
1179      */
1180     public function validate($data, $group = null)
1181     {
1182         // Make sure there is a valid JForm XML document.
1183         if (!($this->xml instanceof SimpleXMLElement))
1184         {
1185             return false;
1186         }
1187 
1188         $return = true;
1189 
1190         // Create an input registry object from the data to validate.
1191         $input = new Registry($data);
1192 
1193         // Get the fields for which to validate the data.
1194         $fields = $this->findFieldsByGroup($group);
1195 
1196         if (!$fields)
1197         {
1198             // PANIC!
1199             return false;
1200         }
1201 
1202         // Validate the fields.
1203         foreach ($fields as $field)
1204         {
1205             $value = null;
1206             $name = (string) $field['name'];
1207 
1208             // Get the group names as strings for ancestor fields elements.
1209             $attrs = $field->xpath('ancestor::fields[@name]/@name');
1210             $groups = array_map('strval', $attrs ? $attrs : array());
1211             $group = implode('.', $groups);
1212 
1213             // Get the value from the input data.
1214             if ($group)
1215             {
1216                 $value = $input->get($group . '.' . $name);
1217             }
1218             else
1219             {
1220                 $value = $input->get($name);
1221             }
1222 
1223             // Validate the field.
1224             $valid = $this->validateField($field, $group, $value, $input);
1225 
1226             // Check for an error.
1227             if ($valid instanceof Exception)
1228             {
1229                 $this->errors[] = $valid;
1230                 $return         = false;
1231             }
1232         }
1233 
1234         return $return;
1235     }
1236 
1237     /**
1238      * Method to apply an input filter to a value based on field data.
1239      *
1240      * @param   string  $element  The XML element object representation of the form field.
1241      * @param   mixed   $value    The value to filter for the field.
1242      *
1243      * @return  mixed   The filtered value.
1244      *
1245      * @since   11.1
1246      */
1247     protected function filterField($element, $value)
1248     {
1249         // Make sure there is a valid SimpleXMLElement.
1250         if (!($element instanceof SimpleXMLElement))
1251         {
1252             return false;
1253         }
1254 
1255         // Get the field filter type.
1256         $filter = (string) $element['filter'];
1257 
1258         // Process the input value based on the filter.
1259         $return = null;
1260 
1261         switch (strtoupper($filter))
1262         {
1263             // Access Control Rules.
1264             case 'RULES':
1265                 $return = array();
1266 
1267                 foreach ((array) $value as $action => $ids)
1268                 {
1269                     // Build the rules array.
1270                     $return[$action] = array();
1271 
1272                     foreach ($ids as $id => $p)
1273                     {
1274                         if ($p !== '')
1275                         {
1276                             $return[$action][$id] = ($p == '1' || $p == 'true') ? true : false;
1277                         }
1278                     }
1279                 }
1280                 break;
1281 
1282             // Do nothing, thus leaving the return value as null.
1283             case 'UNSET':
1284                 break;
1285 
1286             // No Filter.
1287             case 'RAW':
1288                 $return = $value;
1289                 break;
1290 
1291             // Filter the input as an array of integers.
1292             case 'INT_ARRAY':
1293                 // Make sure the input is an array.
1294                 if (is_object($value))
1295                 {
1296                     $value = get_object_vars($value);
1297                 }
1298 
1299                 $value = is_array($value) ? $value : array($value);
1300 
1301                 $value = ArrayHelper::toInteger($value);
1302                 $return = $value;
1303                 break;
1304 
1305             // Filter safe HTML.
1306             case 'SAFEHTML':
1307                 $return = JFilterInput::getInstance(null, null, 1, 1)->clean($value, 'html');
1308                 break;
1309 
1310             // Convert a date to UTC based on the server timezone offset.
1311             case 'SERVER_UTC':
1312                 if ((int) $value > 0)
1313                 {
1314                     // Check if we have a localised date format
1315                     $translateFormat = (string) $element['translateformat'];
1316 
1317                     if ($translateFormat && $translateFormat != 'false')
1318                     {
1319                         $showTime = (string) $element['showtime'];
1320                         $showTime = ($showTime && $showTime != 'false');
1321                         $format   = ($showTime) ? JText::_('DATE_FORMAT_FILTER_DATETIME') : JText::_('DATE_FORMAT_FILTER_DATE');
1322                         $date     = date_parse_from_format($format, $value);
1323                         $value    = (int) $date['year'] . '-' . (int) $date['month'] . '-' . (int) $date['day'];
1324 
1325                         if ($showTime)
1326                         {
1327                             $value .= ' ' . (int) $date['hour'] . ':' . (int) $date['minute'] . ':' . (int) $date['second'];
1328                         }
1329                     }
1330 
1331                     // Get the server timezone setting.
1332                     $offset = JFactory::getConfig()->get('offset');
1333 
1334                     // Return an SQL formatted datetime string in UTC.
1335                     try
1336                     {
1337                         $return = JFactory::getDate($value, $offset)->toSql();
1338                     }
1339                     catch (Exception $e)
1340                     {
1341                         JFactory::getApplication()->enqueueMessage(JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', JText::_((string) $element['label'])), 'warning');
1342 
1343                         $return = '';
1344                     }
1345                 }
1346                 else
1347                 {
1348                     $return = '';
1349                 }
1350                 break;
1351 
1352             // Convert a date to UTC based on the user timezone offset.
1353             case 'USER_UTC':
1354                 if ((int) $value > 0)
1355                 {
1356                     // Check if we have a localised date format
1357                     $translateFormat = (string) $element['translateformat'];
1358 
1359                     if ($translateFormat && $translateFormat != 'false')
1360                     {
1361                         $showTime = (string) $element['showtime'];
1362                         $showTime = ($showTime && $showTime != 'false');
1363                         $format   = ($showTime) ? JText::_('DATE_FORMAT_FILTER_DATETIME') : JText::_('DATE_FORMAT_FILTER_DATE');
1364                         $date     = date_parse_from_format($format, $value);
1365                         $value    = (int) $date['year'] . '-' . (int) $date['month'] . '-' . (int) $date['day'];
1366 
1367                         if ($showTime)
1368                         {
1369                             $value .= ' ' . (int) $date['hour'] . ':' . (int) $date['minute'] . ':' . (int) $date['second'];
1370                         }
1371                     }
1372 
1373                     // Get the user timezone setting defaulting to the server timezone setting.
1374                     $offset = JFactory::getUser()->getTimezone();
1375 
1376                     // Return a MySQL formatted datetime string in UTC.
1377                     try
1378                     {
1379                         $return = JFactory::getDate($value, $offset)->toSql();
1380                     }
1381                     catch (Exception $e)
1382                     {
1383                         JFactory::getApplication()->enqueueMessage(JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', JText::_((string) $element['label'])), 'warning');
1384 
1385                         $return = '';
1386                     }
1387                 }
1388                 else
1389                 {
1390                     $return = '';
1391                 }
1392                 break;
1393 
1394             /*
1395              * Ensures a protocol is present in the saved field unless the relative flag is set.
1396              * Only use when the only permitted protocols require '://'.
1397              * See JFormRuleUrl for list of these.
1398              */
1399 
1400             case 'URL':
1401                 if (empty($value))
1402                 {
1403                     return false;
1404                 }
1405 
1406                 // This cleans some of the more dangerous characters but leaves special characters that are valid.
1407                 $value = JFilterInput::getInstance()->clean($value, 'html');
1408                 $value = trim($value);
1409 
1410                 // <>" are never valid in a uri see http://www.ietf.org/rfc/rfc1738.txt.
1411                 $value = str_replace(array('<', '>', '"'), '', $value);
1412 
1413                 // Check for a protocol
1414                 $protocol = parse_url($value, PHP_URL_SCHEME);
1415 
1416                 // If there is no protocol and the relative option is not specified,
1417                 // we assume that it is an external URL and prepend http://.
1418                 if (($element['type'] == 'url' && !$protocol &&  !$element['relative'])
1419                     || (!$element['type'] == 'url' && !$protocol))
1420                 {
1421                     $protocol = 'http';
1422 
1423                     // If it looks like an internal link, then add the root.
1424                     if (substr($value, 0, 9) == 'index.php')
1425                     {
1426                         $value = JUri::root() . $value;
1427                     }
1428 
1429                     // Otherwise we treat it as an external link.
1430                     else
1431                     {
1432                         // Put the url back together.
1433                         $value = $protocol . '://' . $value;
1434                     }
1435                 }
1436 
1437                 // If relative URLS are allowed we assume that URLs without protocols are internal.
1438                 elseif (!$protocol && $element['relative'])
1439                 {
1440                     $host = JUri::getInstance('SERVER')->gethost();
1441 
1442                     // If it starts with the host string, just prepend the protocol.
1443                     if (substr($value, 0) == $host)
1444                     {
1445                         $value = 'http://' . $value;
1446                     }
1447 
1448                     // Otherwise if it doesn't start with "/" prepend the prefix of the current site.
1449                     elseif (substr($value, 0, 1) != '/')
1450                     {
1451                         $value = JUri::root(true) . '/' . $value;
1452                     }
1453                 }
1454 
1455                 $value = JStringPunycode::urlToPunycode($value);
1456                 $return = $value;
1457                 break;
1458 
1459             case 'TEL':
1460                 $value = trim($value);
1461 
1462                 // Does it match the NANP pattern?
1463                 if (preg_match('/^(?:\+?1[-. ]?)?\(?([2-9][0-8][0-9])\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/', $value) == 1)
1464                 {
1465                     $number = (string) preg_replace('/[^\d]/', '', $value);
1466 
1467                     if (substr($number, 0, 1) == 1)
1468                     {
1469                         $number = substr($number, 1);
1470                     }
1471 
1472                     if (substr($number, 0, 2) == '+1')
1473                     {
1474                         $number = substr($number, 2);
1475                     }
1476 
1477                     $result = '1.' . $number;
1478                 }
1479 
1480                 // If not, does it match ITU-T?
1481                 elseif (preg_match('/^\+(?:[0-9] ?){6,14}[0-9]$/', $value) == 1)
1482                 {
1483                     $countrycode = substr($value, 0, strpos($value, ' '));
1484                     $countrycode = (string) preg_replace('/[^\d]/', '', $countrycode);
1485                     $number = strstr($value, ' ');
1486                     $number = (string) preg_replace('/[^\d]/', '', $number);
1487                     $result = $countrycode . '.' . $number;
1488                 }
1489 
1490                 // If not, does it match EPP?
1491                 elseif (preg_match('/^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/', $value) == 1)
1492                 {
1493                     if (strstr($value, 'x'))
1494                     {
1495                         $xpos = strpos($value, 'x');
1496                         $value = substr($value, 0, $xpos);
1497                     }
1498 
1499                     $result = str_replace('+', '', $value);
1500                 }
1501 
1502                 // Maybe it is already ccc.nnnnnnn?
1503                 elseif (preg_match('/[0-9]{1,3}\.[0-9]{4,14}$/', $value) == 1)
1504                 {
1505                     $result = $value;
1506                 }
1507 
1508                 // If not, can we make it a string of digits?
1509                 else
1510                 {
1511                     $value = (string) preg_replace('/[^\d]/', '', $value);
1512 
1513                     if ($value != null && strlen($value) <= 15)
1514                     {
1515                         $length = strlen($value);
1516 
1517                         // If it is fewer than 13 digits assume it is a local number
1518                         if ($length <= 12)
1519                         {
1520                             $result = '.' . $value;
1521                         }
1522                         else
1523                         {
1524                             // If it has 13 or more digits let's make a country code.
1525                             $cclen = $length - 12;
1526                             $result = substr($value, 0, $cclen) . '.' . substr($value, $cclen);
1527                         }
1528                     }
1529 
1530                     // If not let's not save anything.
1531                     else
1532                     {
1533                         $result = '';
1534                     }
1535                 }
1536 
1537                 $return = $result;
1538 
1539                 break;
1540             default:
1541                 // Check for a callback filter.
1542                 if (strpos($filter, '::') !== false && is_callable(explode('::', $filter)))
1543                 {
1544                     $return = call_user_func(explode('::', $filter), $value);
1545                 }
1546 
1547                 // Filter using a callback function if specified.
1548                 elseif (function_exists($filter))
1549                 {
1550                     $return = call_user_func($filter, $value);
1551                 }
1552 
1553                 // Check for empty value and return empty string if no value is required,
1554                 // otherwise filter using JFilterInput. All HTML code is filtered by default.
1555                 else
1556                 {
1557                     $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required');
1558 
1559                     if (($value === '' || $value === null) && ! $required)
1560                     {
1561                         $return = '';
1562                     }
1563                     else
1564                     {
1565                         $return = JFilterInput::getInstance()->clean($value, $filter);
1566                     }
1567                 }
1568                 break;
1569         }
1570 
1571         return $return;
1572     }
1573 
1574     /**
1575      * Method to get a form field represented as an XML element object.
1576      *
1577      * @param   string  $name   The name of the form field.
1578      * @param   string  $group  The optional dot-separated form group path on which to find the field.
1579      *
1580      * @return  SimpleXMLElement|boolean  The XML element object for the field or boolean false on error.
1581      *
1582      * @since   11.1
1583      */
1584     protected function findField($name, $group = null)
1585     {
1586         $element = false;
1587         $fields = array();
1588 
1589         // Make sure there is a valid JForm XML document.
1590         if (!($this->xml instanceof SimpleXMLElement))
1591         {
1592             return false;
1593         }
1594 
1595         // Let's get the appropriate field element based on the method arguments.
1596         if ($group)
1597         {
1598             // Get the fields elements for a given group.
1599             $elements = &$this->findGroup($group);
1600 
1601             // Get all of the field elements with the correct name for the fields elements.
1602             foreach ($elements as $el)
1603             {
1604                 // If there are matching field elements add them to the fields array.
1605                 if ($tmp = $el->xpath('descendant::field[@name="' . $name . '" and not(ancestor::field/form/*)]'))
1606                 {
1607                     $fields = array_merge($fields, $tmp);
1608                 }
1609             }
1610 
1611             // Make sure something was found.
1612             if (!$fields)
1613             {
1614                 return false;
1615             }
1616 
1617             // Use the first correct match in the given group.
1618             $groupNames = explode('.', $group);
1619 
1620             foreach ($fields as &$field)
1621             {
1622                 // Get the group names as strings for ancestor fields elements.
1623                 $attrs = $field->xpath('ancestor::fields[@name]/@name');
1624                 $names = array_map('strval', $attrs ? $attrs : array());
1625 
1626                 // If the field is in the exact group use it and break out of the loop.
1627                 if ($names == (array) $groupNames)
1628                 {
1629                     $element = &$field;
1630                     break;
1631                 }
1632             }
1633         }
1634         else
1635         {
1636             // Get an array of fields with the correct name.
1637             $fields = $this->xml->xpath('//field[@name="' . $name . '" and not(ancestor::field/form/*)]');
1638 
1639             // Make sure something was found.
1640             if (!$fields)
1641             {
1642                 return false;
1643             }
1644 
1645             // Search through the fields for the right one.
1646             foreach ($fields as &$field)
1647             {
1648                 // If we find an ancestor fields element with a group name then it isn't what we want.
1649                 if ($field->xpath('ancestor::fields[@name]'))
1650                 {
1651                     continue;
1652                 }
1653 
1654                 // Found it!
1655                 else
1656                 {
1657                     $element = &$field;
1658                     break;
1659                 }
1660             }
1661         }
1662 
1663         return $element;
1664     }
1665 
1666     /**
1667      * Method to get an array of `<field>` elements from the form XML document which are in a specified fieldset by name.
1668      *
1669      * @param   string  $name  The name of the fieldset.
1670      *
1671      * @return  SimpleXMLElement[]|boolean  Boolean false on error or array of SimpleXMLElement objects.
1672      *
1673      * @since   11.1
1674      */
1675     protected function &findFieldsByFieldset($name)
1676     {
1677         $false = false;
1678 
1679         // Make sure there is a valid JForm XML document.
1680         if (!($this->xml instanceof SimpleXMLElement))
1681         {
1682             return $false;
1683         }
1684 
1685         /*
1686          * Get an array of <field /> elements that are underneath a <fieldset /> element
1687          * with the appropriate name attribute, and also any <field /> elements with
1688          * the appropriate fieldset attribute. To allow repeatable elements only fields
1689          * which are not descendants of other fields are selected.
1690          */
1691         $fields = $this->xml->xpath('(//fieldset[@name="' . $name . '"]//field | //field[@fieldset="' . $name . '"])[not(ancestor::field)]');
1692 
1693         return $fields;
1694     }
1695 
1696     /**
1697      * Method to get an array of `<field>` elements from the form XML document which are in a control group by name.
1698      *
1699      * @param   mixed    $group   The optional dot-separated form group path on which to find the fields.
1700      *                            Null will return all fields. False will return fields not in a group.
1701      * @param   boolean  $nested  True to also include fields in nested groups that are inside of the
1702      *                            group for which to find fields.
1703      *
1704      * @return  SimpleXMLElement[]|boolean  Boolean false on error or array of SimpleXMLElement objects.
1705      *
1706      * @since   11.1
1707      */
1708     protected function &findFieldsByGroup($group = null, $nested = false)
1709     {
1710         $false = false;
1711         $fields = array();
1712 
1713         // Make sure there is a valid JForm XML document.
1714         if (!($this->xml instanceof SimpleXMLElement))
1715         {
1716             return $false;
1717         }
1718 
1719         // Get only fields in a specific group?
1720         if ($group)
1721         {
1722             // Get the fields elements for a given group.
1723             $elements = &$this->findGroup($group);
1724 
1725             // Get all of the field elements for the fields elements.
1726             foreach ($elements as $element)
1727             {
1728                 // If there are field elements add them to the return result.
1729                 if ($tmp = $element->xpath('descendant::field'))
1730                 {
1731                     // If we also want fields in nested groups then just merge the arrays.
1732                     if ($nested)
1733                     {
1734                         $fields = array_merge($fields, $tmp);
1735                     }
1736 
1737                     // If we want to exclude nested groups then we need to check each field.
1738                     else
1739                     {
1740                         $groupNames = explode('.', $group);
1741 
1742                         foreach ($tmp as $field)
1743                         {
1744                             // Get the names of the groups that the field is in.
1745                             $attrs = $field->xpath('ancestor::fields[@name]/@name');
1746                             $names = array_map('strval', $attrs ? $attrs : array());
1747 
1748                             // If the field is in the specific group then add it to the return list.
1749                             if ($names == (array) $groupNames)
1750                             {
1751                                 $fields = array_merge($fields, array($field));
1752                             }
1753                         }
1754                     }
1755                 }
1756             }
1757         }
1758         elseif ($group === false)
1759         {
1760             // Get only field elements not in a group.
1761             $fields = $this->xml->xpath('descendant::fields[not(@name)]/field | descendant::fields[not(@name)]/fieldset/field ');
1762         }
1763         else
1764         {
1765             // Get an array of all the <field /> elements.
1766             $fields = $this->xml->xpath('//field[not(ancestor::field/form/*)]');
1767         }
1768 
1769         return $fields;
1770     }
1771 
1772     /**
1773      * Method to get a form field group represented as an XML element object.
1774      *
1775      * @param   string  $group  The dot-separated form group path on which to find the group.
1776      *
1777      * @return  SimpleXMLElement[]|boolean  An array of XML element objects for the group or boolean false on error.
1778      *
1779      * @since   11.1
1780      */
1781     protected function &findGroup($group)
1782     {
1783         $false = false;
1784         $groups = array();
1785         $tmp = array();
1786 
1787         // Make sure there is a valid JForm XML document.
1788         if (!($this->xml instanceof SimpleXMLElement))
1789         {
1790             return $false;
1791         }
1792 
1793         // Make sure there is actually a group to find.
1794         $group = explode('.', $group);
1795 
1796         if (!empty($group))
1797         {
1798             // Get any fields elements with the correct group name.
1799             $elements = $this->xml->xpath('//fields[@name="' . (string) $group[0] . '" and not(ancestor::field/form/*)]');
1800 
1801             // Check to make sure that there are no parent groups for each element.
1802             foreach ($elements as $element)
1803             {
1804                 if (!$element->xpath('ancestor::fields[@name]'))
1805                 {
1806                     $tmp[] = $element;
1807                 }
1808             }
1809 
1810             // Iterate through the nested groups to find any matching form field groups.
1811             for ($i = 1, $n = count($group); $i < $n; $i++)
1812             {
1813                 // Initialise some loop variables.
1814                 $validNames = array_slice($group, 0, $i + 1);
1815                 $current = $tmp;
1816                 $tmp = array();
1817 
1818                 // Check to make sure that there are no parent groups for each element.
1819                 foreach ($current as $element)
1820                 {
1821                     // Get any fields elements with the correct group name.
1822                     $children = $element->xpath('descendant::fields[@name="' . (string) $group[$i] . '"]');
1823 
1824                     // For the found fields elements validate that they are in the correct groups.
1825                     foreach ($children as $fields)
1826                     {
1827                         // Get the group names as strings for ancestor fields elements.
1828                         $attrs = $fields->xpath('ancestor-or-self::fields[@name]/@name');
1829                         $names = array_map('strval', $attrs ? $attrs : array());
1830 
1831                         // If the group names for the fields element match the valid names at this
1832                         // level add the fields element.
1833                         if ($validNames == $names)
1834                         {
1835                             $tmp[] = $fields;
1836                         }
1837                     }
1838                 }
1839             }
1840 
1841             // Only include valid XML objects.
1842             foreach ($tmp as $element)
1843             {
1844                 if ($element instanceof SimpleXMLElement)
1845                 {
1846                     $groups[] = $element;
1847                 }
1848             }
1849         }
1850 
1851         return $groups;
1852     }
1853 
1854     /**
1855      * Method to load, setup and return a JFormField object based on field data.
1856      *
1857      * @param   string  $element  The XML element object representation of the form field.
1858      * @param   string  $group    The optional dot-separated form group path on which to find the field.
1859      * @param   mixed   $value    The optional value to use as the default for the field.
1860      *
1861      * @return  JFormField|boolean  The JFormField object for the field or boolean false on error.
1862      *
1863      * @since   11.1
1864      */
1865     protected function loadField($element, $group = null, $value = null)
1866     {
1867         // Make sure there is a valid SimpleXMLElement.
1868         if (!($element instanceof SimpleXMLElement))
1869         {
1870             return false;
1871         }
1872 
1873         // Get the field type.
1874         $type = $element['type'] ? (string) $element['type'] : 'text';
1875 
1876         // Load the JFormField object for the field.
1877         $field = $this->loadFieldType($type);
1878 
1879         // If the object could not be loaded, get a text field object.
1880         if ($field === false)
1881         {
1882             $field = $this->loadFieldType('text');
1883         }
1884 
1885         /*
1886          * Get the value for the form field if not set.
1887          * Default to the translated version of the 'default' attribute
1888          * if 'translate_default' attribute if set to 'true' or '1'
1889          * else the value of the 'default' attribute for the field.
1890          */
1891         if ($value === null)
1892         {
1893             $default = (string) ($element['default'] ? $element['default'] : $element->default);
1894 
1895             if (($translate = $element['translate_default']) && ((string) $translate == 'true' || (string) $translate == '1'))
1896             {
1897                 $lang = JFactory::getLanguage();
1898 
1899                 if ($lang->hasKey($default))
1900                 {
1901                     $debug = $lang->setDebug(false);
1902                     $default = JText::_($default);
1903                     $lang->setDebug($debug);
1904                 }
1905                 else
1906                 {
1907                     $default = JText::_($default);
1908                 }
1909             }
1910 
1911             $value = $this->getValue((string) $element['name'], $group, $default);
1912         }
1913 
1914         // Setup the JFormField object.
1915         $field->setForm($this);
1916 
1917         if ($field->setup($element, $value, $group))
1918         {
1919             return $field;
1920         }
1921         else
1922         {
1923             return false;
1924         }
1925     }
1926 
1927     /**
1928      * Proxy for {@link JFormHelper::loadFieldType()}.
1929      *
1930      * @param   string   $type  The field type.
1931      * @param   boolean  $new   Flag to toggle whether we should get a new instance of the object.
1932      *
1933      * @return  JFormField|boolean  JFormField object on success, false otherwise.
1934      *
1935      * @since   11.1
1936      */
1937     protected function loadFieldType($type, $new = true)
1938     {
1939         return JFormHelper::loadFieldType($type, $new);
1940     }
1941 
1942     /**
1943      * Proxy for JFormHelper::loadRuleType().
1944      *
1945      * @param   string   $type  The rule type.
1946      * @param   boolean  $new   Flag to toggle whether we should get a new instance of the object.
1947      *
1948      * @return  JFormRule|boolean  JFormRule object on success, false otherwise.
1949      *
1950      * @see     JFormHelper::loadRuleType()
1951      * @since   11.1
1952      */
1953     protected function loadRuleType($type, $new = true)
1954     {
1955         return JFormHelper::loadRuleType($type, $new);
1956     }
1957 
1958     /**
1959      * Method to synchronize any field, form or rule paths contained in the XML document.
1960      *
1961      * @return  boolean  True on success.
1962      *
1963      * @since   11.1
1964      * @todo    Maybe we should receive all addXXXpaths attributes at once?
1965      */
1966     protected function syncPaths()
1967     {
1968         // Make sure there is a valid JForm XML document.
1969         if (!($this->xml instanceof SimpleXMLElement))
1970         {
1971             return false;
1972         }
1973 
1974         // Get any addfieldpath attributes from the form definition.
1975         $paths = $this->xml->xpath('//*[@addfieldpath]/@addfieldpath');
1976         $paths = array_map('strval', $paths ? $paths : array());
1977 
1978         // Add the field paths.
1979         foreach ($paths as $path)
1980         {
1981             $path = JPATH_ROOT . '/' . ltrim($path, '/\\');
1982             self::addFieldPath($path);
1983         }
1984 
1985         // Get any addformpath attributes from the form definition.
1986         $paths = $this->xml->xpath('//*[@addformpath]/@addformpath');
1987         $paths = array_map('strval', $paths ? $paths : array());
1988 
1989         // Add the form paths.
1990         foreach ($paths as $path)
1991         {
1992             $path = JPATH_ROOT . '/' . ltrim($path, '/\\');
1993             self::addFormPath($path);
1994         }
1995 
1996         // Get any addrulepath attributes from the form definition.
1997         $paths = $this->xml->xpath('//*[@addrulepath]/@addrulepath');
1998         $paths = array_map('strval', $paths ? $paths : array());
1999 
2000         // Add the rule paths.
2001         foreach ($paths as $path)
2002         {
2003             $path = JPATH_ROOT . '/' . ltrim($path, '/\\');
2004             self::addRulePath($path);
2005         }
2006 
2007         return true;
2008     }
2009 
2010     /**
2011      * Method to validate a JFormField object based on field data.
2012      *
2013      * @param   SimpleXMLElement  $element  The XML element object representation of the form field.
2014      * @param   string            $group    The optional dot-separated form group path on which to find the field.
2015      * @param   mixed             $value    The optional value to use as the default for the field.
2016      * @param   Registry          $input    An optional Registry object with the entire data set to validate
2017      *                                      against the entire form.
2018      *
2019      * @return  boolean  Boolean true if field value is valid, Exception on failure.
2020      *
2021      * @since   11.1
2022      * @throws  InvalidArgumentException
2023      * @throws  UnexpectedValueException
2024      */
2025     protected function validateField(SimpleXMLElement $element, $group = null, $value = null, Registry $input = null)
2026     {
2027         $valid = true;
2028 
2029         // Check if the field is required.
2030         $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required');
2031 
2032         if ($required)
2033         {
2034             // If the field is required and the value is empty return an error message.
2035             if (($value === '') || ($value === null))
2036             {
2037                 if ($element['label'])
2038                 {
2039                     $message = JText::_($element['label']);
2040                 }
2041                 else
2042                 {
2043                     $message = JText::_($element['name']);
2044                 }
2045 
2046                 $message = JText::sprintf('JLIB_FORM_VALIDATE_FIELD_REQUIRED', $message);
2047 
2048                 return new RuntimeException($message);
2049             }
2050         }
2051 
2052         // Get the field validation rule.
2053         if ($type = (string) $element['validate'])
2054         {
2055             // Load the JFormRule object for the field.
2056             $rule = $this->loadRuleType($type);
2057 
2058             // If the object could not be loaded return an error message.
2059             if ($rule === false)
2060             {
2061                 throw new UnexpectedValueException(sprintf('%s::validateField() rule `%s` missing.', get_class($this), $type));
2062             }
2063 
2064             // Run the field validation rule test.
2065             $valid = $rule->test($element, $value, $group, $input, $this);
2066 
2067             // Check for an error in the validation test.
2068             if ($valid instanceof Exception)
2069             {
2070                 return $valid;
2071             }
2072         }
2073 
2074         // Check if the field is valid.
2075         if ($valid === false)
2076         {
2077             // Does the field have a defined error message?
2078             $message = (string) $element['message'];
2079 
2080             if ($message)
2081             {
2082                 $message = JText::_($element['message']);
2083 
2084                 return new UnexpectedValueException($message);
2085             }
2086             else
2087             {
2088                 $message = JText::_($element['label']);
2089                 $message = JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', $message);
2090 
2091                 return new UnexpectedValueException($message);
2092             }
2093         }
2094 
2095         return true;
2096     }
2097 
2098     /**
2099      * Proxy for {@link JFormHelper::addFieldPath()}.
2100      *
2101      * @param   mixed  $new  A path or array of paths to add.
2102      *
2103      * @return  array  The list of paths that have been added.
2104      *
2105      * @since   11.1
2106      */
2107     public static function addFieldPath($new = null)
2108     {
2109         return JFormHelper::addFieldPath($new);
2110     }
2111 
2112     /**
2113      * Proxy for JFormHelper::addFormPath().
2114      *
2115      * @param   mixed  $new  A path or array of paths to add.
2116      *
2117      * @return  array  The list of paths that have been added.
2118      *
2119      * @see     JFormHelper::addFormPath()
2120      * @since   11.1
2121      */
2122     public static function addFormPath($new = null)
2123     {
2124         return JFormHelper::addFormPath($new);
2125     }
2126 
2127     /**
2128      * Proxy for JFormHelper::addRulePath().
2129      *
2130      * @param   mixed  $new  A path or array of paths to add.
2131      *
2132      * @return  array  The list of paths that have been added.
2133      *
2134      * @see     JFormHelper::addRulePath()
2135      * @since   11.1
2136      */
2137     public static function addRulePath($new = null)
2138     {
2139         return JFormHelper::addRulePath($new);
2140     }
2141 
2142     /**
2143      * Method to get an instance of a form.
2144      *
2145      * @param   string          $name     The name of the form.
2146      * @param   string          $data     The name of an XML file or string to load as the form definition.
2147      * @param   array           $options  An array of form options.
2148      * @param   boolean         $replace  Flag to toggle whether form fields should be replaced if a field
2149      *                                    already exists with the same group/name.
2150      * @param   string|boolean  $xpath    An optional xpath to search for the fields.
2151      *
2152      * @return  JForm  JForm instance.
2153      *
2154      * @since   11.1
2155      * @throws  InvalidArgumentException if no data provided.
2156      * @throws  RuntimeException if the form could not be loaded.
2157      */
2158     public static function getInstance($name, $data = null, $options = array(), $replace = true, $xpath = false)
2159     {
2160         // Reference to array with form instances
2161         $forms = &self::$forms;
2162 
2163         // Only instantiate the form if it does not already exist.
2164         if (!isset($forms[$name]))
2165         {
2166             $data = trim($data);
2167 
2168             if (empty($data))
2169             {
2170                 throw new InvalidArgumentException(sprintf('JForm::getInstance(%s, *%s*)', $name, gettype($data)));
2171             }
2172 
2173             // Instantiate the form.
2174             $forms[$name] = new JForm($name, $options);
2175 
2176             // Load the data.
2177             if (substr($data, 0, 1) == '<')
2178             {
2179                 if ($forms[$name]->load($data, $replace, $xpath) == false)
2180                 {
2181                     throw new RuntimeException('JForm::getInstance could not load form');
2182                 }
2183             }
2184             else
2185             {
2186                 if ($forms[$name]->loadFile($data, $replace, $xpath) == false)
2187                 {
2188                     throw new RuntimeException('JForm::getInstance could not load file');
2189                 }
2190             }
2191         }
2192 
2193         return $forms[$name];
2194     }
2195 
2196     /**
2197      * Adds a new child SimpleXMLElement node to the source.
2198      *
2199      * @param   SimpleXMLElement  $source  The source element on which to append.
2200      * @param   SimpleXMLElement  $new     The new element to append.
2201      *
2202      * @return  void
2203      *
2204      * @since   11.1
2205      */
2206     protected static function addNode(SimpleXMLElement $source, SimpleXMLElement $new)
2207     {
2208         // Add the new child node.
2209         $node = $source->addChild($new->getName(), htmlspecialchars(trim($new)));
2210 
2211         // Add the attributes of the child node.
2212         foreach ($new->attributes() as $name => $value)
2213         {
2214             $node->addAttribute($name, $value);
2215         }
2216 
2217         // Add any children of the new node.
2218         foreach ($new->children() as $child)
2219         {
2220             self::addNode($node, $child);
2221         }
2222     }
2223 
2224     /**
2225      * Update the attributes of a child node
2226      *
2227      * @param   SimpleXMLElement  $source  The source element on which to append the attributes
2228      * @param   SimpleXMLElement  $new     The new element to append
2229      *
2230      * @return  void
2231      *
2232      * @since   11.1
2233      */
2234     protected static function mergeNode(SimpleXMLElement $source, SimpleXMLElement $new)
2235     {
2236         // Update the attributes of the child node.
2237         foreach ($new->attributes() as $name => $value)
2238         {
2239             if (isset($source[$name]))
2240             {
2241                 $source[$name] = (string) $value;
2242             }
2243             else
2244             {
2245                 $source->addAttribute($name, $value);
2246             }
2247         }
2248     }
2249 
2250     /**
2251      * Merges new elements into a source `<fields>` element.
2252      *
2253      * @param   SimpleXMLElement  $source  The source element.
2254      * @param   SimpleXMLElement  $new     The new element to merge.
2255      *
2256      * @return  void
2257      *
2258      * @since   11.1
2259      */
2260     protected static function mergeNodes(SimpleXMLElement $source, SimpleXMLElement $new)
2261     {
2262         // The assumption is that the inputs are at the same relative level.
2263         // So we just have to scan the children and deal with them.
2264 
2265         // Update the attributes of the child node.
2266         foreach ($new->attributes() as $name => $value)
2267         {
2268             if (isset($source[$name]))
2269             {
2270                 $source[$name] = (string) $value;
2271             }
2272             else
2273             {
2274                 $source->addAttribute($name, $value);
2275             }
2276         }
2277 
2278         foreach ($new->children() as $child)
2279         {
2280             $type = $child->getName();
2281             $name = $child['name'];
2282 
2283             // Does this node exist?
2284             $fields = $source->xpath($type . '[@name="' . $name . '"]');
2285 
2286             if (empty($fields))
2287             {
2288                 // This node does not exist, so add it.
2289                 self::addNode($source, $child);
2290             }
2291             else
2292             {
2293                 // This node does exist.
2294                 switch ($type)
2295                 {
2296                     case 'field':
2297                         self::mergeNode($fields[0], $child);
2298                         break;
2299 
2300                     default:
2301                         self::mergeNodes($fields[0], $child);
2302                         break;
2303                 }
2304             }
2305         }
2306     }
2307 
2308     /**
2309      * Returns the value of an attribute of the form itself
2310      *
2311      * @param   string  $name     Name of the attribute to get
2312      * @param   mixed   $default  Optional value to return if attribute not found
2313      *
2314      * @return  mixed             Value of the attribute / default
2315      *
2316      * @since   3.2
2317      */
2318     public function getAttribute($name, $default = null)
2319     {
2320         if ($this->xml instanceof SimpleXMLElement)
2321         {
2322             $attributes = $this->xml->attributes();
2323 
2324             // Ensure that the attribute exists
2325             if (property_exists($attributes, $name))
2326             {
2327                 $value = $attributes->$name;
2328 
2329                 if ($value !== null)
2330                 {
2331                     return (string) $value;
2332                 }
2333             }
2334         }
2335 
2336         return $default;
2337     }
2338 
2339     /**
2340      * Getter for the form data
2341      *
2342      * @return   Registry  Object with the data
2343      *
2344      * @since    3.2
2345      */
2346     public function getData()
2347     {
2348         return $this->data;
2349     }
2350 
2351     /**
2352      * Method to get the XML form object
2353      *
2354      * @return  SimpleXMLElement  The form XML object
2355      *
2356      * @since   3.2
2357      */
2358     public function getXml()
2359     {
2360         return $this->xml;
2361     }
2362 
2363     /**
2364      * Method to get a form field represented as an XML element object.
2365      *
2366      * @param   string  $name   The name of the form field.
2367      * @param   string  $group  The optional dot-separated form group path on which to find the field.
2368      *
2369      * @return  SimpleXMLElement|boolean  The XML element object for the field or boolean false on error.
2370      *
2371      * @since   3.7.0
2372      */
2373     public function getFieldXml($name, $group = null)
2374     {
2375         return $this->findField($name, $group);
2376     }
2377 }
2378 
Joomla! Framework TM API documentation generated by ApiGen 2.8.0
Joomla!® and Joomla! Framework™ are trademarks of Open Source Matters, Inc. in the United States and other countries.