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     FrameworkOnFramework
   4  * @subpackage  model
   5  * @copyright   Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
   6  * @license     GNU General Public License version 2 or later; see LICENSE.txt
   7  */
   8 // Protect from unauthorized access
   9 defined('FOF_INCLUDED') or die;
  10 
  11 /**
  12  * FrameworkOnFramework Model class. The Model is the workhorse. It performs all
  13  * of the business logic based on its state and then returns the raw (processed)
  14  * data to the caller, or modifies its own state. It's important to note that
  15  * the model doesn't get data directly from the request (this is the
  16  * Controller's business) and that it doesn't output anything (that the View's
  17  * business).
  18  *
  19  * @package  FrameworkOnFramework
  20  * @since    1.0
  21  */
  22 class FOFModel extends FOFUtilsObject
  23 {
  24     /**
  25      * Indicates if the internal state has been set
  26      *
  27      * @var    boolean
  28      * @since  12.2
  29      */
  30     protected $__state_set = null;
  31 
  32     /**
  33      * Database Connector
  34      *
  35      * @var    object
  36      * @since  12.2
  37      */
  38     protected $_db;
  39 
  40     /**
  41      * The event to trigger after deleting the data.
  42      * @var    string
  43      */
  44     protected $event_after_delete = 'onContentAfterDelete';
  45 
  46     /**
  47      * The event to trigger after saving the data.
  48      * @var    string
  49      */
  50     protected $event_after_save = 'onContentAfterSave';
  51 
  52     /**
  53      * The event to trigger before deleting the data.
  54      * @var    string
  55      */
  56     protected $event_before_delete = 'onContentBeforeDelete';
  57 
  58     /**
  59      * The event to trigger before saving the data.
  60      * @var    string
  61      */
  62     protected $event_before_save = 'onContentBeforeSave';
  63 
  64     /**
  65      * The event to trigger after changing the published state of the data.
  66      * @var    string
  67      */
  68     protected $event_change_state = 'onContentChangeState';
  69 
  70     /**
  71      * The event to trigger when cleaning cache.
  72      *
  73      * @var      string
  74      * @since    12.2
  75      */
  76     protected $event_clean_cache = null;
  77 
  78     /**
  79      * Stores a list of IDs passed to the model's state
  80      * @var array
  81      */
  82     protected $id_list = array();
  83 
  84     /**
  85      * The first row ID passed to the model's state
  86      * @var int
  87      */
  88     protected $id = null;
  89 
  90     /**
  91      * Input variables, passed on from the controller, in an associative array
  92      * @var FOFInput
  93      */
  94     protected $input = array();
  95 
  96     /**
  97      * The list of records made available through getList
  98      * @var array
  99      */
 100     protected $list = null;
 101 
 102     /**
 103      * The model (base) name
 104      *
 105      * @var    string
 106      * @since  12.2
 107      */
 108     protected $name;
 109 
 110     /**
 111      * The URL option for the component.
 112      *
 113      * @var    string
 114      * @since  12.2
 115      */
 116     protected $option = null;
 117 
 118     /**
 119      * The table object, populated when saving data
 120      * @var FOFTable
 121      */
 122     protected $otable = null;
 123 
 124     /**
 125      * Pagination object
 126      * @var JPagination
 127      */
 128     protected $pagination = null;
 129 
 130     /**
 131      * The table object, populated when retrieving data
 132      * @var FOFTable
 133      */
 134     protected $record = null;
 135 
 136     /**
 137      * A state object
 138      *
 139      * @var    string
 140      * @since  12.2
 141      */
 142     protected $state;
 143 
 144     /**
 145      * The name of the table to use
 146      * @var string
 147      */
 148     protected $table = null;
 149 
 150     /**
 151      * Total rows based on the filters set in the model's state
 152      * @var int
 153      */
 154     protected $total = null;
 155 
 156     /**
 157      * Should I save the model's state in the session?
 158      * @var bool
 159      */
 160     protected $_savestate = null;
 161 
 162     /**
 163      * Array of form objects.
 164      *
 165      * @var    array
 166      * @since  2.0
 167      */
 168     protected $_forms = array();
 169 
 170     /**
 171      * The data to load into a form
 172      *
 173      * @var    array
 174      * @since  2.0
 175      */
 176     protected $_formData = array();
 177 
 178     /**
 179      * An instance of FOFConfigProvider to provision configuration overrides
 180      *
 181      * @var    FOFConfigProvider
 182      */
 183     protected $configProvider = null;
 184 
 185     /**
 186      * FOFModelDispatcherBehavior for dealing with extra behaviors
 187      *
 188      * @var    FOFModelDispatcherBehavior
 189      */
 190     protected $modelDispatcher = null;
 191 
 192     /**
 193      *  Default behaviors to apply to the model
 194      *
 195      * @var     array
 196      */
 197     protected $default_behaviors = array('filters');
 198 
 199     /**
 200      * Behavior parameters
 201      *
 202      * @var    array
 203      */
 204     protected $_behaviorParams = array();
 205 
 206     /**
 207      * Returns a new model object. Unless overriden by the $config array, it will
 208      * try to automatically populate its state from the request variables.
 209      *
 210      * @param   string  $type    Model type, e.g. 'Items'
 211      * @param   string  $prefix  Model prefix, e.g. 'FoobarModel'
 212      * @param   array   $config  Model configuration variables
 213      *
 214      * @return  FOFModel
 215      */
 216     public static function &getAnInstance($type, $prefix = '', $config = array())
 217     {
 218         // Make sure $config is an array
 219         if (is_object($config))
 220         {
 221             $config = (array) $config;
 222         }
 223         elseif (!is_array($config))
 224         {
 225             $config = array();
 226         }
 227 
 228         $type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type);
 229         $modelClass = $prefix . ucfirst($type);
 230         $result = false;
 231 
 232         // Guess the component name and include path
 233         if (!empty($prefix))
 234         {
 235             preg_match('/(.*)Model$/', $prefix, $m);
 236             $component = 'com_' . strtolower($m[1]);
 237         }
 238         else
 239         {
 240             $component = '';
 241         }
 242 
 243         if (array_key_exists('input', $config))
 244         {
 245             if (!($config['input'] instanceof FOFInput))
 246             {
 247                 if (!is_array($config['input']))
 248                 {
 249                     $config['input'] = (array) $config['input'];
 250                 }
 251 
 252                 $config['input'] = array_merge($_REQUEST, $config['input']);
 253                 $config['input'] = new FOFInput($config['input']);
 254             }
 255         }
 256         else
 257         {
 258             $config['input'] = new FOFInput;
 259         }
 260 
 261         if (empty($component))
 262         {
 263             $component = $config['input']->get('option', 'com_foobar');
 264         }
 265 
 266         $config['option'] = $component;
 267 
 268         $needsAView = true;
 269 
 270         if (array_key_exists('view', $config))
 271         {
 272             if (!empty($config['view']))
 273             {
 274                 $needsAView = false;
 275             }
 276         }
 277 
 278         if ($needsAView)
 279         {
 280             $config['view'] = strtolower($type);
 281         }
 282 
 283         $config['input']->set('option', $config['option']);
 284 
 285         // Get the component directories
 286         $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($component);
 287         $filesystem     = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
 288 
 289         // Try to load the requested model class
 290         if (!class_exists($modelClass))
 291         {
 292             $include_paths = self::addIncludePath();
 293 
 294             $extra_paths = array(
 295                 $componentPaths['main'] . '/models',
 296                 $componentPaths['alt'] . '/models'
 297             );
 298 
 299             $include_paths = array_merge($extra_paths, $include_paths);
 300 
 301             // Try to load the model file
 302             $path = $filesystem->pathFind(
 303                     $include_paths, self::_createFileName('model', array('name' => $type))
 304             );
 305 
 306             if ($path)
 307             {
 308                 require_once $path;
 309             }
 310         }
 311 
 312         // Fallback to the Default model class, e.g. FoobarModelDefault
 313         if (!class_exists($modelClass))
 314         {
 315             $modelClass = $prefix . 'Default';
 316 
 317             if (!class_exists($modelClass))
 318             {
 319                 $include_paths = self::addIncludePath();
 320 
 321                 $extra_paths = array(
 322                     $componentPaths['main'] . '/models',
 323                     $componentPaths['alt'] . '/models'
 324                 );
 325 
 326                 $include_paths = array_merge($extra_paths, $include_paths);
 327 
 328                 // Try to load the model file
 329                 $path = $filesystem->pathFind(
 330                         $include_paths, self::_createFileName('model', array('name' => 'default'))
 331                 );
 332 
 333                 if ($path)
 334                 {
 335                     require_once $path;
 336                 }
 337             }
 338         }
 339 
 340         // Fallback to the generic FOFModel model class
 341 
 342         if (!class_exists($modelClass))
 343         {
 344             $modelClass = 'FOFModel';
 345         }
 346 
 347         $result = new $modelClass($config);
 348 
 349         return $result;
 350     }
 351 
 352     /**
 353      * Adds a behavior to the model
 354      *
 355      * @param   string  $name    The name of the behavior
 356      * @param   array   $config  Optional Behavior configuration
 357      *
 358      * @return  boolean  True if the behavior is found and added
 359      */
 360     public function addBehavior($name, $config = array())
 361     {
 362         // Sanity check: this objects needs a non-null behavior handler
 363         if (!is_object($this->modelDispatcher))
 364         {
 365             return false;
 366         }
 367 
 368         // Sanity check: this objects needs a behavior handler of the correct class type
 369         if (!($this->modelDispatcher instanceof FOFModelDispatcherBehavior))
 370         {
 371             return false;
 372         }
 373 
 374         // First look for ComponentnameModelViewnameBehaviorName (e.g. FoobarModelItemsBehaviorFilter)
 375         $option_name = str_replace('com_', '', $this->option);
 376         $behaviorClass = ucfirst($option_name) . 'Model' . FOFInflector::pluralize($this->name) . 'Behavior' . ucfirst(strtolower($name));
 377 
 378         if (class_exists($behaviorClass))
 379         {
 380             $behavior = new $behaviorClass($this->modelDispatcher, $config);
 381 
 382             return true;
 383         }
 384 
 385         // Then look for ComponentnameModelBehaviorName (e.g. FoobarModelBehaviorFilter)
 386         $option_name = str_replace('com_', '', $this->option);
 387         $behaviorClass = ucfirst($option_name) . 'ModelBehavior' . ucfirst(strtolower($name));
 388 
 389         if (class_exists($behaviorClass))
 390         {
 391             $behavior = new $behaviorClass($this->modelDispatcher, $config);
 392 
 393             return true;
 394         }
 395 
 396         // Then look for FOFModelBehaviorName (e.g. FOFModelBehaviorFilter)
 397         $behaviorClassAlt = 'FOFModelBehavior' . ucfirst(strtolower($name));
 398 
 399         if (class_exists($behaviorClassAlt))
 400         {
 401             $behavior = new $behaviorClassAlt($this->modelDispatcher, $config);
 402 
 403             return true;
 404         }
 405 
 406         // Nothing found? Return false.
 407 
 408         return false;
 409     }
 410 
 411     /**
 412      * Returns a new instance of a model, with the state reset to defaults
 413      *
 414      * @param   string  $type    Model type, e.g. 'Items'
 415      * @param   string  $prefix  Model prefix, e.g. 'FoobarModel'
 416      * @param   array   $config  Model configuration variables
 417      *
 418      * @return FOFModel
 419      */
 420     public static function &getTmpInstance($type, $prefix = '', $config = array())
 421     {
 422         // Make sure $config is an array
 423         if (is_object($config))
 424         {
 425             $config = (array) $config;
 426         }
 427         elseif (!is_array($config))
 428         {
 429             $config = array();
 430         }
 431 
 432         if (!array_key_exists('savestate', $config))
 433         {
 434             $config['savestate'] = false;
 435         }
 436 
 437         $ret = self::getAnInstance($type, $prefix, $config)
 438             ->getClone()
 439             ->clearState()
 440             ->clearInput()
 441             ->reset()
 442             ->savestate(0)
 443             ->limitstart(0)
 444             ->limit(0);
 445 
 446         return $ret;
 447     }
 448 
 449     /**
 450      * Add a directory where FOFModel should search for models. You may
 451      * either pass a string or an array of directories.
 452      *
 453      * @param   mixed   $path    A path or array[sting] of paths to search.
 454      * @param   string  $prefix  A prefix for models.
 455      *
 456      * @return  array  An array with directory elements. If prefix is equal to '', all directories are returned.
 457      *
 458      * @since   12.2
 459      */
 460     public static function addIncludePath($path = '', $prefix = '')
 461     {
 462         static $paths;
 463 
 464         if (!isset($paths))
 465         {
 466             $paths = array();
 467         }
 468 
 469         if (!isset($paths[$prefix]))
 470         {
 471             $paths[$prefix] = array();
 472         }
 473 
 474         if (!isset($paths['']))
 475         {
 476             $paths[''] = array();
 477         }
 478 
 479         if (!empty($path))
 480         {
 481             $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
 482 
 483             if (!in_array($path, $paths[$prefix]))
 484             {
 485                 array_unshift($paths[$prefix], $filesystem->pathClean($path));
 486             }
 487 
 488             if (!in_array($path, $paths['']))
 489             {
 490                 array_unshift($paths[''], $filesystem->pathClean($path));
 491             }
 492         }
 493 
 494         return $paths[$prefix];
 495     }
 496 
 497     /**
 498      * Adds to the stack of model table paths in LIFO order.
 499      *
 500      * @param   mixed  $path  The directory as a string or directories as an array to add.
 501      *
 502      * @return  void
 503      *
 504      * @since   12.2
 505      */
 506     public static function addTablePath($path)
 507     {
 508         FOFTable::addIncludePath($path);
 509     }
 510 
 511     /**
 512      * Create the filename for a resource
 513      *
 514      * @param   string  $type   The resource type to create the filename for.
 515      * @param   array   $parts  An associative array of filename information.
 516      *
 517      * @return  string  The filename
 518      *
 519      * @since   12.2
 520      */
 521     protected static function _createFileName($type, $parts = array())
 522     {
 523         $filename = '';
 524 
 525         switch ($type)
 526         {
 527             case 'model':
 528                 $filename = strtolower($parts['name']) . '.php';
 529                 break;
 530         }
 531 
 532         return $filename;
 533     }
 534 
 535     /**
 536      * Public class constructor
 537      *
 538      * @param array $config The configuration array
 539      */
 540     public function __construct($config = array())
 541     {
 542         // Make sure $config is an array
 543         if (is_object($config))
 544         {
 545             $config = (array) $config;
 546         }
 547         elseif (!is_array($config))
 548         {
 549             $config = array();
 550         }
 551 
 552         // Get the input
 553         if (array_key_exists('input', $config))
 554         {
 555             if ($config['input'] instanceof FOFInput)
 556             {
 557                 $this->input = $config['input'];
 558             }
 559             else
 560             {
 561                 $this->input = new FOFInput($config['input']);
 562             }
 563         }
 564         else
 565         {
 566             $this->input = new FOFInput;
 567         }
 568 
 569         // Load the configuration provider
 570         $this->configProvider = new FOFConfigProvider;
 571 
 572         // Load the behavior dispatcher
 573         $this->modelDispatcher = new FOFModelDispatcherBehavior;
 574 
 575         // Set the $name/$_name variable
 576         $component = $this->input->getCmd('option', 'com_foobar');
 577 
 578         if (array_key_exists('option', $config))
 579         {
 580             $component = $config['option'];
 581         }
 582 
 583         // Set the $name variable
 584         $this->input->set('option', $component);
 585         $component = $this->input->getCmd('option', 'com_foobar');
 586 
 587         if (array_key_exists('option', $config))
 588         {
 589             $component = $config['option'];
 590         }
 591 
 592         $this->input->set('option', $component);
 593         $bareComponent = str_replace('com_', '', strtolower($component));
 594 
 595         // Get the view name
 596         $className = get_class($this);
 597 
 598         if ($className == 'FOFModel')
 599         {
 600             if (array_key_exists('view', $config))
 601             {
 602                 $view = $config['view'];
 603             }
 604 
 605             if (empty($view))
 606             {
 607                 $view = $this->input->getCmd('view', 'cpanel');
 608             }
 609         }
 610         else
 611         {
 612             if (array_key_exists('view', $config))
 613             {
 614                 $view = $config['view'];
 615             }
 616 
 617             if (empty($view))
 618             {
 619                 $eliminatePart = ucfirst($bareComponent) . 'Model';
 620                 $view = strtolower(str_replace($eliminatePart, '', $className));
 621             }
 622         }
 623 
 624         if (array_key_exists('name', $config))
 625         {
 626             $name = $config['name'];
 627         }
 628         else
 629         {
 630             $name = $view;
 631         }
 632 
 633         $this->name = $name;
 634         $this->option = $component;
 635 
 636         // Set the model state
 637         if (array_key_exists('state', $config))
 638         {
 639             $this->state = $config['state'];
 640         }
 641         else
 642         {
 643             $this->state = new FOFUtilsObject;
 644         }
 645 
 646         // Set the model dbo
 647         if (array_key_exists('dbo', $config))
 648         {
 649             $this->_db = $config['dbo'];
 650         }
 651         else
 652         {
 653             $this->_db = FOFPlatform::getInstance()->getDbo();
 654         }
 655 
 656         // Set the default view search path
 657         if (array_key_exists('table_path', $config))
 658         {
 659             $this->addTablePath($config['table_path']);
 660         }
 661         else
 662         {
 663             $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($this->option);
 664 
 665             $path = $componentPaths['admin'] . '/tables';
 666             $altPath = $this->configProvider->get($this->option . '.views.' . FOFInflector::singularize($this->name) . '.config.table_path', null);
 667 
 668             if ($altPath)
 669             {
 670                 $path = $componentPaths['main'] . '/' . $altPath;
 671             }
 672 
 673             $this->addTablePath($path);
 674         }
 675 
 676         // Assign the correct table
 677         if (array_key_exists('table', $config))
 678         {
 679             $this->table = $config['table'];
 680         }
 681         else
 682         {
 683             $table = $this->configProvider->get(
 684                 $this->option . '.views.' . FOFInflector::singularize($this->name) .
 685                 '.config.table', FOFInflector::singularize($view)
 686             );
 687             $this->table = $table;
 688         }
 689 
 690         // Set the internal state marker - used to ignore setting state from the request
 691 
 692         if (!empty($config['ignore_request']) || !is_null(
 693                 $this->configProvider->get(
 694                     $this->option . '.views.' . FOFInflector::singularize($this->name) .
 695                     '.config.ignore_request', null
 696                 )
 697         ))
 698         {
 699             $this->__state_set = true;
 700         }
 701 
 702         // Get and store the pagination request variables
 703         $defaultSaveState = array_key_exists('savestate', $config) ? $config['savestate'] : -999;
 704         $this->populateSavestate($defaultSaveState);
 705 
 706         if (FOFPlatform::getInstance()->isCli())
 707         {
 708             $limit = 20;
 709             $limitstart = 0;
 710         }
 711         else
 712         {
 713             $app = JFactory::getApplication();
 714 
 715             if (method_exists($app, 'getCfg'))
 716             {
 717                 $default_limit = $app->getCfg('list_limit');
 718             }
 719             else
 720             {
 721                 $default_limit = 20;
 722             }
 723 
 724             $limit = $this->getUserStateFromRequest($component . '.' . $view . '.limit', 'limit', $default_limit, 'int', $this->_savestate);
 725             $limitstart = $this->getUserStateFromRequest($component . '.' . $view . '.limitstart', 'limitstart', 0, 'int', $this->_savestate);
 726         }
 727 
 728         $this->setState('limit', $limit);
 729         $this->setState('limitstart', $limitstart);
 730 
 731         // Get the ID or list of IDs from the request or the configuration
 732 
 733         if (array_key_exists('cid', $config))
 734         {
 735             $cid = $config['cid'];
 736         }
 737         elseif ($cid = $this->configProvider->get(
 738                 $this->option . '.views.' . FOFInflector::singularize($this->name) . '.config.cid', null
 739             )
 740         )
 741         {
 742             $cid = explode(',', $cid);
 743         }
 744         else
 745         {
 746             $cid = $this->input->get('cid', array(), 'array');
 747         }
 748 
 749         if (array_key_exists('id', $config))
 750         {
 751             $id = $config['id'];
 752         }
 753         elseif ($id = $this->configProvider->get(
 754                 $this->option . '.views.' . FOFInflector::singularize($this->name) . '.config.id', null
 755             )
 756         )
 757         {
 758             $id = explode(',', $id);
 759             $id = array_shift($id);
 760         }
 761         else
 762         {
 763             $id = $this->input->getInt('id', 0);
 764         }
 765 
 766         if (is_array($cid) && !empty($cid))
 767         {
 768             $this->setIds($cid);
 769         }
 770         else
 771         {
 772             $this->setId($id);
 773         }
 774 
 775         // Populate the event names from the $config array
 776         $configKey = $this->option . '.views.' . FOFInflector::singularize($view) . '.config.';
 777 
 778         // Assign after delete event handler
 779 
 780         if (isset($config['event_after_delete']))
 781         {
 782             $this->event_after_delete = $config['event_after_delete'];
 783         }
 784         else
 785         {
 786             $this->event_after_delete = $this->configProvider->get(
 787                 $configKey . 'event_after_delete',
 788                 $this->event_after_delete
 789             );
 790         }
 791 
 792         // Assign after save event handler
 793 
 794         if (isset($config['event_after_save']))
 795         {
 796             $this->event_after_save = $config['event_after_save'];
 797         }
 798         else
 799         {
 800             $this->event_after_save = $this->configProvider->get(
 801                 $configKey . 'event_after_save',
 802                 $this->event_after_save
 803             );
 804         }
 805 
 806         // Assign before delete event handler
 807 
 808         if (isset($config['event_before_delete']))
 809         {
 810             $this->event_before_delete = $config['event_before_delete'];
 811         }
 812         else
 813         {
 814             $this->event_before_delete = $this->configProvider->get(
 815                 $configKey . 'event_before_delete',
 816                 $this->event_before_delete
 817             );
 818         }
 819 
 820         // Assign before save event handler
 821 
 822         if (isset($config['event_before_save']))
 823         {
 824             $this->event_before_save = $config['event_before_save'];
 825         }
 826         else
 827         {
 828             $this->event_before_save = $this->configProvider->get(
 829                 $configKey . 'event_before_save',
 830                 $this->event_before_save
 831             );
 832         }
 833 
 834         // Assign state change event handler
 835 
 836         if (isset($config['event_change_state']))
 837         {
 838             $this->event_change_state = $config['event_change_state'];
 839         }
 840         else
 841         {
 842             $this->event_change_state = $this->configProvider->get(
 843                 $configKey . 'event_change_state',
 844                 $this->event_change_state
 845             );
 846         }
 847 
 848         // Assign cache clean event handler
 849 
 850         if (isset($config['event_clean_cache']))
 851         {
 852             $this->event_clean_cache = $config['event_clean_cache'];
 853         }
 854         else
 855         {
 856             $this->event_clean_cache = $this->configProvider->get(
 857                 $configKey . 'event_clean_cache',
 858                 $this->event_clean_cache
 859             );
 860         }
 861 
 862         // Apply model behaviors
 863 
 864         if (isset($config['behaviors']))
 865         {
 866             $behaviors = (array) $config['behaviors'];
 867         }
 868         elseif ($behaviors = $this->configProvider->get($configKey . 'behaviors', null))
 869         {
 870             $behaviors = explode(',', $behaviors);
 871         }
 872         else
 873         {
 874             $behaviors = $this->default_behaviors;
 875         }
 876 
 877         if (is_array($behaviors) && count($behaviors))
 878         {
 879             foreach ($behaviors as $behavior)
 880             {
 881                 $this->addBehavior($behavior);
 882             }
 883         }
 884     }
 885 
 886     /**
 887      * Sets the list of IDs from the request data
 888      *
 889      * @return FOFModel
 890      */
 891     public function setIDsFromRequest()
 892     {
 893         // Get the ID or list of IDs from the request or the configuration
 894         $cid = $this->input->get('cid', array(), 'array');
 895         $id = $this->input->getInt('id', 0);
 896         $kid = $this->input->getInt($this->getTable($this->table)->getKeyName(), 0);
 897 
 898         if (is_array($cid) && !empty($cid))
 899         {
 900             $this->setIds($cid);
 901         }
 902         else
 903         {
 904             if (empty($id))
 905             {
 906                 $this->setId($kid);
 907             }
 908             else
 909             {
 910                 $this->setId($id);
 911             }
 912         }
 913 
 914         return $this;
 915     }
 916 
 917     /**
 918      * Sets the ID and resets internal data
 919      *
 920      * @param   integer $id The ID to use
 921      *
 922      * @throws InvalidArgumentException
 923      *
 924      * @return FOFModel
 925      */
 926     public function setId($id = 0)
 927     {
 928         // If this is an array extract the first item
 929         if (is_array($id))
 930         {
 931             FOFPlatform::getInstance()->logDeprecated('Passing arrays to FOFModel::setId is deprecated. Use setIds() instead.');
 932             $id = array_shift($id);
 933         }
 934 
 935         // No string or no integer? What are you trying to do???
 936         if (!is_string($id) && !is_numeric($id))
 937         {
 938             throw new InvalidArgumentException(sprintf('%s::setId()', get_class($this)));
 939         }
 940 
 941         $this->reset();
 942         $this->id = (int) $id;
 943         $this->id_list = array($this->id);
 944 
 945         return $this;
 946     }
 947 
 948     /**
 949      * Returns the currently set ID
 950      *
 951      * @return  integer
 952      */
 953     public function getId()
 954     {
 955         return $this->id;
 956     }
 957 
 958     /**
 959      * Sets a list of IDs for batch operations from an array and resets the model
 960      *
 961      * @param   array  $idlist  An array of item IDs to be set to the model's state
 962      *
 963      * @return  FOFModel
 964      */
 965     public function setIds($idlist)
 966     {
 967         $this->reset();
 968         $this->id_list = array();
 969         $this->id = 0;
 970 
 971         if (is_array($idlist) && !empty($idlist))
 972         {
 973             foreach ($idlist as $value)
 974             {
 975                 // Protect vs fatal error (objects) and wrong behavior (nested array)
 976                 if(!is_object($value) && !is_array($value))
 977                 {
 978                     $this->id_list[] = (int) $value;
 979                 }
 980             }
 981 
 982             if(count($this->id_list))
 983             {
 984                 $this->id = $this->id_list[0];
 985             }
 986         }
 987 
 988         return $this;
 989     }
 990 
 991     /**
 992      * Returns the list of IDs for batch operations
 993      *
 994      * @return  array  An array of integers
 995      */
 996     public function getIds()
 997     {
 998         return $this->id_list;
 999     }
