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

Namespaces

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

Classes

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

Interfaces

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

Exceptions

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

Constants

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

Functions

  • __autoload
  • array_column
  • boolval
  • composerRequire205c915b9c7d3e718e7c95793ee67ffe
  • gzopen
  • gzseek
  • gztell
  • hash_equals
  • hash_pbkdf2
  • HTMLFilter
  • jexit
  • jimport
  • json_last_error_msg
  • ldap_escape
  • password_get_info
  • password_hash
  • password_needs_rehash
  • password_verify
  • PHPMailerAutoload
  • random_bytes
  • random_int
  • RandomCompat_intval
  • RandomCompat_strlen
  • RandomCompat_substr
  • tln_body2div
  • tln_casenormalize
  • tln_deent
  • tln_defang
  • tln_findnxreg
  • tln_findnxstr
  • tln_fixatts
  • tln_fixstyle
  • tln_fixurl
  • tln_getnxtag
  • tln_sanitize
  • tln_skipspace
  • tln_tagprint
  • tln_unspace
  • utf8_accents_to_ascii
  • utf8_bad_explain
  • utf8_bad_find
  • utf8_bad_findall
  • utf8_bad_identify
  • utf8_bad_replace
  • utf8_bad_strip
  • utf8_byte_position
  • utf8_compliant
  • utf8_from_unicode
  • utf8_ireplace
  • utf8_is_ascii
  • utf8_is_ascii_ctrl
  • utf8_is_valid
  • utf8_is_word_chars
  • utf8_locate_current_chr
  • utf8_locate_next_chr
  • utf8_ltrim
  • utf8_ord
  • utf8_rtrim
  • utf8_specials_pattern
  • utf8_str_pad
  • utf8_str_split
  • utf8_strcasecmp
  • utf8_strcspn
  • utf8_strip_ascii_ctrl
  • utf8_strip_non_ascii
  • utf8_strip_non_ascii_ctrl
  • utf8_strip_specials
  • utf8_stristr
  • utf8_strlen
  • utf8_strpos
  • utf8_strrev
  • utf8_strrpos
  • utf8_strspn
  • utf8_strtolower
  • utf8_strtoupper
  • utf8_substr
  • utf8_substr_replace
  • utf8_to_unicode
  • utf8_trim
  • utf8_ucfirst
  • utf8_ucwords
  • utf8_ucwords_callback
   1 <?php
   2 /**
   3  * @package     Joomla.Libraries
   4  * @subpackage  Installer
   5  *
   6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
   7  * @license     GNU General Public License version 2 or later; see LICENSE.txt
   8  */
   9 
  10 defined('JPATH_PLATFORM') or die;
  11 
  12 jimport('joomla.filesystem.folder');
  13 
  14 /**
  15  * Component installer
  16  *
  17  * @since  3.1
  18  */
  19 class JInstallerAdapterComponent extends JInstallerAdapter
  20 {
  21     /**
  22      * The list of current files fo the Joomla! CMS administrator that are installed and is read
  23      * from the manifest on disk in the update area to handle doing a diff
  24      * and deleting files that are in the old files list and not in the new
  25      * files list.
  26      *
  27      * @var    array
  28      * @since  3.1
  29      * */
  30     protected $oldAdminFiles = null;
  31 
  32     /**
  33      * The list of current files that are installed and is read
  34      * from the manifest on disk in the update area to handle doing a diff
  35      * and deleting files that are in the old files list and not in the new
  36      * files list.
  37      *
  38      * @var    array
  39      * @since  3.1
  40      * */
  41     protected $oldFiles = null;
  42 
  43     /**
  44      * A path to the PHP file that the scriptfile declaration in
  45      * the manifest refers to.
  46      *
  47      * @var    string
  48      * @since  3.1
  49      * */
  50     protected $manifest_script = null;
  51 
  52     /**
  53      * For legacy installations this is a path to the PHP file that the scriptfile declaration in the
  54      * manifest refers to.
  55      *
  56      * @var    string
  57      * @since  3.1
  58      * */
  59     protected $install_script = null;
  60 
  61     /**
  62      * Method to check if the extension is present in the filesystem
  63      *
  64      * @return  boolean
  65      *
  66      * @since   3.4
  67      * @throws  RuntimeException
  68      */
  69     protected function checkExtensionInFilesystem()
  70     {
  71         /*
  72          * If the component site or admin directory already exists, then we will assume that the component is already
  73          * installed or another component is using that directory.
  74          */
  75         if (file_exists($this->parent->getPath('extension_site')) || file_exists($this->parent->getPath('extension_administrator')))
  76         {
  77             // Look for an update function or update tag
  78             $updateElement = $this->getManifest()->update;
  79 
  80             // Upgrade manually set or update function available or update tag detected
  81             if ($updateElement || $this->parent->isUpgrade()
  82                 || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')))
  83             {
  84                 // If there is a matching extension mark this as an update
  85                 $this->setRoute('update');
  86             }
  87             elseif (!$this->parent->isOverwrite())
  88             {
  89                 // We didn't have overwrite set, find an update function or find an update tag so lets call it safe
  90                 if (file_exists($this->parent->getPath('extension_site')))
  91                 {
  92                     // If the site exists say so.
  93                     throw new RuntimeException(
  94                         JText::sprintf(
  95                             'JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_SITE',
  96                             $this->parent->getPath('extension_site')
  97                         )
  98                     );
  99                 }
 100 
 101                 // If the admin exists say so
 102                 throw new RuntimeException(
 103                     JText::sprintf(
 104                         'JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_ADMIN',
 105                         $this->parent->getPath('extension_administrator')
 106                     )
 107                 );
 108             }
 109         }
 110 
 111         return false;
 112     }
 113 
 114     /**
 115      * Method to copy the extension's base files from the `<files>` tag(s) and the manifest file
 116      *
 117      * @return  void
 118      *
 119      * @since   3.4
 120      * @throws  RuntimeException
 121      */
 122     protected function copyBaseFiles()
 123     {
 124         // Copy site files
 125         if ($this->getManifest()->files)
 126         {
 127             if ($this->route === 'update')
 128             {
 129                 $result = $this->parent->parseFiles($this->getManifest()->files, 0, $this->oldFiles);
 130             }
 131             else
 132             {
 133                 $result = $this->parent->parseFiles($this->getManifest()->files);
 134             }
 135 
 136             if ($result === false)
 137             {
 138                 throw new RuntimeException(
 139                     JText::sprintf(
 140                         'JLIB_INSTALLER_ABORT_COMP_FAIL_SITE_FILES',
 141                         JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
 142                     )
 143                 );
 144             }
 145         }
 146 
 147         // Copy admin files
 148         if ($this->getManifest()->administration->files)
 149         {
 150             if ($this->route === 'update')
 151             {
 152                 $result = $this->parent->parseFiles($this->getManifest()->administration->files, 1, $this->oldAdminFiles);
 153             }
 154             else
 155             {
 156                 $result = $this->parent->parseFiles($this->getManifest()->administration->files, 1);
 157             }
 158 
 159             if ($result === false)
 160             {
 161                 throw new RuntimeException(
 162                     JText::sprintf(
 163                         'JLIB_INSTALLER_ABORT_COMP_FAIL_ADMIN_FILES',
 164                         JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
 165                     )
 166                 );
 167             }
 168         }
 169 
 170         // If there is a manifest script, let's copy it.
 171         if ($this->manifest_script)
 172         {
 173             $path['src']  = $this->parent->getPath('source') . '/' . $this->manifest_script;
 174             $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $this->manifest_script;
 175 
 176             if ($this->parent->isOverwrite() || !file_exists($path['dest']))
 177             {
 178                 if (!$this->parent->copyFiles(array($path)))
 179                 {
 180                     throw new RuntimeException(
 181                         JText::sprintf(
 182                             'JLIB_INSTALLER_ABORT_COMP_COPY_MANIFEST',
 183                             JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
 184                         )
 185                     );
 186                 }
 187             }
 188         }
 189     }
 190 
 191     /**
 192      * Method to create the extension root path if necessary
 193      *
 194      * @return  void
 195      *
 196      * @since   3.4
 197      * @throws  RuntimeException
 198      */
 199     protected function createExtensionRoot()
 200     {
 201         // If the component directory does not exist, let's create it
 202         $created = false;
 203 
 204         if (!file_exists($this->parent->getPath('extension_site')))
 205         {
 206             if (!$created = JFolder::create($this->parent->getPath('extension_site')))
 207             {
 208                 throw new RuntimeException(
 209                     JText::sprintf(
 210                         'JLIB_INSTALLER_ERROR_COMP_FAILED_TO_CREATE_DIRECTORY',
 211                         JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
 212                         $this->parent->getPath('extension_site')
 213                     )
 214                 );
 215             }
 216         }
 217 
 218         /*
 219          * Since we created the component directory and we will want to remove it if we have to roll back
 220          * the installation, let's add it to the installation step stack
 221          */
 222         if ($created)
 223         {
 224             $this->parent->pushStep(
 225                 array(
 226                     'type' => 'folder',
 227                     'path' => $this->parent->getPath('extension_site'),
 228                 )
 229             );
 230         }
 231 
 232         // If the component admin directory does not exist, let's create it
 233         $created = false;
 234 
 235         if (!file_exists($this->parent->getPath('extension_administrator')))
 236         {
 237             if (!$created = JFolder::create($this->parent->getPath('extension_administrator')))
 238             {
 239                 throw new RuntimeException(
 240                     JText::sprintf(
 241                         'JLIB_INSTALLER_ERROR_COMP_FAILED_TO_CREATE_DIRECTORY',
 242                         JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
 243                         $this->parent->getPath('extension_site')
 244                     )
 245                 );
 246             }
 247         }
 248 
 249         /*
 250          * Since we created the component admin directory and we will want to remove it if we have to roll
 251          * back the installation, let's add it to the installation step stack
 252          */
 253         if ($created)
 254         {
 255             $this->parent->pushStep(
 256                 array(
 257                     'type' => 'folder',
 258                     'path' => $this->parent->getPath('extension_administrator'),
 259                 )
 260             );
 261         }
 262     }
 263 
 264     /**
 265      * Method to finalise the installation processing
 266      *
 267      * @return  void
 268      *
 269      * @since   3.4
 270      * @throws  RuntimeException
 271      */
 272     protected function finaliseInstall()
 273     {
 274         /** @var JTableUpdate $update */
 275         $update = JTable::getInstance('update');
 276 
 277         // Clobber any possible pending updates
 278         $uid = $update->find(
 279             array(
 280                 'element'   => $this->element,
 281                 'type'      => $this->extension->type,
 282                 'client_id' => 1,
 283             )
 284         );
 285 
 286         if ($uid)
 287         {
 288             $update->delete($uid);
 289         }
 290 
 291         // We will copy the manifest file to its appropriate place.
 292         if ($this->route !== 'discover_install')
 293         {
 294             if (!$this->parent->copyManifest())
 295             {
 296                 // Install failed, roll back changes
 297                 throw new RuntimeException(
 298                     JText::sprintf(
 299                         'JLIB_INSTALLER_ABORT_COMP_COPY_SETUP',
 300                         JText::_('JLIB_INSTALLER_' . strtoupper($this->route))
 301                     )
 302                 );
 303             }
 304         }
 305 
 306         // Time to build the admin menus
 307         if (!$this->_buildAdminMenus($this->extension->extension_id))
 308         {
 309             JLog::add(JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED'), JLog::WARNING, 'jerror');
 310         }
 311 
 312         // Make sure that menu items pointing to the component have correct component id assigned to them.
 313         // Prevents message "Component 'com_extension' does not exist." after uninstalling / re-installing component.
 314         if (!$this->_updateMenus($this->extension->extension_id))
 315         {
 316             JLog::add(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATESITEMENUS_FAILED'), JLog::WARNING, 'jerror');
 317         }
 318 
 319         /** @var JTableAsset $asset */
 320         $asset = JTable::getInstance('Asset');
 321 
 322         // Check if an asset already exists for this extension and create it if not
 323         if (!$asset->loadByName($this->extension->element))
 324         {
 325             // Register the component container just under root in the assets table.
 326             $asset->name      = $this->extension->element;
 327             $asset->parent_id = 1;
 328             $asset->rules     = '{}';
 329             $asset->title     = $this->extension->name;
 330             $asset->setLocation(1, 'last-child');
 331 
 332             if (!$asset->store())
 333             {
 334                 // Install failed, roll back changes
 335                 throw new RuntimeException(
 336                     JText::sprintf(
 337                         'JLIB_INSTALLER_ABORT_ROLLBACK',
 338                         JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
 339                         $this->extension->getError()
 340                     )
 341                 );
 342             }
 343         }
 344     }
 345 
 346     /**
 347      * Get the filtered extension element from the manifest
 348      *
 349      * @param   string  $element  Optional element name to be converted
 350      *
 351      * @return  string  The filtered element
 352      *
 353      * @since   3.4
 354      */
 355     public function getElement($element = null)
 356     {
 357         $element = parent::getElement($element);
 358 
 359         if (strpos($element, 'com_') !== 0)
 360         {
 361             $element = 'com_' . $element;
 362         }
 363 
 364         return $element;
 365     }
 366 
 367     /**
 368      * Custom loadLanguage method
 369      *
 370      * @param   string  $path  The path language files are on.
 371      *
 372      * @return  void
 373      *
 374      * @since   3.1
 375      */
 376     public function loadLanguage($path = null)
 377     {
 378         $source = $this->parent->getPath('source');
 379         $client = $this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE;
 380 
 381         if (!$source)
 382         {
 383             $this->parent->setPath('source', $client . '/components/' . $this->parent->extension->element);
 384         }
 385 
 386         $extension = $this->getElement();
 387         $source    = $path ?: $client . '/components/' . $extension;
 388 
 389         if ($this->getManifest()->administration->files)
 390         {
 391             $element = $this->getManifest()->administration->files;
 392         }
 393         elseif ($this->getManifest()->files)
 394         {
 395             $element = $this->getManifest()->files;
 396         }
 397         else
 398         {
 399             $element = null;
 400         }
 401 
 402         if ($element)
 403         {
 404             $folder = (string) $element->attributes()->folder;
 405 
 406             if ($folder && file_exists($path . '/' . $folder))
 407             {
 408                 $source = $path . '/' . $folder;
 409             }
 410         }
 411 
 412         $this->doLoadLanguage($extension, $source);
 413     }
 414 
 415     /**
 416      * Method to parse optional tags in the manifest
 417      *
 418      * @return  void
 419      *
 420      * @since   3.4
 421      */
 422     protected function parseOptionalTags()
 423     {
 424         // Parse optional tags
 425         $this->parent->parseMedia($this->getManifest()->media);
 426         $this->parent->parseLanguages($this->getManifest()->languages);
 427         $this->parent->parseLanguages($this->getManifest()->administration->languages, 1);
 428     }
 429 
 430     /**
 431      * Prepares the adapter for a discover_install task
 432      *
 433      * @return  void
 434      *
 435      * @since   3.4
 436      * @throws  RuntimeException
 437      */
 438     public function prepareDiscoverInstall()
 439     {
 440         // Need to find to find where the XML file is since we don't store this normally
 441         $client = JApplicationHelper::getClientInfo($this->extension->client_id);
 442         $short_element = str_replace('com_', '', $this->extension->element);
 443         $manifestPath = $client->path . '/components/' . $this->extension->element . '/' . $short_element . '.xml';
 444         $this->parent->manifest = $this->parent->isManifest($manifestPath);
 445         $this->parent->setPath('manifest', $manifestPath);
 446         $this->parent->setPath('source', $client->path . '/components/' . $this->extension->element);
 447         $this->parent->setPath('extension_root', $this->parent->getPath('source'));
 448         $this->setManifest($this->parent->getManifest());
 449 
 450         $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
 451         $this->extension->manifest_cache = json_encode($manifest_details);
 452         $this->extension->state = 0;
 453         $this->extension->name = $manifest_details['name'];
 454         $this->extension->enabled = 1;
 455         $this->extension->params = $this->parent->getParams();
 456 
 457         $stored = false;
 458 
 459         try
 460         {
 461             $this->extension->store();
 462             $stored = true;
 463         }
 464         catch (RuntimeException $e)
 465         {
 466             // Try to delete existing failed records before retrying
 467             $db = $this->db;
 468 
 469             $query = $db->getQuery(true)
 470                 ->select($db->qn('extension_id'))
 471                 ->from($db->qn('#__extensions'))
 472                 ->where($db->qn('name') . ' = ' . $db->q($this->extension->name))
 473                 ->where($db->qn('type') . ' = ' . $db->q($this->extension->type))
 474                 ->where($db->qn('element') . ' = ' . $db->q($this->extension->element));
 475 
 476             $db->setQuery($query);
 477 
 478             $extension_ids = $db->loadColumn();
 479 
 480             if (!empty($extension_ids))
 481             {
 482                 foreach ($extension_ids as $eid)
 483                 {
 484                     // Remove leftover admin menus for this extension ID
 485                     $this->_removeAdminMenus($eid);
 486 
 487                     // Remove the extension record itself
 488                     /** @var JTableExtension $extensionTable */
 489                     $extensionTable = JTable::getInstance('extension');
 490                     $extensionTable->delete($eid);
 491                 }
 492             }
 493         }
 494 
 495         if (!$stored)
 496         {
 497             try
 498             {
 499                 $this->extension->store();
 500             }
 501             catch (RuntimeException $e)
 502             {
 503                 throw new RuntimeException(JText::_('JLIB_INSTALLER_ERROR_COMP_DISCOVER_STORE_DETAILS'), $e->getCode(), $e);
 504             }
 505         }
 506     }
 507 
 508     /**
 509      * Method to do any prechecks and setup the install paths for the extension
 510      *
 511      * @return  void
 512      *
 513      * @since   3.4
 514      * @throws  RuntimeException
 515      */
 516     protected function setupInstallPaths()
 517     {
 518         // Set the installation target paths
 519         $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->element));
 520         $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->element));
 521 
 522         // Copy the admin path as it's used as a common base
 523         $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator'));
 524 
 525         // Make sure that we have an admin element
 526         if (!$this->getManifest()->administration)
 527         {
 528             throw new RuntimeException(JText::_('JLIB_INSTALLER_ERROR_COMP_INSTALL_ADMIN_ELEMENT'));
 529         }
 530     }
 531 
 532     /**
 533      * Method to setup the update routine for the adapter
 534      *
 535      * @return  void
 536      *
 537      * @since   3.4
 538      */
 539     protected function setupUpdates()
 540     {
 541         // Hunt for the original XML file
 542         $old_manifest = null;
 543 
 544         // Use a temporary instance due to side effects; start in the administrator first
 545         $tmpInstaller = new JInstaller;
 546         $tmpInstaller->setPath('source', $this->parent->getPath('extension_administrator'));
 547 
 548         if (!$tmpInstaller->findManifest())
 549         {
 550             // Then the site
 551             $tmpInstaller->setPath('source', $this->parent->getPath('extension_site'));
 552 
 553             if ($tmpInstaller->findManifest())
 554             {
 555                 $old_manifest = $tmpInstaller->getManifest();
 556             }
 557         }
 558         else
 559         {
 560             $old_manifest = $tmpInstaller->getManifest();
 561         }
 562 
 563         if ($old_manifest)
 564         {
 565             $this->oldAdminFiles = $old_manifest->administration->files;
 566             $this->oldFiles = $old_manifest->files;
 567         }
 568     }
 569 
 570     /**
 571      * Method to store the extension to the database
 572      *
 573      * @param   bool  $deleteExisting  Should I try to delete existing records of the same component?
 574      *
 575      * @return  void
 576      *
 577      * @since   3.4
 578      * @throws  RuntimeException
 579      */
 580     protected function storeExtension($deleteExisting = false)
 581     {
 582         // The extension is stored during prepareDiscoverInstall for discover installs
 583         if ($this->route === 'discover_install')
 584         {
 585             return;
 586         }
 587 
 588         // Add or update an entry to the extension table
 589         $this->extension->name    = $this->name;
 590         $this->extension->type    = 'component';
 591         $this->extension->element = $this->element;
 592 
 593         // If we are told to delete existing extension entries then do so.
 594         if ($deleteExisting)
 595         {
 596             $db = $this->parent->getDbo();
 597 
 598             $query = $db->getQuery(true)
 599                         ->select($db->qn('extension_id'))
 600                         ->from($db->qn('#__extensions'))
 601                         ->where($db->qn('name') . ' = ' . $db->q($this->extension->name))
 602                         ->where($db->qn('type') . ' = ' . $db->q($this->extension->type))
 603                         ->where($db->qn('element') . ' = ' . $db->q($this->extension->element));
 604 
 605             $db->setQuery($query);
 606 
 607             $extension_ids = $db->loadColumn();
 608 
 609             if (!empty($extension_ids))
 610             {
 611                 foreach ($extension_ids as $eid)
 612                 {
 613                     // Remove leftover admin menus for this extension ID
 614                     $this->_removeAdminMenus($eid);
 615 
 616                     // Remove the extension record itself
 617                     /** @var JTableExtension $extensionTable */
 618                     $extensionTable = JTable::getInstance('extension');
 619                     $extensionTable->delete($eid);
 620                 }
 621             }
 622         }
 623 
 624         // If there is not already a row, generate a heap of defaults
 625         if (!$this->currentExtensionId)
 626         {
 627             $this->extension->folder    = '';
 628             $this->extension->enabled   = 1;
 629             $this->extension->protected = 0;
 630             $this->extension->access    = 0;
 631             $this->extension->client_id = 1;
 632             $this->extension->params    = $this->parent->getParams();
 633             $this->extension->custom_data = '';
 634             $this->extension->system_data = '';
 635         }
 636 
 637         $this->extension->manifest_cache = $this->parent->generateManifestCache();
 638 
 639         $couldStore = $this->extension->store();
 640 
 641         if (!$couldStore && $deleteExisting)
 642         {
 643             // Install failed, roll back changes
 644             throw new RuntimeException(
 645                 JText::sprintf(
 646                     'JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK',
 647                     $this->extension->getError()
 648                 )
 649             );
 650         }
 651 
 652         if (!$couldStore && !$deleteExisting)
 653         {
 654             // Maybe we have a failed installation (e.g. timeout). Let's retry after deleting old records.
 655             $this->storeExtension(true);
 656         }
 657     }
 658 
 659     /**
 660      * Custom uninstall method for components
 661      *
 662      * @param   integer  $id  The unique extension id of the component to uninstall
 663      *
 664      * @return  boolean  True on success
 665      *
 666      * @since   3.1
 667      */
 668     public function uninstall($id)
 669     {
 670         $db     = $this->db;
 671         $retval = true;
 672 
 673         // First order of business will be to load the component object table from the database.
 674         // This should give us the necessary information to proceed.
 675         if (!$this->extension->load((int) $id))
 676         {
 677             JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORUNKOWNEXTENSION'), JLog::WARNING, 'jerror');
 678 
 679             return false;
 680         }
 681 
 682         // Is the component we are trying to uninstall a core one?
 683         // Because that is not a good idea...
 684         if ($this->extension->protected)
 685         {
 686             JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_WARNCORECOMPONENT'), JLog::WARNING, 'jerror');
 687 
 688             return false;
 689         }
 690 
 691         /*
 692          * Does this extension have a parent package?
 693          * If so, check if the package disallows individual extensions being uninstalled if the package is not being uninstalled
 694          */
 695         if ($this->extension->package_id && !$this->parent->isPackageUninstall() && !$this->canUninstallPackageChild($this->extension->package_id))
 696         {
 697             JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_CANNOT_UNINSTALL_CHILD_OF_PACKAGE', $this->extension->name), JLog::WARNING, 'jerror');
 698 
 699             return false;
 700         }
 701 
 702         // Get the admin and site paths for the component
 703         $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->extension->element));
 704         $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->extension->element));
 705 
 706         // Copy the admin path as it's used as a common base
 707         $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator'));
 708 
 709         /**
 710          * ---------------------------------------------------------------------------------------------
 711          * Manifest Document Setup Section
 712          * ---------------------------------------------------------------------------------------------
 713          */
 714 
 715         // Find and load the XML install file for the component
 716         $this->parent->setPath('source', $this->parent->getPath('extension_administrator'));
 717 
 718         // Get the package manifest object
 719         // We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file
 720         $this->parent->findManifest();
 721         $this->setManifest($this->parent->getManifest());
 722 
 723         if (!$this->getManifest())
 724         {
 725             // Make sure we delete the folders if no manifest exists
 726             JFolder::delete($this->parent->getPath('extension_administrator'));
 727             JFolder::delete($this->parent->getPath('extension_site'));
 728 
 729             // Remove the menu
 730             $this->_removeAdminMenus($this->extension->extension_id);
 731 
 732             // Raise a warning
 733             JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORREMOVEMANUALLY'), JLog::WARNING, 'jerror');
 734 
 735             // Return
 736             return false;
 737         }
 738 
 739         // Set the extensions name
 740         $this->set('name', $this->getName());
 741         $this->set('element', $this->getElement());
 742 
 743         // Attempt to load the admin language file; might have uninstall strings
 744         $this->loadLanguage(JPATH_ADMINISTRATOR . '/components/' . $this->element);
 745 
 746         /**
 747          * ---------------------------------------------------------------------------------------------
 748          * Installer Trigger Loading and Uninstall
 749          * ---------------------------------------------------------------------------------------------
 750          */
 751 
 752         $this->setupScriptfile();
 753 
 754         try
 755         {
 756             $this->triggerManifestScript('uninstall');
 757         }
 758         catch (RuntimeException $e)
 759         {
 760             // Ignore errors for now
 761         }
 762 
 763         /**
 764          * ---------------------------------------------------------------------------------------------
 765          * Database Processing Section
 766          * ---------------------------------------------------------------------------------------------
 767          */
 768 
 769         // Let's run the uninstall queries for the component
 770         try
 771         {
 772             $this->parseQueries();
 773         }
 774         catch (RuntimeException $e)
 775         {
 776             JLog::add($e->getMessage(), JLog::WARNING, 'jerror');
 777 
 778             $retval = false;
 779         }
 780 
 781         $this->_removeAdminMenus($this->extension->extension_id);
 782 
 783         /**
 784          * ---------------------------------------------------------------------------------------------
 785          * Filesystem Processing Section
 786          * ---------------------------------------------------------------------------------------------
 787          */
 788 
 789         // Let's remove those language files and media in the JROOT/images/ folder that are
 790         // associated with the component we are uninstalling
 791         $this->parent->removeFiles($this->getManifest()->media);
 792         $this->parent->removeFiles($this->getManifest()->languages);
 793         $this->parent->removeFiles($this->getManifest()->administration->languages, 1);
 794 
 795         // Remove the schema version
 796         $query = $db->getQuery(true)
 797                     ->delete('#__schemas')
 798                     ->where('extension_id = ' . $id);
 799         $db->setQuery($query);
 800         $db->execute();
 801 
 802         // Remove the component container in the assets table.
 803         $asset = JTable::getInstance('Asset');
 804 
 805         if ($asset->loadByName($this->element))
 806         {
 807             $asset->delete();
 808         }
 809 
 810         // Remove categories for this component
 811         $query->clear()
 812             ->delete('#__categories')
 813             ->where('extension=' . $db->quote($this->element), 'OR')
 814             ->where('extension LIKE ' . $db->quote($this->element . '.%'));
 815         $db->setQuery($query);
 816         $db->execute();
 817 
 818         // Rebuild the categories for correct lft/rgt
 819         $category = JTable::getInstance('category');
 820         $category->rebuild();
 821 
 822         // Clobber any possible pending updates
 823         $update = JTable::getInstance('update');
 824         $uid = $update->find(
 825             array(
 826                 'element'   => $this->extension->element,
 827                 'type'      => 'component',
 828                 'client_id' => 1,
 829                 'folder'    => '',
 830             )
 831         );
 832 
 833         if ($uid)
 834         {
 835             $update->delete($uid);
 836         }
 837 
 838         // Now we need to delete the installation directories. This is the final step in uninstalling the component.
 839         if (trim($this->extension->element))
 840         {
 841             // Delete the component site directory
 842             if (is_dir($this->parent->getPath('extension_site')))
 843             {
 844                 if (!JFolder::delete($this->parent->getPath('extension_site')))
 845                 {
 846                     JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_SITE'), JLog::WARNING, 'jerror');
 847                     $retval = false;
 848                 }
 849             }
 850 
 851             // Delete the component admin directory
 852             if (is_dir($this->parent->getPath('extension_administrator')))
 853             {
 854                 if (!JFolder::delete($this->parent->getPath('extension_administrator')))
 855                 {
 856                     JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_ADMIN'), JLog::WARNING, 'jerror');
 857                     $retval = false;
 858                 }
 859             }
 860 
 861             // Now we will no longer need the extension object, so let's delete it
 862             $this->extension->delete($this->extension->extension_id);
 863 
 864             return $retval;
 865         }
 866         else
 867         {
 868             // No component option defined... cannot delete what we don't know about
 869             JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_NO_OPTION'), JLog::WARNING, 'jerror');
 870 
 871             return false;
 872         }
 873     }
 874 
 875     /**
 876      * Method to build menu database entries for a component
 877      *
 878      * @param   int|null  $component_id  The component ID for which I'm building menus
 879      *
 880      * @return  boolean  True if successful
 881      *
 882      * @since   3.1
 883      */
 884     protected function _buildAdminMenus($component_id = null)
 885     {
 886         $db     = $this->parent->getDbo();
 887 
 888         $option = $this->get('element');
 889 
 890         // If a component exists with this option in the table within the protected menutype 'main' then we don't need to add menus
 891         $query = $db->getQuery(true)
 892                     ->select('m.id, e.extension_id')
 893                     ->from('#__menu AS m')
 894                     ->join('LEFT', '#__extensions AS e ON m.component_id = e.extension_id')
 895                     ->where('m.parent_id = 1')
 896                     ->where('m.client_id = 1')
 897                     ->where('m.menutype = ' . $db->quote('main'))
 898                     ->where('e.element = ' . $db->quote($option));
 899 
 900         $db->setQuery($query);
 901 
 902         // In case of a failed installation (e.g. timeout error) we may have duplicate menu item and extension records.
 903         $componentrows = $db->loadObjectList();
 904 
 905         // Check if menu items exist
 906         if (!empty($componentrows))
 907         {
 908             // Don't do anything if overwrite has not been enabled
 909             if (!$this->parent->isOverwrite())
 910             {
 911                 return true;
 912             }
 913 
 914             // Remove all menu items
 915             foreach ($componentrows as $componentrow)
 916             {
 917                 // Remove existing menu items if overwrite has been enabled
 918                 if ($option)
 919                 {
 920                     // If something goes wrong, there's no way to rollback TODO: Search for better solution
 921                     $this->_removeAdminMenus($componentrow->extension_id);
 922                 }
 923             }
 924         }
 925 
 926         // Only try to detect the component ID if it's not provided
 927         if (empty($component_id))
 928         {
 929             // Lets find the extension id
 930             $query->clear()
 931                 ->select('e.extension_id')
 932                 ->from('#__extensions AS e')
 933                 ->where('e.type = ' . $db->quote('component'))
 934                 ->where('e.element = ' . $db->quote($option));
 935 
 936             $db->setQuery($query);
 937             $component_id = $db->loadResult();
 938         }
 939 
 940         // Ok, now its time to handle the menus.  Start with the component root menu, then handle submenus.
 941         $menuElement = $this->getManifest()->administration->menu;
 942 
 943         // Just do not create the menu if $menuElement not exist
 944         if (!$menuElement)
 945         {
 946             return true;
 947         }
 948 
 949         // If the menu item is hidden do nothing more, just return
 950         if (in_array((string) $menuElement['hidden'], array('true', 'hidden')))
 951         {
 952             return true;
 953         }
 954 
 955         // Let's figure out what the menu item data should look like
 956         $data = array();
 957 
 958         if ($menuElement)
 959         {
 960             // I have a menu element, use this information
 961             $data['menutype'] = 'main';
 962             $data['client_id'] = 1;
 963             $data['title'] = (string) trim($menuElement);
 964             $data['alias'] = (string) $menuElement;
 965             $data['link'] = 'index.php?option=' . $option;
 966             $data['type'] = 'component';
 967             $data['published'] = 1;
 968             $data['parent_id'] = 1;
 969             $data['component_id'] = $component_id;
 970             $data['img'] = ((string) $menuElement->attributes()->img) ?: 'class:component';
 971             $data['home'] = 0;
 972             $data['path'] = '';
 973             $data['params'] = '';
 974         }
 975         else
 976         {
 977             // No menu element was specified, Let's make a generic menu item
 978             $data = array();
 979             $data['menutype'] = 'main';
 980             $data['client_id'] = 1;
 981             $data['title'] = $option;
 982             $data['alias'] = $option;
 983             $data['link'] = 'index.php?option=' . $option;
 984             $data['type'] = 'component';
 985             $data['published'] = 1;
 986             $data['parent_id'] = 1;
 987             $data['component_id'] = $component_id;
 988             $data['img'] = 'class:component';
 989             $data['home'] = 0;
 990             $data['path'] = '';
 991             $data['params'] = '';
 992         }
 993 
 994         // Try to create the menu item in the database
 995         $parent_id = $this->_createAdminMenuItem($data, 1);
 996 
 997         if ($parent_id === false)
 998         {
 999             return false;
1000         }
1001 
1002         /*
1003          * Process SubMenus
1004          */
1005 
1006         if (!$this->getManifest()->administration->submenu)
1007         {
1008             // No submenu? We're done.
1009             return true;
1010         }
1011 
1012         foreach ($this->getManifest()->administration->submenu->menu as $child)
1013         {
1014             $data = array();
1015             $data['menutype'] = 'main';
1016             $data['client_id'] = 1;
1017             $data['title'] = (string) trim($child);
1018             $data['alias'] = (string) $child;
1019             $data['type'] = 'component';
1020             $data['published'] = 1;
1021             $data['parent_id'] = $parent_id;
1022             $data['component_id'] = $component_id;
1023             $data['img'] = ((string) $child->attributes()->img) ?: 'class:component';
1024             $data['home'] = 0;
1025 
1026             // Set the sub menu link
1027             if ((string) $child->attributes()->link)
1028             {
1029                 $data['link'] = 'index.php?' . $child->attributes()->link;
1030             }
1031             else
1032             {
1033                 $request = array();
1034 
1035                 if ((string) $child->attributes()->act)
1036                 {
1037                     $request[] = 'act=' . $child->attributes()->act;
1038                 }
1039 
1040                 if ((string) $child->attributes()->task)
1041                 {
1042                     $request[] = 'task=' . $child->attributes()->task;
1043                 }
1044 
1045                 if ((string) $child->attributes()->controller)
1046                 {
1047                     $request[] = 'controller=' . $child->attributes()->controller;
1048                 }
1049 
1050                 if ((string) $child->attributes()->view)
1051                 {
1052                     $request[] = 'view=' . $child->attributes()->view;
1053                 }
1054 
1055                 if ((string) $child->attributes()->layout)
1056                 {
1057                     $request[] = 'layout=' . $child->attributes()->layout;
1058                 }
1059 
1060                 if ((string) $child->attributes()->sub)
1061                 {
1062                     $request[] = 'sub=' . $child->attributes()->sub;
1063                 }
1064 
1065                 $qstring = count($request) ? '&' . implode('&', $request) : '';
1066                 $data['link'] = 'index.php?option=' . $option . $qstring;
1067             }
1068 
1069             $submenuId = $this->_createAdminMenuItem($data, $parent_id);
1070 
1071             if ($submenuId === false)
1072             {
1073                 return false;
1074             }
1075 
1076             /*
1077              * Since we have created a menu item, we add it to the installation step stack
1078              * so that if we have to rollback the changes we can undo it.
1079              */
1080             $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id));
1081         }
1082 
1083         return true;
1084     }
1085 
1086     /**
1087      * Method to remove admin menu references to a component
1088      *
1089      * @param   int  $id  The ID of the extension whose admin menus will be removed
1090      *
1091      * @return  boolean  True if successful.
1092      *
1093      * @since   3.1
1094      */
1095     protected function _removeAdminMenus($id)
1096     {
1097         $db = $this->parent->getDbo();
1098 
1099         /** @var  JTableMenu  $table */
1100         $table = JTable::getInstance('menu');
1101 
1102         // Get the ids of the menu items
1103         $query = $db->getQuery(true)
1104                     ->select('id')
1105                     ->from('#__menu')
1106                     ->where($db->quoteName('client_id') . ' = 1')
1107                     ->where($db->quoteName('menutype') . ' = ' . $db->q('main'))
1108                     ->where($db->quoteName('component_id') . ' = ' . (int) $id);
1109 
1110         $db->setQuery($query);
1111 
1112         $ids = $db->loadColumn();
1113 
1114         $result = true;
1115 
1116         // Check for error
1117         if (!empty($ids))
1118         {
1119             // Iterate the items to delete each one.
1120             foreach ($ids as $menuid)
1121             {
1122                 if (!$table->delete((int) $menuid))
1123                 {
1124                     $this->setError($table->getError());
1125 
1126                     $result = false;
1127                 }
1128             }
1129 
1130             // Rebuild the whole tree
1131             $table->rebuild();
1132         }
1133 
1134         return $result;
1135     }
1136 
1137     /**
1138      * Method to update menu database entries for a component in case the component has been uninstalled before.
1139      * NOTE: This will not update admin menus. Use _updateMenus() instead to update admin menus ase well.
1140      *
1141      * @param   int|null  $component_id  The component ID.
1142      *
1143      * @return  boolean  True if successful
1144      *
1145      * @since   3.4.2
1146      */
1147     protected function _updateSiteMenus($component_id = null)
1148     {
1149         return $this->_updateMenus($component_id, 0);
1150     }
1151 
1152     /**
1153      * Method to update menu database entries for a component in case if the component has been uninstalled before.
1154      *
1155      * @param   int|null  $component_id  The component ID.
1156      * @param   int       $clientId      The client id
1157      *
1158      * @return  boolean  True if successful
1159      *
1160      * @since   3.7.0
1161      */
1162     protected function _updateMenus($component_id, $clientId = null)
1163     {
1164         $db     = $this->parent->getDbo();
1165         $option = $this->get('element');
1166 
1167         // Update all menu items which contain 'index.php?option=com_extension' or 'index.php?option=com_extension&...'
1168         // to use the new component id.
1169         $query = $db->getQuery(true)
1170                     ->update('#__menu')
1171                     ->set('component_id = ' . $db->quote($component_id))
1172                     ->where('type = ' . $db->quote('component'))
1173                     ->where('(' .
1174                         'link LIKE ' . $db->quote('index.php?option=' . $option) . ' OR ' .
1175                         'link LIKE ' . $db->q($db->escape('index.php?option=' . $option . '&') . '%', false) .
1176                     ')');
1177 
1178         if (isset($clientId))
1179         {
1180             $query->where('client_id = ' . (int) $clientId);
1181         }
1182 
1183         $db->setQuery($query);
1184 
1185         try
1186         {
1187             $db->execute();
1188         }
1189         catch (RuntimeException $e)
1190         {
1191             return false;
1192         }
1193 
1194         return true;
1195     }
1196 
1197     /**
1198      * Custom rollback method
1199      * - Roll back the component menu item
1200      *
1201      * @param   array  $step  Installation step to rollback.
1202      *
1203      * @return  boolean  True on success
1204      *
1205      * @since   3.1
1206      */
1207     protected function _rollback_menu($step)
1208     {
1209         return $this->_removeAdminMenus($step['id']);
1210     }
1211 
1212     /**
1213      * Discover unregistered extensions.
1214      *
1215      * @return  array  A list of extensions.
1216      *
1217      * @since   3.1
1218      */
1219     public function discover()
1220     {
1221         $results = array();
1222         $site_components = JFolder::folders(JPATH_SITE . '/components');
1223         $admin_components = JFolder::folders(JPATH_ADMINISTRATOR . '/components');
1224 
1225         foreach ($site_components as $component)
1226         {
1227             if (file_exists(JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml'))
1228             {
1229                 $manifest_details = JInstaller::parseXMLInstallFile(
1230                     JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml'
1231                 );
1232                 $extension = JTable::getInstance('extension');
1233                 $extension->set('type', 'component');
1234                 $extension->set('client_id', 0);
1235                 $extension->set('element', $component);
1236                 $extension->set('folder', '');
1237                 $extension->set('name', $component);
1238                 $extension->set('state', -1);
1239                 $extension->set('manifest_cache', json_encode($manifest_details));
1240                 $extension->set('params', '{}');
1241                 $results[] = $extension;
1242             }
1243         }
1244 
1245         foreach ($admin_components as $component)
1246         {
1247             if (file_exists(JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml'))
1248             {
1249                 $manifest_details = JInstaller::parseXMLInstallFile(
1250                     JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml'
1251                 );
1252                 $extension = JTable::getInstance('extension');
1253                 $extension->set('type', 'component');
1254                 $extension->set('client_id', 1);
1255                 $extension->set('element', $component);
1256                 $extension->set('folder', '');
1257                 $extension->set('name', $component);
1258                 $extension->set('state', -1);
1259                 $extension->set('manifest_cache', json_encode($manifest_details));
1260                 $extension->set('params', '{}');
1261                 $results[] = $extension;
1262             }
1263         }
1264 
1265         return $results;
1266     }
1267 
1268     /**
1269      * Refreshes the extension table cache
1270      *
1271      * @return  boolean  Result of operation, true if updated, false on failure
1272      *
1273      * @since   3.1
1274      */
1275     public function refreshManifestCache()
1276     {
1277         // Need to find to find where the XML file is since we don't store this normally
1278         $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
1279         $short_element = str_replace('com_', '', $this->parent->extension->element);
1280         $manifestPath = $client->path . '/components/' . $this->parent->extension->element . '/' . $short_element . '.xml';
1281         $this->parent->manifest = $this->parent->isManifest($manifestPath);
1282         $this->parent->setPath('manifest', $manifestPath);
1283 
1284         $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
1285         $this->parent->extension->manifest_cache = json_encode($manifest_details);
1286         $this->parent->extension->name = $manifest_details['name'];
1287 
1288         try
1289         {
1290             return $this->parent->extension->store();
1291         }
1292         catch (RuntimeException $e)
1293         {
1294             JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
1295 
1296             return false;
1297         }
1298     }
1299 
1300     /**
1301      * Creates the menu item in the database. If the item already exists it tries to remove it and create it afresh.
1302      *
1303      * @param   array    &$data     The menu item data to create
1304      * @param   integer  $parentId  The parent menu item ID
1305      *
1306      * @return  bool|int  Menu item ID on success, false on failure
1307      */
1308     protected function _createAdminMenuItem(array &$data, $parentId)
1309     {
1310         $db = $this->parent->getDbo();
1311 
1312         /** @var  JTableMenu  $table */
1313         $table  = JTable::getInstance('menu');
1314 
1315         try
1316         {
1317             $table->setLocation($parentId, 'last-child');
1318         }
1319         catch (InvalidArgumentException $e)
1320         {
1321             JLog::add($e->getMessage(), JLog::WARNING, 'jerror');
1322 
1323             return false;
1324         }
1325 
1326         if (!$table->bind($data) || !$table->check() || !$table->store())
1327         {
1328             // The menu item already exists. Delete it and retry instead of throwing an error.
1329             $query = $db->getQuery(true)
1330                         ->select('id')
1331                         ->from('#__menu')
1332                         ->where('menutype = ' . $db->q($data['menutype']))
1333                         ->where('client_id = 1')
1334                         ->where('link = ' . $db->q($data['link']))
1335                         ->where('type = ' . $db->q($data['type']))
1336                         ->where('parent_id = ' . $db->q($data['parent_id']))
1337                         ->where('home = ' . $db->q($data['home']));
1338 
1339             $db->setQuery($query);
1340             $menu_id = $db->loadResult();
1341 
1342             if (!$menu_id)
1343             {
1344                 // Oops! Could not get the menu ID. Go back and rollback changes.
1345                 JError::raiseWarning(1, $table->getError());
1346 
1347                 return false;
1348             }
1349             else
1350             {
1351                 /** @var  JTableMenu $temporaryTable */
1352                 $temporaryTable = JTable::getInstance('menu');
1353                 $temporaryTable->delete($menu_id, true);
1354                 $temporaryTable->rebuild($data['parent_id']);
1355 
1356                 // Retry creating the menu item
1357                 $table->setLocation($parentId, 'last-child');
1358 
1359                 if (!$table->bind($data) || !$table->check() || !$table->store())
1360                 {
1361                     // Install failed, warn user and rollback changes
1362                     JError::raiseWarning(1, $table->getError());
1363 
1364                     return false;
1365                 }
1366             }
1367         }
1368 
1369         return $table->id;
1370     }
1371 }
1372 
1373 /**
1374  * Deprecated class placeholder. You should use JInstallerAdapterComponent instead.
1375  *
1376  * @since       3.1
1377  * @deprecated  4.0
1378  * @codeCoverageIgnore
1379  */
1380 class JInstallerComponent extends JInstallerAdapterComponent
1381 {
1382 }
1383 
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.