1000 
1001     /**
1002      * Resets the model, like it was freshly loaded
1003      *
1004      * @return  FOFModel
1005      */
1006     public function reset()
1007     {
1008         $this->id = 0;
1009         $this->id_list = null;
1010         $this->record = null;
1011         $this->list = null;
1012         $this->pagination = null;
1013         $this->total = null;
1014         $this->otable = null;
1015 
1016         return $this;
1017     }
1018 
1019     /**
1020      * Clears the model state, but doesn't touch the internal lists of records,
1021      * record tables or record id variables. To clear these values, please use
1022      * reset().
1023      *
1024      * @return  FOFModel
1025      */
1026     public function clearState()
1027     {
1028         $this->state = new FOFUtilsObject;
1029 
1030         return $this;
1031     }
1032 
1033     /**
1034      * Clears the input array.
1035      *
1036      * @return  FOFModel
1037      */
1038     public function clearInput()
1039     {
1040         $defSource = array();
1041         $this->input = new FOFInput($defSource);
1042 
1043         return $this;
1044     }
1045 
1046     /**
1047      * Set the internal input field
1048      *
1049      * @param $input
1050      *
1051      * @return FOFModel
1052      */
1053     public function setInput($input)
1054     {
1055         if (!($input instanceof FOFInput))
1056         {
1057             if (!is_array($input))
1058             {
1059                 $input = (array) $input;
1060             }
1061 
1062             $input = array_merge($_REQUEST, $input);
1063             $input = new FOFInput($input);
1064         }
1065 
1066         $this->input = $input;
1067 
1068         return $this;
1069     }
1070 
1071     /**
1072      * Resets the saved state for this view
1073      *
1074      * @return  FOFModel
1075      */
1076     public function resetSavedState()
1077     {
1078         JFactory::getApplication()->setUserState(substr($this->getHash(), 0, -1), null);
1079 
1080         return $this;
1081     }
1082 
1083     /**
1084      * Method to load a row for editing from the version history table.
1085      *
1086      * @param   integer    $version_id  Key to the version history table.
1087      * @param   FOFTable   &$table      Content table object being loaded.
1088      * @param   string     $alias       The type_alias in #__content_types
1089      *
1090      * @return  boolean  False on failure or error, true otherwise.
1091      *
1092      * @since   2.3
1093      */
1094     public function loadhistory($version_id, FOFTable &$table, $alias)
1095     {
1096         // Only attempt to check the row in if it exists.
1097         if ($version_id)
1098         {
1099             $user = JFactory::getUser();
1100 
1101             // Get an instance of the row to checkout.
1102             $historyTable = JTable::getInstance('Contenthistory');
1103 
1104             if (!$historyTable->load($version_id))
1105             {
1106                 $this->setError($historyTable->getError());
1107 
1108                 return false;
1109             }
1110 
1111             $rowArray = JArrayHelper::fromObject(json_decode($historyTable->version_data));
1112 
1113             $typeId = JTable::getInstance('Contenttype')->getTypeId($alias);
1114 
1115             if ($historyTable->ucm_type_id != $typeId)
1116             {
1117                 $this->setError(JText::_('JLIB_APPLICATION_ERROR_HISTORY_ID_MISMATCH'));
1118                 $key = $table->getKeyName();
1119 
1120                 if (isset($rowArray[$key]))
1121                 {
1122                     $table->checkIn($rowArray[$key]);
1123                 }
1124 
1125                 return false;
1126             }
1127         }
1128 
1129         $this->setState('save_date', $historyTable->save_date);
1130         $this->setState('version_note', $historyTable->version_note);
1131 
1132         return $table->bind($rowArray);
1133     }
1134 
1135     /**
1136      * Returns a single item. It uses the id set with setId, or the first ID in
1137      * the list of IDs for batch operations
1138      *
1139      * @param   integer  $id  Force a primary key ID to the model. Use null to use the id from the state.
1140      *
1141      * @return  FOFTable  A copy of the item's FOFTable array
1142      */
1143     public function &getItem($id = null)
1144     {
1145         if (!is_null($id))
1146         {
1147             $this->record = null;
1148             $this->setId($id);
1149         }
1150 
1151         if (empty($this->record))
1152         {
1153             $table = $this->getTable($this->table);
1154             $table->load($this->id);
1155             $this->record = $table;
1156 
1157             // Do we have saved data?
1158             $session = JFactory::getSession();
1159             if ($this->_savestate)
1160             {
1161                 $serialized = $session->get($this->getHash() . 'savedata', null);
1162                 if (!empty($serialized))
1163                 {
1164                     $data = @unserialize($serialized);
1165 
1166                     if ($data !== false)
1167                     {
1168                         $k = $table->getKeyName();
1169 
1170                         if (!array_key_exists($k, $data))
1171                         {
1172                             $data[$k] = null;
1173                         }
1174 
1175                         if ($data[$k] != $this->id)
1176                         {
1177                             $session->set($this->getHash() . 'savedata', null);
1178                         }
1179                         else
1180                         {
1181                             $this->record->bind($data);
1182                         }
1183                     }
1184                 }
1185             }
1186 
1187             $this->onAfterGetItem($this->record);
1188         }
1189 
1190         return $this->record;
1191     }
1192 
1193     /**
1194      * Alias for getItemList
1195      *
1196      * @param   boolean  $overrideLimits  Should I override set limits?
1197      * @param   string   $group           The group by clause
1198      * @codeCoverageIgnore
1199      *
1200      * @return  array
1201      */
1202     public function &getList($overrideLimits = false, $group = '')
1203     {
1204         return $this->getItemList($overrideLimits, $group);
1205     }
1206 
1207     /**
1208      * Returns a list of items
1209      *
1210      * @param   boolean  $overrideLimits  Should I override set limits?
1211      * @param   string   $group           The group by clause
1212      *
1213      * @return  array
1214      */
1215     public function &getItemList($overrideLimits = false, $group = '')
1216     {
1217         if (empty($this->list))
1218         {
1219             $query = $this->buildQuery($overrideLimits);
1220 
1221             if (!$overrideLimits)
1222             {
1223                 $limitstart = $this->getState('limitstart');
1224                 $limit = $this->getState('limit');
1225                 $this->list = $this->_getList((string) $query, $limitstart, $limit, $group);
1226             }
1227             else
1228             {
1229                 $this->list = $this->_getList((string) $query, 0, 0, $group);
1230             }
1231         }
1232 
1233         return $this->list;
1234     }
1235 
1236     /**
1237      * Returns a FOFDatabaseIterator over a list of items.
1238      *
1239      * THERE BE DRAGONS. Unlike the getItemList() you have a few restrictions:
1240      * - The onProcessList event does not run when you get an iterator
1241      * - The Iterator returns FOFTable instances. By default, $this->table is used. If you have JOINs, GROUPs or a
1242      *   complex query in general you will need to create a custom FOFTable subclass and pass its type in $tableType.
1243      *
1244      * The getIterator() method is a great way to sift through a large amount of records which would otherwise not fit
1245      * in memory since it only keeps one record in PHP memory at a time. It works best with simple models, returning
1246      * all the contents of a single database table.
1247      *
1248      * @param   boolean  $overrideLimits  Should I ignore set limits?
1249      * @param   string   $tableClass      The table class for the iterator, e.g. FoobarTableBar. Leave empty to use
1250      *                                    the default Table class for this Model.
1251      *
1252      * @return  FOFDatabaseIterator
1253      */
1254     public function &getIterator($overrideLimits = false, $tableClass = null)
1255     {
1256         // Get the table name (required by the Iterator)
1257         if (empty($tableClass))
1258         {
1259             $name = $this->table;
1260 
1261             if (empty($name))
1262             {
1263                 $name = FOFInflector::singularize($this->getName());
1264             }
1265 
1266             $bareComponent = str_replace('com_', '', $this->option);
1267             $prefix        = ucfirst($bareComponent) . 'Table';
1268 
1269             $tableClass = $prefix . ucfirst($name);
1270         }
1271 
1272         // Get the query
1273         $query = $this->buildQuery($overrideLimits);
1274 
1275         // Apply limits
1276         if ($overrideLimits)
1277         {
1278             $limitStart = 0;
1279             $limit = 0;
1280         }
1281         else
1282         {
1283             $limitStart = $this->getState('limitstart');
1284             $limit      = $this->getState('limit');
1285         }
1286 
1287         // This is required to prevent one relation from killing the db cursor used in a different relation...
1288         $oldDb = $this->getDbo();
1289         $oldDb->disconnect(); // YES, WE DO NEED TO DISCONNECT BEFORE WE CLONE THE DB OBJECT. ARGH!
1290         $db = clone $oldDb;
1291 
1292         // Execute the query, get a db cursor and return the iterator
1293         $db->setQuery($query, $limitStart, $limit);
1294 
1295         $cursor = $db->execute();
1296 
1297         $iterator = FOFDatabaseIterator::getIterator($db->name, $cursor, null, $tableClass);
1298 
1299         return $iterator;
1300     }
1301 
1302     /**
1303      * A cross-breed between getItem and getItemList. It runs the complete query,
1304      * like getItemList does. However, instead of returning an array of ad-hoc
1305      * objects, it binds the data from the first item fetched on the list to an
1306      * instance of the table object and returns that table object instead.
1307      *
1308      * @param   boolean  $overrideLimits  Should I override set limits?
1309      *
1310      * @return  FOFTable
1311      */
1312     public function &getFirstItem($overrideLimits = false)
1313     {
1314         /**
1315          * We have to clone the instance, or when multiple getFirstItem calls occur,
1316          * we'll update EVERY instance created
1317          */
1318         $table = clone $this->getTable($this->table);
1319 
1320         $list = $this->getItemList($overrideLimits);
1321 
1322         if (!empty($list))
1323         {
1324             $firstItem = array_shift($list);
1325             $table->bind($firstItem);
1326         }
1327 
1328         unset($list);
1329 
1330         return $table;
1331     }
1332 
1333     /**
1334      * Binds the data to the model and tries to save it
1335      *
1336      * @param   array|object  $data  The source data array or object
1337      *
1338      * @return  boolean  True on success
1339      */
1340     public function save($data)
1341     {
1342         $this->otable = null;
1343 
1344         $table = $this->getTable($this->table);
1345 
1346         if (is_object($data))
1347         {
1348             $data = clone($data);
1349         }
1350 
1351         $key = $table->getKeyName();
1352 
1353         if (array_key_exists($key, (array) $data))
1354         {
1355             $aData = (array) $data;
1356             $oid = $aData[$key];
1357             $table->load($oid);
1358         }
1359 
1360         if ($data instanceof FOFTable)
1361         {
1362             $allData = $data->getData();
1363         }
1364         elseif (is_object($data))
1365         {
1366             $allData = (array) $data;
1367         }
1368         else
1369         {
1370             $allData = $data;
1371         }
1372 
1373         // Get the form if there is any
1374         $form = $this->getForm($allData, false);
1375 
1376         if ($form instanceof FOFForm)
1377         {
1378             // Make sure that $allData has for any field a key
1379             $fieldset = $form->getFieldset();
1380 
1381             foreach ($fieldset as $nfield => $fldset)
1382             {
1383                 if (!array_key_exists($nfield, $allData))
1384                 {
1385                     $field = $form->getField($fldset->fieldname, $fldset->group);
1386                     $type  = strtolower($field->type);
1387 
1388                     switch ($type)
1389                     {
1390                         case 'checkbox':
1391                             $allData[$nfield] = 0;
1392                             break;
1393 
1394                         default:
1395                             $allData[$nfield] = '';
1396                             break;
1397                     }
1398                 }
1399             }
1400 
1401             $serverside_validate = strtolower($form->getAttribute('serverside_validate'));
1402 
1403             $validateResult = true;
1404             if (in_array($serverside_validate, array('true', 'yes', '1', 'on')))
1405             {
1406                 $validateResult = $this->validateForm($form, $allData);
1407             }
1408 
1409             if ($validateResult === false)
1410             {
1411                 if ($this->_savestate)
1412                 {
1413                     $session = JFactory::getSession();
1414                     $hash = $this->getHash() . 'savedata';
1415                     $session->set($hash, serialize($allData));
1416                 }
1417 
1418                 return false;
1419             }
1420         }
1421 
1422         if (!$this->onBeforeSave($allData, $table))
1423         {
1424             if ($this->_savestate)
1425             {
1426                 $session = JFactory::getSession();
1427                 $hash = $this->getHash() . 'savedata';
1428                 $session->set($hash, serialize($allData));
1429             }
1430 
1431             return false;
1432         }
1433         else
1434         {
1435             // If onBeforeSave successful, refetch the possibly modified data
1436             if ($data instanceof FOFTable)
1437             {
1438                 $data->bind($allData);
1439             }
1440             elseif (is_object($data))
1441             {
1442                 $data = (object) $allData;
1443             }
1444             else
1445             {
1446                 $data = $allData;
1447             }
1448         }
1449 
1450         if (!$table->save($data))
1451         {
1452             foreach ($table->getErrors() as $error)
1453             {
1454                 if (!empty($error))
1455                 {
1456                     $this->setError($error);
1457                     $session = JFactory::getSession();
1458                     $tableprops = $table->getProperties(true);
1459 
1460                     unset($tableprops['input']);
1461                     unset($tableprops['config']['input']);
1462                     unset($tableprops['config']['db']);
1463                     unset($tableprops['config']['dbo']);
1464 
1465 
1466                     if ($this->_savestate)
1467                     {
1468                         $hash = $this->getHash() . 'savedata';
1469                         $session->set($hash, serialize($tableprops));
1470                     }
1471                 }
1472             }
1473 
1474             return false;
1475         }
1476         else
1477         {
1478             $this->id = $table->$key;
1479 
1480             // Remove the session data
1481             if ($this->_savestate)
1482             {
1483                 JFactory::getSession()->set($this->getHash() . 'savedata', null);
1484             }
1485         }
1486 
1487         $this->onAfterSave($table);
1488 
1489         $this->otable = $table;
1490 
1491         return true;
1492     }
1493 
1494     /**
1495      * Copy one or more records
1496      *
1497      * @return  boolean  True on success
1498      */
1499     public function copy()
1500     {
1501         if (is_array($this->id_list) && !empty($this->id_list))
1502         {
1503             $table = $this->getTable($this->table);
1504 
1505             if (!$this->onBeforeCopy($table))
1506             {
1507                 return false;
1508             }
1509 
1510             if (!$table->copy($this->id_list))
1511             {
1512                 $this->setError($table->getError());
1513 
1514                 return false;
1515             }
1516             else
1517             {
1518                 // Call our internal event
1519                 $this->onAfterCopy($table);
1520 
1521                 // @todo Should we fire the content plugin?
1522             }
1523         }
1524 
1525         return true;
1526     }
1527 
1528     /**
1529      * Returns the table object after the last save() operation
1530      *
1531      * @return  FOFTable
1532      */
1533     public function getSavedTable()
1534     {
1535         return $this->otable;
1536     }
1537 
1538     /**
1539      * Deletes one or several items
1540      *
1541      * @return  boolean True on success
1542      */
1543     public function delete()
1544     {
1545         if (is_array($this->id_list) && !empty($this->id_list))
1546         {
1547             $table = $this->getTable($this->table);
1548 
1549             foreach ($this->id_list as $id)
1550             {
1551                 if (!$this->onBeforeDelete($id, $table))
1552                 {
1553                     continue;
1554                 }
1555 
1556                 if (!$table->delete($id))
1557                 {
1558                     $this->setError($table->getError());
1559 
1560                     return false;
1561                 }
1562                 else
1563                 {
1564                     $this->onAfterDelete($id);
1565                 }
1566             }
1567         }
1568 
1569         return true;
1570     }
1571 
1572     /**
1573      * Toggles the published state of one or several items
1574      *
1575      * @param   integer  $publish  The publishing state to set (e.g. 0 is unpublished)
1576      * @param   integer  $user     The user ID performing this action
1577      *
1578      * @return  boolean True on success
1579      */
1580     public function publish($publish = 1, $user = null)
1581     {
1582         if (is_array($this->id_list) && !empty($this->id_list))
1583         {
1584             if (empty($user))
1585             {
1586                 $oUser = FOFPlatform::getInstance()->getUser();
1587                 $user = $oUser->id;
1588             }
1589 
1590             $table = $this->getTable($this->table);
1591 
1592             if (!$this->onBeforePublish($table))
1593             {
1594                 return false;
1595             }
1596 
1597             if (!$table->publish($this->id_list, $publish, $user))
1598             {
1599                 $this->setError($table->getError());
1600 
1601                 return false;
1602             }
1603             else
1604             {
1605                 // Call our internal event
1606                 $this->onAfterPublish($table);
1607 
1608                 // Call the plugin events
1609                 FOFPlatform::getInstance()->importPlugin('content');
1610                 $name = $this->name;
1611                 $context = $this->option . '.' . $name;
1612 
1613                 // @TODO should we do anything with this return value?
1614                 $result  = FOFPlatform::getInstance()->runPlugins($this->event_change_state, array($context, $this->id_list, $publish));
1615             }
1616         }
1617 
1618         return true;
1619     }
1620 
1621     /**
1622      * Checks out the current item
1623      *
1624      * @return  boolean
1625      */
1626     public function checkout()
1627     {
1628         $table  = $this->getTable($this->table);
1629         $status = $table->checkout(FOFPlatform::getInstance()->getUser()->id, $this->id);
1630 
1631         if (!$status)
1632         {
1633             $this->setError($table->getError());
1634         }
1635 
1636         return $status;
1637     }
1638 
1639     /**
1640      * Checks in the current item
1641      *
1642      * @return  boolean
1643      */
1644     public function checkin()
1645     {
1646         $table  = $this->getTable($this->table);
1647         $status = $table->checkin($this->id);
1648 
1649         if (!$status)
1650         {
1651             $this->setError($table->getError());
1652         }
1653 
1654         return $status;
1655     }
1656 
1657     /**
1658      * Tells you if the current item is checked out or not
1659      *
1660      * @return  boolean
1661      */
1662     public function isCheckedOut()
1663     {
1664         $table  = $this->getTable($this->table);
1665         $status = $table->isCheckedOut($this->id);
1666 
1667         if (!$status)
1668         {
1669             $this->setError($table->getError());
1670         }
1671 
1672         return $status;
1673     }
1674 
1675     /**
1676      * Increments the hit counter
1677      *
1678      * @return  boolean
1679      */
1680     public function hit()
1681     {
1682         $table = $this->getTable($this->table);
1683 
1684         if (!$this->onBeforeHit($table))
1685         {
1686             return false;
1687         }
1688 
1689         $status = $table->hit($this->id);
1690 
1691         if (!$status)
1692         {
1693             $this->setError($table->getError());
1694         }
1695         else
1696         {
1697             $this->onAfterHit($table);
1698         }
1699 
1700         return $status;
1701     }
1702 
1703     /**
1704      * Moves the current item up or down in the ordering list
1705      *
1706      * @param   string  $dirn  The direction and magnitude to use (2 means move up by 2 positions, -3 means move down three positions)
1707      *
1708      * @return  boolean  True on success
1709      */
1710     public function move($dirn)
1711     {
1712         $table = $this->getTable($this->table);
1713 
1714         $id = $this->getId();
1715         $status = $table->load($id);
1716 
1717         if (!$status)
1718         {
1719             $this->setError($table->getError());
1720         }
1721 
1722         if (!$status)
1723         {
1724             return false;
1725         }
1726 
1727         if (!$this->onBeforeMove($table))
1728         {
1729             return false;
1730         }
1731 
1732         $status = $table->move($dirn);
1733 
1734         if (!$status)
1735         {
1736             $this->setError($table->getError());
1737         }
1738         else
1739         {
1740             $this->onAfterMove($table);
1741         }
1742 
1743         return $status;
1744     }
1745 
1746     /**
1747      * Reorders all items in the table
1748      *
1749      * @return  boolean
1750      */
1751     public function reorder()
1752     {
1753         $table = $this->getTable($this->table);
1754 
1755         if (!$this->onBeforeReorder($table))
1756         {
1757             return false;
1758         }
1759 
1760         $status = $table->reorder($this->getReorderWhere());
1761 
1762         if (!$status)
1763         {
1764             $this->setError($table->getError());
1765         }
1766         else
1767         {
1768             if (!$this->onAfterReorder($table))
1769             {
1770                 return false;
1771             }
1772         }
1773 
1774         return $status;
1775     }
1776 
1777     /**
1778      * Get a pagination object
1779      *
1780      * @return  JPagination
1781      */
1782     public function getPagination()
1783     {
1784         if (empty($this->pagination))
1785         {
1786             // Import the pagination library
1787             JLoader::import('joomla.html.pagination');
1788 
1789             // Prepare pagination values
1790             $total = $this->getTotal();
1791             $limitstart = $this->getState('limitstart');
1792             $limit = $this->getState('limit');
1793 
1794             // Create the pagination object
1795             $this->pagination = new JPagination($total, $limitstart, $limit);
1796         }
1797 
1798         return $this->pagination;
1799     }
1800 
1801     /**
1802      * Get the number of all items
1803      *
1804      * @return  integer
1805      */
1806     public function getTotal()
1807     {
1808         if (is_null($this->total))
1809         {
1810             $query = $this->buildCountQuery();
1811 
1812             if ($query === false)
1813             {
1814                 $subquery = $this->buildQuery(false);
1815                 $subquery->clear('order');
1816                 $query = $this->_db->getQuery(true)
1817                     ->select('COUNT(*)')
1818                     ->from("(" . (string) $subquery . ") AS a");
1819             }
1820 
1821             $this->_db->setQuery((string) $query);
1822 
1823             $this->total = $this->_db->loadResult();
1824         }
1825 
1826         return $this->total;
1827     }
1828 
1829     /**
1830      * Returns a record count for the query
1831      *
1832      * @param   string  $query  The query.
1833      *
1834      * @return  integer  Number of rows for query
1835      *
1836      * @since   12.2
1837      */
1838     protected function _getListCount($query)
1839     {
1840         return $this->getTotal();
1841     }
1842 
1843     /**
1844      * Get a filtered state variable
1845      *
1846      * @param   string  $key          The name of the state variable
1847      * @param   mixed   $default      The default value to use
1848      * @param   string  $filter_type  Filter type
1849      *
1850      * @return  mixed  The variable's value
1851      */
1852     public function getState($key = null, $default = null, $filter_type = 'raw')
1853     {
1854         if (empty($key))
1855         {
1856             return $this->_real_getState();
1857         }
1858 
1859         // Get the savestate status
1860         $value = $this->_real_getState($key);
1861 
1862         if (is_null($value))
1863         {
1864             $value = $this->getUserStateFromRequest($this->getHash() . $key, $key, $value, 'none', $this->_savestate);
1865 
1866             if (is_null($value))
1867             {
1868                 return $default;
1869             }
1870         }
1871 
1872         if (strtoupper($filter_type) == 'RAW')
1873         {
1874             return $value;
1875         }
1876         else
1877         {
1878             JLoader::import('joomla.filter.filterinput');
1879             $filter = new JFilterInput;
1880 
1881             return $filter->clean($value, $filter_type);
1882         }
1883     }
1884 
1885     /**
1886      * Method to get model state variables
1887      *
1888      * @param   string  $property  Optional parameter name
1889      * @param   mixed   $default   Optional default value
1890      *
1891      * @return  object  The property where specified, the state object where omitted
1892      *
1893      * @since   12.2
1894      */
1895     protected function _real_getState($property = null, $default = null)
1896     {
1897         if (!$this->__state_set)
1898         {
1899             // Protected method to auto-populate the model state.
1900             $this->populateState();
1901 
1902             // Set the model state set flag to true.
1903             $this->__state_set = true;
1904         }
1905 
1906         return $property === null ? $this->state : $this->state->get($property, $default);
1907     }
1908 
1909     /**
1910      * Returns a hash for this component and view, e.g. "foobar.items.", used
1911      * for determining the keys of the variables which will be placed in the
1912      * session storage.
1913      *
1914      * @return  string  The hash
1915      */
1916     public function getHash()
1917     {
1918         $option = $this->input->getCmd('option', 'com_foobar');
1919         $view = FOFInflector::pluralize($this->input->getCmd('view', 'cpanel'));
1920 
1921         return "$option.$view.";
1922     }
1923 
1924     /**
1925      * Gets the value of a user state variable.
1926      *
1927      * @param   string   $key           The key of the user state variable.
1928      * @param   string   $request       The name of the variable passed in a request.
1929      * @param   string   $default       The default value for the variable if not found. Optional.
1930      * @param   string   $type          Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional.
1931      * @param   boolean  $setUserState  Should I save the variable in the user state? Default: true. Optional.
1932      *
1933      * @return  string   The request user state.
1934      */
1935     protected function getUserStateFromRequest($key, $request, $default = null, $type = 'none', $setUserState = true)
1936     {
1937         return FOFPlatform::getInstance()->getUserStateFromRequest($key, $request, $this->input, $default, $type, $setUserState);
1938     }
1939 
1940     /**
1941      * Returns an object list
1942      *
1943      * @param   string   $query       The query
1944      * @param   integer  $limitstart  Offset from start
1945      * @param   integer  $limit       The number of records
1946      * @param   string   $group       The group by clause
1947      *
1948      * @return  array  Array of objects
1949      */
1950     protected function &_getList($query, $limitstart = 0, $limit = 0, $group = '')
1951     {
1952         $this->_db->setQuery($query, $limitstart, $limit);
1953         $result = $this->_db->loadObjectList($group);
1954 
1955         $this->onProcessList($result);
1956 
1957         return $result;
1958     }
1959 
1960     /**
1961      * Method to get a table object, load it if necessary.
1962      *
1963      * @param   string  $name The table name. Optional.
1964      * @param   string  $prefix The class prefix. Optional.
1965      * @param   array   $options Configuration array for model. Optional.
1966      *
1967      * @throws Exception
1968      *
1969      * @return  FOFTable  A FOFTable object
1970      */
1971     public function getTable($name = '', $prefix = null, $options = array())
1972     {
1973         if (empty($name))
1974         {
1975             $name = $this->table;
1976 
1977             if (empty($name))
1978             {
1979                 $name = FOFInflector::singularize($this->getName());
1980             }
1981         }
1982 
1983         if (empty($prefix))
1984         {
1985             $bareComponent = str_replace('com_', '', $this->option);
1986             $prefix        = ucfirst($bareComponent) . 'Table';
1987         }
1988 
1989         if (empty($options))
1990         {
1991             $options = array('input' => $this->input);
1992         }
1993 
1994         if ($table = $this->_createTable($name, $prefix, $options))
1995         {
1996             return $table;
1997         }
1998 
1999         FOFPlatform::getInstance()->raiseError(0, JText::sprintf('JLIB_APPLICATION_ERROR_TABLE_NAME_NOT_SUPPORTED', $name));
2000 
2001         return null;
2002     }
2003 
2004     /**
2005      * Method to load and return a model object.
2006      *
2007      * @param   string  $name    The name of the view
2008      * @param   string  $prefix  The class prefix. Optional.
2009      * @param   array   $config  The configuration array to pass to the table
2010      *
2011      * @return  FOFTable  Table object or boolean false if failed
2012      */
2013     protected function &_createTable($name, $prefix = 'Table', $config = array())
2014     {
2015         // Make sure $config is an array
2016         if (is_object($config))
2017         {
2018             $config = (array) $config;
2019         }
2020         elseif (!is_array($config))
2021         {
2022             $config = array();
2023         }
2024 
2025         $result = null;
2026 
2027         // Clean the model name
2028         $name   = preg_replace('/[^A-Z0-9_]/i', '', $name);
2029         $prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
2030 
2031         // Make sure we are returning a DBO object
2032         if (!array_key_exists('dbo', $config))
2033         {
2034             $config['dbo'] = $this->getDBO();
2035         }
2036 
2037         $instance = FOFTable::getAnInstance($name, $prefix, $config);
2038 
2039         return $instance;
2040     }
2041 
2042     /**
2043      * Creates the WHERE part of the reorder query
2044      *
2045      * @return  string
2046      */
2047     public function getReorderWhere()
2048     {
2049         return '';
2050     }
2051 
2052     /**
2053      * Builds the SELECT query
2054      *
2055      * @param   boolean  $overrideLimits  Are we requested to override the set limits?
2056      *
2057      * @return  FOFDatabaseQuery
2058      */
2059     public function buildQuery($overrideLimits = false)
2060     {
2061         $table = $this->getTable();
2062         $tableName = $table->getTableName();
2063         $tableKey = $table->getKeyName();
2064         $db = $this->getDbo();
2065 
2066         $query = $db->getQuery(true);
2067 
2068         // Call the behaviors
2069         $this->modelDispatcher->trigger('onBeforeBuildQuery', array(&$this, &$query));
2070 
2071         $alias = $this->getTableAlias();
2072 
2073         if ($alias)
2074         {
2075             $alias = ' AS ' . $db->qn($alias);
2076         }
2077         else
2078         {
2079             $alias = '';
2080         }
2081 
2082         $select = $this->getTableAlias() ? $db->qn($this->getTableAlias()) . '.*' : $db->qn($tableName) . '.*';
2083 
2084         $query->select($select)->from($db->qn($tableName) . $alias);
2085 
2086         if (!$overrideLimits)
2087         {
2088             $order = $this->getState('filter_order', null, 'cmd');
2089 
2090             if (!in_array($order, array_keys($table->getData())))
2091             {
2092                 $order = $tableKey;
2093             }
2094 
2095             $order = $db->qn($order);
2096 
2097             if ($alias)
2098             {
2099                 $order = $db->qn($this->getTableAlias()) . '.' . $order;
2100             }
2101 
2102             $dir = strtoupper($this->getState('filter_order_Dir', 'ASC', 'cmd'));
2103             $dir = in_array($dir, array('DESC', 'ASC')) ? $dir : 'ASC';
2104 
2105             // If the table cache is broken you may end up with an empty order by.
2106             if (!empty($order) && ($order != $db->qn('')))
2107             {
2108                 $query->order($order . ' ' . $dir);
2109             }
2110         }
2111 
2112         // Call the behaviors
2113         $this->modelDispatcher->trigger('onAfterBuildQuery', array(&$this, &$query));
2114 
2115         return $query;
2116     }
2117 
2118     /**
2119      * Returns a list of the fields of the table associated with this model
2120      *
2121      * @return  array
2122      */
2123     public function getTableFields()
2124     {
2125         $tableName = $this->getTable()->getTableName();
2126 
2127         if (version_compare(JVERSION, '3.0', 'ge'))
2128         {
2129             $fields = $this->getDbo()->getTableColumns($tableName, true);
2130         }
2131         else
2132         {
2133             $fieldsArray = $this->getDbo()->getTableFields($tableName, true);
2134             $fields = array_shift($fieldsArray);
2135         }
2136 
2137         return $fields;
2138     }
2139 
2140     /**
2141      * Get the alias set for this model's table
2142      *
2143      * @return  string  The table alias
2144      */
2145     public function getTableAlias()
2146     {
2147         return $this->getTable($this->table)->getTableAlias();
2148     }
2149 
2150     /**
2151      * Builds the count query used in getTotal()
2152      *
2153      * @return  boolean
2154      */
2155     public function buildCountQuery()
2156     {
2157         return false;
2158     }
2159 
2160     /**
2161      * Clones the model object and returns the clone
2162      *
2163      * @return  FOFModel
2164      */
2165     public function &getClone()
2166     {
2167         $clone = clone($this);
2168 
2169         return $clone;
2170     }
2171 
2172     /**
2173      * Magic getter; allows to use the name of model state keys as properties
2174      *
2175      * @param   string  $name  The name of the variable to get
2176      *
2177      * @return  mixed  The value of the variable
2178      */
2179     public function __get($name)
2180     {
2181         return $this->getState($name);
2182     }
2183 
2184     /**
2185      * Magic setter; allows to use the name of model state keys as properties
2186      *
2187      * @param   string  $name   The name of the variable
2188      * @param   mixed   $value  The value to set the variable to
2189      *
2190      * @return  void
2191      */
2192     public function __set($name, $value)
2193     {
2194         return $this->setState($name, $value);
2195     }
2196 
2197     /**
2198      * Magic caller; allows to use the name of model state keys as methods to
2199      * set their values.
2200      *
2201      * @param   string  $name       The name of the state variable to set
2202      * @param   mixed   $arguments  The value to set the state variable to
2203      *
2204      * @return  FOFModel  Reference to self
2205      */
2206     public function __call($name, $arguments)
2207     {
2208         $arg1 = array_shift($arguments);
2209         $this->setState($name, $arg1);
2210 
2211         return $this;
2212     }
2213 
2214     /**
2215      * Sets the model state auto-save status. By default the model is set up to
2216      * save its state to the session.
2217      *
2218      * @param   boolean  $newState  True to save the state, false to not save it.
2219      *
2220      * @return  FOFModel  Reference to self
2221      */
2222     public function &savestate($newState)
2223     {
2224         $this->_savestate = $newState ? true : false;
2225 
2226         return $this;
2227     }
2228 
2229     /**
2230      * Initialises the _savestate variable
2231      *
2232      * @param   integer  $defaultSaveState  The default value for the savestate
2233      *
2234      * @return  void
2235      */
2236     public function populateSavestate($defaultSaveState = -999)
2237     {
2238         if (is_null($this->_savestate))
2239         {
2240             $savestate = $this->input->getInt('savestate', $defaultSaveState);
2241 
2242             if ($savestate == -999)
2243             {
2244                 $savestate = true;
2245             }
2246 
2247             $this->savestate($savestate);
2248         }
2249     }
2250 
2251     /**
2252      * Method to auto-populate the model state.
2253      *
2254      * This method should only be called once per instantiation and is designed
2255      * to be called on the first call to the getState() method unless the model
2256      * configuration flag to ignore the request is set.
2257      *
2258      * @return  void
2259      *
2260      * @note    Calling getState in this method will result in recursion.
2261      * @since   12.2
2262      */
2263     protected function populateState()
2264     {
2265     }
2266 
2267     /**
2268      * Applies view access level filtering for the specified user. Useful to
2269      * filter a front-end items listing.
2270      *
2271      * @param   integer  $userID  The user ID to use. Skip it to use the currently logged in user.
2272      *
2273      * @return  FOFModel  Reference to self
2274      */
2275     public function applyAccessFiltering($userID = null)
2276     {
2277         $user = FOFPlatform::getInstance()->getUser($userID);
2278 
2279         $table = $this->getTable();
2280         $accessField = $table->getColumnAlias('access');
2281 
2282         $this->setState($accessField, $user->getAuthorisedViewLevels());
2283 
2284         return $this;
2285     }
2286 
2287     /**
2288      * A method for getting the form from the model.
2289      *
2290      * @param   array    $data      Data for the form.
2291      * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
2292      * @param   boolean  $source    The name of the form. If not set we'll try the form_name state variable or fall back to default.
2293      *
2294      * @return  mixed  A FOFForm object on success, false on failure
2295      *
2296      * @since   2.0
2297      */
2298     public function getForm($data = array(), $loadData = true, $source = null)
2299     {
2300         $this->_formData = $data;
2301 
2302         if (empty($source))
2303         {
2304             $source = $this->getState('form_name', null);
2305         }
2306 
2307         if (empty($source))
2308         {
2309             $source = 'form.' . $this->name;
2310         }
2311 
2312         $name = $this->input->getCmd('option', 'com_foobar') . '.' . $this->name . '.' . $source;
2313 
2314         $options = array(
2315             'control'    => false,
2316             'load_data'  => $loadData,
2317         );
2318 
2319         $this->onBeforeLoadForm($name, $source, $options);
2320 
2321         $form = $this->loadForm($name, $source, $options);
2322 
2323         if ($form instanceof FOFForm)
2324         {
2325             $this->onAfterLoadForm($form, $name, $source, $options);
2326         }
2327 
2328         return $form;
2329     }
2330 
2331     /**
2332      * Method to get a form object.
2333      *
2334      * @param   string          $name       The name of the form.
2335      * @param   string          $source     The form filename (e.g. form.browse)
2336      * @param   array           $options    Optional array of options for the form creation.
2337      * @param   boolean         $clear      Optional argument to force load a new form.
2338      * @param   bool|string     $xpath      An optional xpath to search for the fields.
2339      *
2340      * @return  mixed  FOFForm object on success, False on error.
2341      *
2342      * @throws  Exception
2343      *
2344      * @see     FOFForm
2345      * @since   2.0
2346      */
2347     protected function loadForm($name, $source, $options = array(), $clear = false, $xpath = false)
2348     {
2349         // Handle the optional arguments.
2350         $options['control'] = isset($options['control']) ? $options['control'] : false;
2351 
2352         // Create a signature hash.
2353         $hash = md5($source . serialize($options));
2354 
2355         // Check if we can use a previously loaded form.
2356         if (isset($this->_forms[$hash]) && !$clear)
2357         {
2358             return $this->_forms[$hash];
2359         }
2360 
2361         // Try to find the name and path of the form to load
2362         $formFilename = $this->findFormFilename($source);
2363 
2364         // No form found? Quit!
2365         if ($formFilename === false)
2366         {
2367             return false;
2368         }
2369 
2370         // Set up the form name and path
2371         $source = basename($formFilename, '.xml');
2372         FOFForm::addFormPath(dirname($formFilename));
2373 
2374         // Set up field paths
2375         $option         = $this->input->getCmd('option', 'com_foobar');
2376         $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($option);
2377         $view           = $this->name;
2378         $file_root      = $componentPaths['main'];
2379         $alt_file_root  = $componentPaths['alt'];
2380 
2381         FOFForm::addFieldPath($file_root . '/fields');
2382         FOFForm::addFieldPath($file_root . '/models/fields');
2383         FOFForm::addFieldPath($alt_file_root . '/fields');
2384         FOFForm::addFieldPath($alt_file_root . '/models/fields');
2385 
2386         FOFForm::addHeaderPath($file_root . '/fields/header');
2387         FOFForm::addHeaderPath($file_root . '/models/fields/header');
2388         FOFForm::addHeaderPath($alt_file_root . '/fields/header');
2389         FOFForm::addHeaderPath($alt_file_root . '/models/fields/header');
2390 
2391         // Get the form.
2392         try
2393         {
2394             $form = FOFForm::getInstance($name, $source, $options, false, $xpath);
2395 
2396             if (isset($options['load_data']) && $options['load_data'])
2397             {
2398                 // Get the data for the form.
2399                 $data = $this->loadFormData();
2400             }
2401             else
2402             {
2403                 $data = array();
2404             }
2405 
2406             // Allows data and form manipulation before preprocessing the form
2407             $this->onBeforePreprocessForm($form, $data);
2408 
2409             // Allow for additional modification of the form, and events to be triggered.
2410             // We pass the data because plugins may require it.
2411             $this->preprocessForm($form, $data);
2412 
2413             // Allows data and form manipulation After preprocessing the form
2414             $this->onAfterPreprocessForm($form, $data);
2415 
2416             // Load the data into the form after the plugins have operated.
2417             $form->bind($data);
2418         }
2419         catch (Exception $e)
2420         {
2421             // The above try-catch statement will catch EVERYTHING, even PhpUnit exceptions while testing
2422             if(stripos(get_class($e), 'phpunit') !== false)
2423             {
2424                 throw $e;
2425             }
2426             else
2427             {
2428                 $this->setError($e->getMessage());
2429 
2430                 return false;
2431             }
2432         }
2433 
2434         // Store the form for later.
2435         $this->_forms[$hash] = $form;
2436 
2437         return $form;
2438     }
2439 
2440     /**
2441      * Guesses the best candidate for the path to use for a particular form.
2442      *
2443      * @param   string  $source  The name of the form file to load, without the .xml extension.
2444      * @param   array   $paths   The paths to look into. You can declare this to override the default FOF paths.
2445      *
2446      * @return  mixed  A string if the path and filename of the form to load is found, false otherwise.
2447      *
2448      * @since   2.0
2449      */
2450     public function findFormFilename($source, $paths = array())
2451     {
2452         // TODO Should we read from internal variables instead of the input? With a temp instance we have no input
2453         $option = $this->input->getCmd('option', 'com_foobar');
2454         $view   = $this->name;
2455 
2456         $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($option);
2457         $file_root      = $componentPaths['main'];
2458         $alt_file_root  = $componentPaths['alt'];
2459         $template_root  = FOFPlatform::getInstance()->getTemplateOverridePath($option);
2460 
2461         if (empty($paths))
2462         {
2463             // Set up the paths to look into
2464             // PLEASE NOTE: If you ever change this, please update Model Unit tests, too, since we have to
2465             // copy these default folders (we have to add the protocol for the virtual filesystem)
2466             $paths = array(
2467                 // In the template override
2468                 $template_root . '/' . $view,
2469                 $template_root . '/' . FOFInflector::singularize($view),
2470                 $template_root . '/' . FOFInflector::pluralize($view),
2471                 // In this side of the component
2472                 $file_root . '/views/' . $view . '/tmpl',
2473                 $file_root . '/views/' . FOFInflector::singularize($view) . '/tmpl',
2474                 $file_root . '/views/' . FOFInflector::pluralize($view) . '/tmpl',
2475                 // In the other side of the component
2476                 $alt_file_root . '/views/' . $view . '/tmpl',
2477                 $alt_file_root . '/views/' . FOFInflector::singularize($view) . '/tmpl',
2478                 $alt_file_root . '/views/' . FOFInflector::pluralize($view) . '/tmpl',
2479                 // In the models/forms of this side
2480                 $file_root . '/models/forms',
2481                 // In the models/forms of the other side
2482                 $alt_file_root . '/models/forms',
2483             );
2484         }
2485 
2486         $paths = array_unique($paths);
2487 
2488         // Set up the suffixes to look into
2489         $suffixes = array();
2490         $temp_suffixes = FOFPlatform::getInstance()->getTemplateSuffixes();
2491 
2492         if (!empty($temp_suffixes))
2493         {
2494             foreach ($temp_suffixes as $suffix)
2495             {
2496                 $suffixes[] = $suffix . '.xml';
2497             }
2498         }
2499 
2500         $suffixes[] = '.xml';
2501 
2502         // Look for all suffixes in all paths
2503         $result     = false;
2504         $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
2505 
2506         foreach ($paths as $path)
2507         {
2508             foreach ($suffixes as $suffix)
2509             {
2510                 $filename = $path . '/' . $source . $suffix;
2511 
2512                 if ($filesystem->fileExists($filename))
2513                 {
2514                     $result = $filename;
2515                     break;
2516                 }
2517             }
2518 
2519             if ($result)
2520             {
2521                 break;
2522             }
2523         }
2524 
2525         return $result;
2526     }
2527 
2528     /**
2529      * Method to get the data that should be injected in the form.
2530      *
2531      * @return  array    The default data is an empty array.
2532      *
2533      * @since   2.0
2534      */
2535     protected function loadFormData()
2536     {
2537         if (empty($this->_formData))
2538         {
2539             return array();
2540         }
2541         else
2542         {
2543             return $this->_formData;
2544         }
2545     }
2546 
2547     /**
2548      * Method to allow derived classes to preprocess the form.
2549      *
2550      * @param   FOFForm  $form   A FOFForm object.
2551      * @param   mixed    &$data  The data expected for the form.
2552      * @param   string   $group  The name of the plugin group to import (defaults to "content").
2553      *
2554      * @return  void
2555      *
2556      * @see     FOFFormField
2557      * @since   2.0
2558      * @throws  Exception if there is an error in the form event.
2559      */
2560     protected function preprocessForm(FOFForm &$form, &$data, $group = 'content')
2561     {
2562         // Import the appropriate plugin group.
2563         FOFPlatform::getInstance()->importPlugin($group);
2564 
2565         // Trigger the form preparation event.
2566         $results = FOFPlatform::getInstance()->runPlugins('onContentPrepareForm', array($form, $data));
2567 
2568         // Check for errors encountered while preparing the form.
2569         if (count($results) && in_array(false, $results, true))
2570         {
2571             // Get the last error.
2572             $dispatcher = FOFUtilsObservableDispatcher::getInstance();
2573             $error = $dispatcher->getError();
2574 
2575             if (!($error instanceof Exception))
2576             {
2577                 throw new Exception($error);
2578             }
2579         }
2580     }
2581 
2582     /**
2583      * Method to validate the form data.
2584      *
2585      * @param   FOFForm  $form   The form to validate against.
2586      * @param   array    $data   The data to validate.
2587      * @param   string   $group  The name of the field group to validate.
2588      *
2589      * @return  mixed   Array of filtered data if valid, false otherwise.
2590      *
2591      * @see     JFormRule
2592      * @see     JFilterInput
2593      * @since   2.0
2594      */
2595     public function validateForm($form, $data, $group = null)
2596     {
2597         // Filter and validate the form data.
2598         $data   = $form->filter($data);
2599         $return = $form->validate($data, $group);
2600 
2601         // Check for an error.
2602         if ($return instanceof Exception)
2603         {
2604             $this->setError($return->getMessage());
2605 
2606             return false;
2607         }
2608 
2609         // Check the validation results.
2610         if ($return === false)
2611         {
2612             // Get the validation messages from the form.
2613             foreach ($form->getErrors() as $message)
2614             {
2615                 if ($message instanceof Exception)
2616                 {
2617                     $this->setError($message->getMessage());
2618                 }
2619                 else
2620                 {
2621                     $this->setError($message);
2622                 }
2623             }
2624 
2625             return false;
2626         }
2627 
2628         return $data;
2629     }
2630 
2631     /**
2632      * Allows the manipulation before the form is loaded
2633      *
2634      * @param   string  &$name     The name of the form.
2635      * @param   string  &$source   The form source. Can be XML string if file flag is set to false.
2636      * @param   array   &$options  Optional array of options for the form creation.
2637      * @codeCoverageIgnore
2638      *
2639      * @return  void
2640      */
2641     public function onBeforeLoadForm(&$name, &$source, &$options)
2642     {
2643     }
2644 
2645     /**
2646      * Allows the manipulation after the form is loaded
2647      *
2648      * @param   FOFForm  $form      A FOFForm object.
2649      * @param   string   &$name     The name of the form.
2650      * @param   string   &$source   The form source. Can be XML string if file flag is set to false.
2651      * @param   array    &$options  Optional array of options for the form creation.
2652      * @codeCoverageIgnore
2653      *
2654      * @return  void
2655      */
2656     public function onAfterLoadForm(FOFForm &$form, &$name, &$source, &$options)
2657     {
2658     }
2659 
2660     /**
2661      * Allows data and form manipulation before preprocessing the form
2662      *
2663      * @param   FOFForm  $form    A FOFForm object.
2664      * @param   array    &$data   The data expected for the form.
2665      * @codeCoverageIgnore
2666      *
2667      * @return  void
2668      */
2669     public function onBeforePreprocessForm(FOFForm &$form, &$data)
2670     {
2671     }
2672 
2673     /**
2674      * Allows data and form manipulation after preprocessing the form
2675      *
2676      * @param   FOFForm  $form    A FOFForm object.
2677      * @param   array    &$data   The data expected for the form.
2678      * @codeCoverageIgnore
2679      *
2680      * @return  void
2681      */
2682     public function onAfterPreprocessForm(FOFForm &$form, &$data)
2683     {
2684     }
2685 
2686     /**
2687      * This method can be overriden to automatically do something with the
2688      * list results array. You are supposed to modify the list which was passed
2689      * in the parameters; DO NOT return a new array!
2690      *
2691      * @param   array  &$resultArray  An array of objects, each row representing a record
2692      *
2693      * @return  void
2694      */
2695     protected function onProcessList(&$resultArray)
2696     {
2697     }
2698 
2699     /**
2700      * This method runs after an item has been gotten from the database in a read
2701      * operation. You can modify it before it's returned to the MVC triad for
2702      * further processing.
2703      *
2704      * @param   FOFTable  &$record  The table instance we fetched
2705      *
2706      * @return  void
2707      */
2708     protected function onAfterGetItem(&$record)
2709     {
2710         try
2711         {
2712             // Call the behaviors
2713             $result = $this->modelDispatcher->trigger('onAfterGetItem', array(&$this, &$record));
2714         }
2715         catch (Exception $e)
2716         {
2717             // Oops, an exception occured!
2718             $this->setError($e->getMessage());
2719         }
2720     }
2721 
2722     /**
2723      * This method runs before the $data is saved to the $table. Return false to
2724      * stop saving.
2725      *
2726      * @param   array     &$data   The data to save
2727      * @param   FOFTable  &$table  The table to save the data to
2728      *
2729      * @return  boolean  Return false to prevent saving, true to allow it
2730      */
2731     protected function onBeforeSave(&$data, &$table)
2732     {
2733         // Let's import the plugin only if we're not in CLI (content plugin needs a user)
2734         FOFPlatform::getInstance()->importPlugin('content');
2735 
2736         try
2737         {
2738             // Do I have a new record?
2739             $key = $table->getKeyName();
2740 
2741             $pk = (!empty($data[$key])) ? $data[$key] : 0;
2742 
2743             $this->_isNewRecord = $pk <= 0;
2744 
2745             // Bind the data
2746             $table->bind($data);
2747 
2748             // Call the behaviors
2749             $result = $this->modelDispatcher->trigger('onBeforeSave', array(&$this, &$data));
2750 
2751             if (in_array(false, $result, true))
2752             {
2753                 // Behavior failed, return false
2754                 return false;
2755             }
2756 
2757             // Call the plugin
2758             $name = $this->name;
2759             $result = FOFPlatform::getInstance()->runPlugins($this->event_before_save, array($this->option . '.' . $name, &$table, $this->_isNewRecord));
2760 
2761             if (in_array(false, $result, true))
2762             {
2763                 // Plugin failed, return false
2764                 $this->setError($table->getError());
2765 
2766                 return false;
2767             }
2768         }
2769         catch (Exception $e)
2770         {
2771             // Oops, an exception occured!
2772             $this->setError($e->getMessage());
2773 
2774             return false;
2775         }
2776 
2777         return true;
2778     }
2779 
2780     /**
2781      * This method runs after the data is saved to the $table.
2782      *
2783      * @param   FOFTable  &$table  The table which was saved
2784      *
2785      * @return  boolean
2786      */
2787     protected function onAfterSave(&$table)
2788     {
2789         // Let's import the plugin only if we're not in CLI (content plugin needs a user)
2790 
2791         FOFPlatform::getInstance()->importPlugin('content');
2792 
2793         try
2794         {
2795             // Call the behaviors
2796             $result = $this->modelDispatcher->trigger('onAfterSave', array(&$this));
2797 
2798             if (in_array(false, $result, true))
2799             {
2800                 // Behavior failed, return false
2801                 return false;
2802             }
2803 
2804             $name = $this->name;
2805             FOFPlatform::getInstance()->runPlugins($this->event_after_save, array($this->option . '.' . $name, &$table, $this->_isNewRecord));
2806 
2807             return true;
2808         }
2809         catch (Exception $e)
2810         {
2811             // Oops, an exception occured!
2812             $this->setError($e->getMessage());
2813 
2814             return false;
2815         }
2816     }
2817 
2818     /**
2819      * This method runs before the record with key value of $id is deleted from $table
2820      *
2821      * @param   integer   &$id     The ID of the record being deleted
2822      * @param   FOFTable  &$table  The table instance used to delete the record
2823      *
2824      * @return  boolean
2825      */
2826     protected function onBeforeDelete(&$id, &$table)
2827     {
2828         // Let's import the plugin only if we're not in CLI (content plugin needs a user)
2829 
2830         FOFPlatform::getInstance()->importPlugin('content');
2831 
2832         try
2833         {
2834             $table->load($id);
2835 
2836             // Call the behaviors
2837             $result = $this->modelDispatcher->trigger('onBeforeDelete', array(&$this));
2838 
2839             if (in_array(false, $result, true))
2840             {
2841                 // Behavior failed, return false
2842                 return false;
2843             }
2844 
2845             $name = $this->name;
2846             $context = $this->option . '.' . $name;
2847             $result = FOFPlatform::getInstance()->runPlugins($this->event_before_delete, array($context, $table));
2848 
2849             if (in_array(false, $result, true))
2850             {
2851                 // Plugin failed, return false
2852                 $this->setError($table->getError());
2853 
2854                 return false;
2855             }
2856 
2857             $this->_recordForDeletion = clone $table;
2858         }
2859         catch (Exception $e)
2860         {
2861             // Oops, an exception occured!
2862             $this->setError($e->getMessage());
2863 
2864             return false;
2865         }
2866         return true;
2867     }
2868 
2869     /**
2870      * This method runs after a record with key value $id is deleted
2871      *
2872      * @param   integer  $id  The id of the record which was deleted
2873      *
2874      * @return  boolean  Return false to raise an error, true otherwise
2875      */
2876     protected function onAfterDelete($id)
2877     {
2878         FOFPlatform::getInstance()->importPlugin('content');
2879 
2880         // Call the behaviors
2881         $result = $this->modelDispatcher->trigger('onAfterDelete', array(&$this));
2882 
2883         if (in_array(false, $result, true))
2884         {
2885             // Behavior failed, return false
2886             return false;
2887         }
2888 
2889         try
2890         {
2891             $name = $this->name;
2892             $context = $this->option . '.' . $name;
2893             $result = FOFPlatform::getInstance()->runPlugins($this->event_after_delete, array($context, $this->_recordForDeletion));
2894             unset($this->_recordForDeletion);
2895         }
2896         catch (Exception $e)
2897         {
2898             // Oops, an exception occured!
2899             $this->setError($e->getMessage());
2900 
2901             return false;
2902         }
2903     }
2904 
2905     /**
2906      * This method runs before a record is copied
2907      *
2908      * @param   FOFTable  &$table  The table instance of the record being copied
2909      *
2910      * @return  boolean  True to allow the copy
2911      */
2912     protected function onBeforeCopy(&$table)
2913     {
2914         // Call the behaviors
2915         $result = $this->modelDispatcher->trigger('onBeforeCopy', array(&$this));
2916 
2917         if (in_array(false, $result, true))
2918         {
2919             // Behavior failed, return false
2920             return false;
2921         }
2922 
2923         return true;
2924     }
2925 
2926     /**
2927      * This method runs after a record has been copied
2928      *
2929      * @param   FOFTable  &$table  The table instance of the record which was copied
2930      *
2931      * @return  boolean  True to allow the copy
2932      */
2933     protected function onAfterCopy(&$table)
2934     {
2935         // Call the behaviors
2936         $result = $this->modelDispatcher->trigger('onAfterCopy', array(&$this));
2937 
2938         if (in_array(false, $result, true))
2939         {
2940             // Behavior failed, return false
2941             return false;
2942         }
2943 
2944         return true;
2945     }
2946 
2947     /**
2948      * This method runs before a record is published
2949      *
2950      * @param   FOFTable  &$table  The table instance of the record being published
2951      *
2952      * @return  boolean  True to allow the operation
2953      */
2954     protected function onBeforePublish(&$table)
2955     {
2956         // Call the behaviors
2957         $result = $this->modelDispatcher->trigger('onBeforePublish', array(&$this));
2958 
2959         if (in_array(false, $result, true))
2960         {
2961             // Behavior failed, return false
2962             return false;
2963         }
2964 
2965         return true;
2966     }
2967 
2968     /**
2969      * This method runs after a record has been published
2970      *
2971      * @param   FOFTable  &$table  The table instance of the record which was published
2972      *
2973      * @return  boolean  True to allow the operation
2974      */
2975     protected function onAfterPublish(&$table)
2976     {
2977         // Call the behaviors
2978         $result = $this->modelDispatcher->trigger('onAfterPublish', array(&$this));
2979 
2980         if (in_array(false, $result, true))
2981         {
2982             // Behavior failed, return false
2983             return false;
2984         }
2985 
2986         return true;
2987     }
2988 
2989     /**
2990      * This method runs before a record is hit
2991      *
2992      * @param   FOFTable  &$table  The table instance of the record being hit
2993      *
2994      * @return  boolean  True to allow the operation
2995      */
2996     protected function onBeforeHit(&$table)
2997     {
2998         // Call the behaviors
2999         $result = $this->modelDispatcher->trigger('onBeforeHit', array(&$this));
3000 
3001         if (in_array(false, $result, true))
3002         {
3003             // Behavior failed, return false
3004             return false;
3005         }
3006 
3007         return true;
3008     }
3009 
3010     /**
3011      * This method runs after a record has been hit
3012      *
3013      * @param   FOFTable  &$table  The table instance of the record which was hit
3014      *
3015      * @return  boolean  True to allow the operation
3016      */
3017     protected function onAfterHit(&$table)
3018     {
3019         // Call the behaviors
3020         $result = $this->modelDispatcher->trigger('onAfterHit', array(&$this));
3021 
3022         if (in_array(false, $result, true))
3023         {
3024             // Behavior failed, return false
3025             return false;
3026         }
3027 
3028         return true;
3029     }
3030 
3031     /**
3032      * This method runs before a record is moved
3033      *
3034      * @param   FOFTable  &$table  The table instance of the record being moved
3035      *
3036      * @return  boolean  True to allow the operation
3037      */
3038     protected function onBeforeMove(&$table)
3039     {
3040         // Call the behaviors
3041         $result = $this->modelDispatcher->trigger('onBeforeMove', array(&$this));
3042 
3043         if (in_array(false, $result, true))
3044         {
3045             // Behavior failed, return false
3046             return false;
3047         }
3048 
3049         return true;
3050     }
3051 
3052     /**
3053      * This method runs after a record has been moved
3054      *
3055      * @param   FOFTable  &$table  The table instance of the record which was moved
3056      *
3057      * @return  boolean  True to allow the operation
3058      */
3059     protected function onAfterMove(&$table)
3060     {
3061         // Call the behaviors
3062         $result = $this->modelDispatcher->trigger('onAfterMove', array(&$this));
3063 
3064         if (in_array(false, $result, true))
3065         {
3066             // Behavior failed, return false
3067             return false;
3068         }
3069 
3070         return true;
3071     }
3072 
3073     /**
3074      * This method runs before a table is reordered
3075      *
3076      * @param   FOFTable  &$table  The table instance being reordered
3077      *
3078      * @return  boolean  True to allow the operation
3079      */
3080     protected function onBeforeReorder(&$table)
3081     {
3082         // Call the behaviors
3083         $result = $this->modelDispatcher->trigger('onBeforeReorder', array(&$this));
3084 
3085         if (in_array(false, $result, true))
3086         {
3087             // Behavior failed, return false
3088             return false;
3089         }
3090 
3091         return true;
3092     }
3093 
3094     /**
3095      * This method runs after a table is reordered
3096      *
3097      * @param   FOFTable  &$table  The table instance which was reordered
3098      *
3099      * @return  boolean  True to allow the operation
3100      */
3101     protected function onAfterReorder(&$table)
3102     {
3103         // Call the behaviors
3104         $result = $this->modelDispatcher->trigger('onAfterReorder', array(&$this));
3105 
3106         if (in_array(false, $result, true))
3107         {
3108             // Behavior failed, return false
3109             return false;
3110         }
3111 
3112         return true;
3113     }
3114 
3115     /**
3116      * Method to get the database driver object
3117      *
3118      * @return  FOFDatabaseDriver
3119      */
3120     public function getDbo()
3121     {
3122         return $this->_db;
3123     }
3124 
3125     /**
3126      * Method to get the model name
3127      *
3128      * The model name. By default parsed using the classname or it can be set
3129      * by passing a $config['name'] in the class constructor
3130      *
3131      * @return  string  The name of the model
3132      *
3133      * @throws  Exception
3134      */
3135     public function getName()
3136     {
3137         if (empty($this->name))
3138         {
3139             $r = null;
3140 
3141             if (!preg_match('/Model(.*)/i', get_class($this), $r))
3142             {
3143                 throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
3144             }
3145 
3146             $this->name = strtolower($r[1]);
3147         }
3148 
3149         return $this->name;
3150     }
3151 
3152     /**
3153      * Method to set the database driver object
3154      *
3155      * @param   FOFDatabaseDriver  $db  A FOFDatabaseDriver based object
3156      *
3157      * @return  void
3158      */
3159     public function setDbo($db)
3160     {
3161         $this->_db = $db;
3162     }
3163 
3164     /**
3165      * Method to set model state variables
3166      *
3167      * @param   string  $property  The name of the property.
3168      * @param   mixed   $value     The value of the property to set or null.
3169      *
3170      * @return  mixed  The previous value of the property or null if not set.
3171      */
3172     public function setState($property, $value = null)
3173     {
3174         return $this->state->set($property, $value);
3175     }
3176 
3177     /**
3178      * Clean the cache
3179      *
3180      * @param   string   $group      The cache group
3181      * @param   integer  $client_id  The ID of the client
3182      *
3183      * @return  void
3184      */
3185     protected function cleanCache($group = null, $client_id = 0)
3186     {
3187         $conf         = JFactory::getConfig();
3188         $platformDirs = FOFPlatform::getInstance()->getPlatformBaseDirs();
3189 
3190         $options = array(
3191             'defaultgroup' => ($group) ? $group : (isset($this->option) ? $this->option : JFactory::getApplication()->input->get('option')),
3192             'cachebase'    => ($client_id) ? $platformDirs['admin'] . '/cache' : $conf->get('cache_path', $platformDirs['public'] . '/cache'));
3193 
3194         $cache = JCache::getInstance('callback', $options);
3195         $cache->clean();
3196 
3197         // Trigger the onContentCleanCache event.
3198         FOFPlatform::getInstance()->runPlugins($this->event_clean_cache, $options);
3199     }
3200 
3201     /**
3202      * Set a behavior param
3203      *
3204      * @param   string  $name     The name of the param
3205      * @param   mixed   $value    The param value to set
3206      *
3207      * @return  FOFModel
3208      */
3209     public function setBehaviorParam($name, $value)
3210     {
3211         $this->_behaviorParams[$name] = $value;
3212 
3213         return $this;
3214     }
3215 
3216     /**
3217      * Get a behavior param
3218      *
3219      * @param   string  $name     The name of the param
3220      * @param   mixed   $default  The default value returned if not set
3221      *
3222      * @return  mixed
3223      */
3224     public function getBehaviorParam($name, $default = null)
3225     {
3226         return isset($this->_behaviorParams[$name]) ? $this->_behaviorParams[$name] : $default;
3227     }
3228 
3229     /**
3230      * Set or get the backlisted filters
3231      *
3232      * @param   mixed    $list    A filter or list of filters to backlist. If null return the list of backlisted filter
3233      * @param   boolean  $reset   Reset the blacklist if true
3234      *
3235      * @return  void|array  Return an array of value if $list is null
3236      */
3237     public function blacklistFilters($list = null, $reset = false)
3238     {
3239         if (!isset($list))
3240         {
3241             return $this->getBehaviorParam('blacklistFilters', array());
3242         }
3243 
3244         if (is_string($list))
3245         {
3246             $list = (array) $list;
3247         }
3248 
3249         if (!$reset)
3250         {
3251             $list = array_unique(array_merge($this->getBehaviorParam('blacklistFilters', array()), $list));
3252         }
3253 
3254         $this->setBehaviorParam('blacklistFilters', $list);
3255     }
3256 }
3257 
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.