├── .gitattributes ├── .gitignore ├── .gitmodules ├── .idea ├── .gitignore ├── .name ├── FOF 4.iml ├── codeStyleSettings.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── composerJson.xml ├── copyright │ ├── FOF.xml │ └── profiles_settings.xml ├── cssxfire.xml ├── deployment.xml ├── dictionaries │ └── nicholas.xml ├── encodings.xml ├── inspectionProfiles │ └── Project_Default.xml ├── libraries │ └── Generated_files.xml ├── markdown.xml ├── misc.xml ├── modules.xml ├── phing.xml ├── php-test-framework.xml ├── php.xml ├── phpunit.xml ├── scopes │ ├── Copyright.xml │ ├── Plugin_CSS_Files.xml │ ├── Plugin_JS_Files.xml │ └── scope_settings.xml ├── sqldialects.xml ├── vcs.xml └── watcherTasks.xml ├── .travis.yml ├── CHANGELOG ├── DESCRIPTION.html ├── MIGRATION_3_TO_4.md ├── README.md ├── RELEASENOTES.html ├── TODO.txt ├── Tests ├── Configuration │ ├── ConfigurationTest.php │ └── Domain │ │ ├── AuthenticationTest.php │ │ ├── ContainerTest.php │ │ ├── DispatcherTest.php │ │ ├── ModelsTest.php │ │ └── ViewsTest.php ├── Controller │ ├── ControllerDataprovider.php │ ├── ControllerTest.php │ ├── DataControllerDataprovider.php │ └── DataControllerTest.php ├── Database │ └── InstallerTest.php ├── Date │ ├── TimezoneWranglerProvider.php │ └── TimezoneWranglerTest.php ├── Dispatcher │ ├── DispatcherDataprovider.php │ └── DispatcherTest.php ├── Download │ ├── Adapter │ │ ├── CurlDataprovider.php │ │ ├── CurlTest.php │ │ ├── FopenDataprovider.php │ │ └── FopenTest.php │ ├── DownloadDataprovider.php │ └── DownloadTest.php ├── Encrypt │ ├── AesTest.php │ ├── Base32Test.php │ └── TotpTest.php ├── Event │ ├── DispatcherTest.php │ └── ObserverTest.php ├── Factory │ ├── BasicFactoryDataprovider.php │ ├── BasicFactoryTest.php │ ├── Magic │ │ ├── BaseFactoryTest.php │ │ ├── ControllerFactoryDataprovider.php │ │ ├── ControllerFactoryTest.php │ │ ├── DispatcherFactoryTest.php │ │ └── TranspAuthFactoryTest.php │ ├── MagicFactoryDataprovider.php │ ├── MagicFactoryTest.php │ ├── MagicSwitchFactoryDataprovider.php │ ├── MagicSwitchFactoryTest.php │ ├── SwitchFactoryDataprovider.php │ └── SwitchFactoryTest.php ├── Helpers │ ├── Application │ │ ├── AppWithLanguageFilter.php │ │ ├── MockApplicationBase.php │ │ ├── MockApplicationCli.php │ │ ├── MockApplicationCms.php │ │ ├── MockApplicationWeb.php │ │ ├── MockDocument.php │ │ ├── MockLanguage.php │ │ ├── MockMenu.php │ │ └── MockSession.php │ ├── ApplicationTestCase.php │ ├── ClosureHelper.php │ ├── DatabaseTest.php │ ├── Download │ │ ├── FakeBase.php │ │ ├── FakeCurl.php │ │ ├── FakeCurlImporter.php │ │ ├── FakeFopen.php │ │ ├── FakeFopenImporter.php │ │ └── data.dat │ ├── FOFTestCase.php │ ├── MockSession.php │ ├── ObserverClosure.php │ ├── Platform │ │ └── UserForAdminAuth.php │ ├── ReflectionHelper.php │ ├── TestContainer.php │ ├── TestHelper.php │ ├── TestJoomlaPlatform.php │ ├── Timer │ │ ├── FakeTimer.php │ │ └── FakeTimerImporter.php │ ├── TravisLogger.php │ └── VfsHelper.php ├── IP │ ├── IPHelperTest.php │ └── IpDataprovider.php ├── Inflector │ └── InflectorTest.php ├── Input │ ├── InputProvider.php │ └── InputTest.php ├── Layout │ ├── LayoutFileTest.php │ ├── LayoutFileTestProvider.php │ ├── LayoutHelperTest.php │ └── LayoutHelperTestProvider.php ├── Model │ ├── DataModel │ │ ├── Behaviour │ │ │ ├── AccessDataprovider.php │ │ │ ├── AccessTest.php │ │ │ ├── AssetsDataprovider.php │ │ │ ├── AssetsTest.php │ │ │ ├── ContentHistoryDataprovider.php │ │ │ ├── ContentHistoryTest.php │ │ │ ├── CreatedDataprovider.php │ │ │ ├── CreatedTest.php │ │ │ ├── EnabledDataprovider.php │ │ │ ├── EnabledTest.php │ │ │ ├── FiltersDataprovider.php │ │ │ ├── FiltersTest.php │ │ │ ├── LanguageDataprovider.php │ │ │ ├── LanguageTest.php │ │ │ ├── ModifiedDataprovider.php │ │ │ ├── ModifiedTest.php │ │ │ ├── OwnDataprovider.php │ │ │ ├── OwnTest.php │ │ │ ├── PageParametersToStateDataprovider.php │ │ │ ├── PageParametersToStateTest.php │ │ │ ├── RelationFiltersDataprovider.php │ │ │ ├── RelationFiltersTest.php │ │ │ ├── TagsDataprovider.php │ │ │ └── TagsTest.php │ │ ├── Collection │ │ │ ├── CollectionDataprovider.php │ │ │ └── CollectionTest.php │ │ ├── CrudDataprovider.php │ │ ├── CrudTest.php │ │ ├── Filter │ │ │ ├── AbstractFilterDataprovider.php │ │ │ ├── AbstractFilterTest.php │ │ │ ├── BooleanDataprovider.php │ │ │ ├── BooleanTest.php │ │ │ ├── DateDataprovider.php │ │ │ ├── DateTest.php │ │ │ ├── NumberDataprovider.php │ │ │ ├── NumberTest.php │ │ │ ├── RelationTest.php │ │ │ ├── TextDataprovider.php │ │ │ └── TextTest.php │ │ ├── GenericDataprovider.php │ │ ├── GenericTest.php │ │ ├── MagicMethodsDataprovider.php │ │ ├── MagicMethodsTest.php │ │ ├── PublishDataprovider.php │ │ ├── PublishTest.php │ │ ├── Relation │ │ │ ├── BelongsToDataprovider.php │ │ │ ├── BelongsToManyDataprovider.php │ │ │ ├── BelongsToManyTest.php │ │ │ ├── BelongsToTest.php │ │ │ ├── HasManyDataprovider.php │ │ │ ├── HasManyTest.php │ │ │ ├── RelationDataprovider.php │ │ │ ├── RelationManagerDataprovider.php │ │ │ ├── RelationManagerTest.php │ │ │ └── RelationTest.php │ │ ├── RelationDataprovider.php │ │ ├── RelationTest.php │ │ ├── SpecialColumnsDataprovider.php │ │ └── SpecialColumnsTest.php │ ├── ModelDataprovider.php │ ├── ModelTest.php │ ├── TreeModelDataprovider.php │ └── TreeModelTest.php ├── Platform │ ├── PlatformJoomlaProvider.php │ └── PlatformJoomlaTest.php ├── README.md ├── Stubs │ ├── Controller │ │ ├── ControllerStub.php │ │ └── DataControllerStub.php │ ├── Dispatcher │ │ └── DispatcherStub.php │ ├── Dummyapp │ │ └── Admin │ │ │ └── fof.xml │ ├── Encrypt │ │ └── MockPhpfunc.php │ ├── Event │ │ ├── FirstObserver.php │ │ └── SecondObserver.php │ ├── Fakeapp │ │ ├── Admin │ │ │ ├── Controller │ │ │ │ └── Bare.php │ │ │ ├── Dispatcher │ │ │ │ └── Dispatcher.php │ │ │ ├── TransparentAuthentication │ │ │ │ └── TransparentAuthentication.php │ │ │ ├── View │ │ │ │ ├── Bare │ │ │ │ │ └── Html.php │ │ │ │ └── Foobar │ │ │ │ │ ├── Html.php │ │ │ │ │ └── tmpl │ │ │ │ │ └── default.php │ │ │ └── fof.xml │ │ ├── MagicSite │ │ │ └── index.html │ │ ├── Site │ │ │ ├── Controller │ │ │ │ ├── DefaultDataController.php │ │ │ │ └── Foobars.php │ │ │ ├── Dispatcher │ │ │ │ └── DefaultDispatcher.php │ │ │ ├── Form │ │ │ │ └── Field │ │ │ │ │ ├── Calendar.php │ │ │ │ │ └── Customfield.php │ │ │ ├── Model │ │ │ │ ├── Behaviour │ │ │ │ │ ├── Foofilters.php │ │ │ │ │ └── Nestedset │ │ │ │ │ │ └── NamedBehaviour.php │ │ │ │ ├── Children.php │ │ │ │ ├── Datafoobars.php │ │ │ │ ├── Foobar.php │ │ │ │ ├── Groups.php │ │ │ │ ├── Parents.php │ │ │ │ └── Parts.php │ │ │ ├── Toolbar │ │ │ │ └── Toolbar.php │ │ │ ├── TransparentAuthentication │ │ │ │ └── DefaultTransparentAuthentication.php │ │ │ └── View │ │ │ │ ├── Foobars │ │ │ │ └── Html.php │ │ │ │ └── Parents │ │ │ │ └── Html.php │ │ └── Standalone.php │ ├── Joomla │ │ └── JToolbarHelper.php │ ├── Model │ │ ├── DataModel │ │ │ └── Filter │ │ │ │ └── FilterStub.php │ │ ├── DataModelStub.php │ │ ├── ModelStub.php │ │ ├── RelationStub.php │ │ └── TreeModelStub.php │ ├── Pimple │ │ ├── Invokable.php │ │ ├── NonInvokable.php │ │ ├── PimpleServiceProvider.php │ │ └── Service.php │ ├── Session │ │ └── FakeSession.php │ ├── Toolbar │ │ └── ToolbarStub.php │ ├── Utils │ │ └── IpStub.php │ ├── View │ │ ├── DataView │ │ │ └── RawStub.php │ │ └── ViewStub.php │ └── schema │ │ ├── database.xml │ │ └── schema.xml ├── Template │ └── TemplateTest.php ├── Timer │ └── TimerTest.php ├── Toolbar │ ├── ToolbarDataprovider.php │ └── ToolbarTest.php ├── TransparentAuthentication │ └── TransparentAuthenticationTest.php ├── Utils │ ├── BufferTest.php │ └── CollectionTest.php ├── View │ ├── DataView │ │ ├── RawDataprovider.php │ │ └── RawTest.php │ ├── ViewDataprovider.php │ ├── ViewTemplateFinderProvider.php │ ├── ViewTemplateFinderTest.php │ └── ViewTest.php ├── _data │ ├── configuration │ │ ├── authentication.xml │ │ ├── container.xml │ │ ├── dispatcher.xml │ │ ├── fof.xml │ │ ├── models.xml │ │ └── views.xml │ ├── fake_test_template │ │ ├── html │ │ │ └── com_foobar │ │ │ │ └── css │ │ │ │ └── test.css │ │ ├── index.php │ │ └── media │ │ │ └── com_foobar │ │ │ ├── css │ │ │ └── test.css │ │ │ └── js │ │ │ └── test.js │ ├── installer │ │ ├── pick_right │ │ │ ├── foobar.xml │ │ │ └── mysql.xml │ │ ├── test_canfail.xml │ │ ├── test_equals.xml │ │ ├── test_fail.xml │ │ └── test_type.xml │ └── layout │ │ ├── layouts │ │ └── test │ │ │ ├── bar.fof.php │ │ │ ├── bat.fof.php │ │ │ ├── foo.php │ │ │ └── overridden.php │ │ └── templates │ │ └── system │ │ └── html │ │ └── layouts │ │ └── test │ │ ├── bat.php │ │ ├── baz.fof.php │ │ └── overridden.php ├── bootstrap.php ├── config.dist.php ├── config_travis.php ├── environments.php ├── environments │ └── .gitinclude └── tmp │ └── index.html ├── assets ├── logo-100.png ├── logo.png └── logo.svg ├── build ├── autoloader_for_rector.php ├── build.properties ├── build.xml ├── fakes │ └── MasterFakeClass.php └── templates │ ├── file_fof40.xml │ ├── include.php │ ├── link.php │ ├── release.yaml │ └── version.txt ├── composer.json ├── fof ├── .htaccess ├── Autoloader │ └── Autoloader.php ├── Cli │ ├── Application.php │ ├── Joomla3.php │ ├── Joomla4.php │ ├── Traits │ │ ├── CGIModeAware.php │ │ ├── CustomOptionsAware.php │ │ ├── JoomlaConfigAware.php │ │ ├── MemStatsAware.php │ │ ├── MessageAware.php │ │ └── TimeAgoAware.php │ └── wrong_php.php ├── Configuration │ ├── Configuration.php │ └── Domain │ │ ├── Authentication.php │ │ ├── Container.php │ │ ├── Dispatcher.php │ │ ├── DomainInterface.php │ │ ├── Models.php │ │ └── Views.php ├── Container │ ├── Container.php │ ├── ContainerBase.php │ └── Exception │ │ └── NoComponent.php ├── Controller │ ├── Controller.php │ ├── DataController.php │ ├── Exception │ │ ├── CannotGetName.php │ │ ├── ItemNotFound.php │ │ ├── LockedRecord.php │ │ ├── NotADataModel.php │ │ ├── NotADataView.php │ │ └── TaskNotFound.php │ └── Mixin │ │ └── PredefinedTaskList.php ├── Database │ └── Installer.php ├── Date │ ├── Date.php │ ├── DateDecorator.php │ └── TimezoneWrangler.php ├── Dispatcher │ ├── Dispatcher.php │ ├── Exception │ │ └── AccessForbidden.php │ └── Mixin │ │ └── ViewAliases.php ├── Download │ ├── Adapter │ │ ├── AbstractAdapter.php │ │ ├── Curl.php │ │ └── Fopen.php │ ├── Download.php │ ├── DownloadInterface.php │ └── Exception │ │ └── DownloadError.php ├── Encrypt │ ├── Aes.php │ ├── AesAdapter │ │ ├── AbstractAdapter.php │ │ ├── AdapterInterface.php │ │ └── OpenSSL.php │ ├── Base32.php │ ├── EncryptService.php │ ├── Randval.php │ ├── RandvalInterface.php │ └── Totp.php ├── Event │ ├── Dispatcher.php │ ├── Observable.php │ └── Observer.php ├── Factory │ ├── BasicFactory.php │ ├── Exception │ │ ├── ControllerNotFound.php │ │ ├── DispatcherNotFound.php │ │ ├── ModelNotFound.php │ │ ├── ToolbarNotFound.php │ │ ├── TransparentAuthenticationNotFound.php │ │ └── ViewNotFound.php │ ├── FactoryInterface.php │ ├── Magic │ │ ├── BaseFactory.php │ │ ├── ControllerFactory.php │ │ ├── DispatcherFactory.php │ │ ├── ModelFactory.php │ │ ├── TransparentAuthenticationFactory.php │ │ └── ViewFactory.php │ ├── MagicFactory.php │ ├── MagicSwitchFactory.php │ └── SwitchFactory.php ├── Html │ ├── FEFHelper │ │ ├── BrowseView.php │ │ ├── browse.php │ │ ├── edit.php │ │ └── select.php │ ├── Fields │ │ └── fancyradio.php │ └── SelectOptions.php ├── IP │ └── IPHelper.php ├── Inflector │ └── Inflector.php ├── Input │ └── Input.php ├── InstallScript │ ├── BaseInstaller.php │ ├── Component.php │ ├── Module.php │ └── Plugin.php ├── JoomlaAbstraction │ ├── CacheCleaner.php │ ├── ComponentVersion.php │ └── DynamicGroups.php ├── LICENSE.txt ├── Layout │ ├── LayoutFile.php │ └── LayoutHelper.php ├── Model │ ├── DataModel.php │ ├── DataModel │ │ ├── Behaviour │ │ │ ├── Access.php │ │ │ ├── Assets.php │ │ │ ├── ContentHistory.php │ │ │ ├── Created.php │ │ │ ├── EmptyNonZero.php │ │ │ ├── Enabled.php │ │ │ ├── Filters.php │ │ │ ├── Language.php │ │ │ ├── Modified.php │ │ │ ├── Own.php │ │ │ ├── PageParametersToState.php │ │ │ ├── RelationFilters.php │ │ │ └── Tags.php │ │ ├── Collection.php │ │ ├── Exception │ │ │ ├── BaseException.php │ │ │ ├── CannotLockNotLoadedRecord.php │ │ │ ├── InvalidSearchMethod.php │ │ │ ├── NoAssetKey.php │ │ │ ├── NoContentType.php │ │ │ ├── NoItemsFound.php │ │ │ ├── NoTableColumns.php │ │ │ ├── RecordNotLoaded.php │ │ │ ├── SpecialColumnMissing.php │ │ │ ├── TreeIncompatibleTable.php │ │ │ ├── TreeInvalidLftRgt.php │ │ │ ├── TreeInvalidLftRgtCurrent.php │ │ │ ├── TreeInvalidLftRgtOther.php │ │ │ ├── TreeInvalidLftRgtParent.php │ │ │ ├── TreeInvalidLftRgtSibling.php │ │ │ ├── TreeMethodOnlyAllowedInRoot.php │ │ │ ├── TreeRootNotFound.php │ │ │ ├── TreeUnexpectedPrimaryKey.php │ │ │ └── TreeUnsupportedMethod.php │ │ ├── Filter │ │ │ ├── AbstractFilter.php │ │ │ ├── Boolean.php │ │ │ ├── Date.php │ │ │ ├── Exception │ │ │ │ ├── InvalidFieldObject.php │ │ │ │ └── NoDatabaseObject.php │ │ │ ├── Number.php │ │ │ ├── Relation.php │ │ │ └── Text.php │ │ ├── Relation.php │ │ ├── Relation │ │ │ ├── BelongsTo.php │ │ │ ├── BelongsToMany.php │ │ │ ├── Exception │ │ │ │ ├── ForeignModelNotFound.php │ │ │ │ ├── NewNotSupported.php │ │ │ │ ├── PivotTableNotFound.php │ │ │ │ ├── RelationNotFound.php │ │ │ │ ├── RelationTypeNotFound.php │ │ │ │ └── SaveNotSupported.php │ │ │ ├── HasMany.php │ │ │ └── HasOne.php │ │ └── RelationManager.php │ ├── Exception │ │ └── CannotGetName.php │ ├── Mixin │ │ ├── Assertions.php │ │ ├── DateManipulation.php │ │ ├── Generators.php │ │ ├── ImplodedArrays.php │ │ └── JsonData.php │ ├── Model.php │ └── TreeModel.php ├── Params │ └── Params.php ├── Pimple │ ├── Container.php │ └── ServiceProviderInterface.php ├── Platform │ ├── Base │ │ ├── Filesystem.php │ │ └── Platform.php │ ├── FilesystemInterface.php │ ├── Joomla │ │ ├── Filesystem.php │ │ └── Platform.php │ └── PlatformInterface.php ├── Render │ ├── FEF.php │ ├── Joomla.php │ ├── Joomla3.php │ ├── Joomla4.php │ ├── RenderBase.php │ └── RenderInterface.php ├── Template │ └── Template.php ├── Timer │ └── Timer.php ├── Toolbar │ ├── Exception │ │ ├── MissingAttribute.php │ │ └── UnknownButtonType.php │ └── Toolbar.php ├── TransparentAuthentication │ └── TransparentAuthentication.php ├── Update │ ├── Collection.php │ ├── Extension.php │ ├── Joomla.php │ └── Update.php ├── Utils │ ├── ArrayHelper.php │ ├── Buffer.php │ ├── CliSessionHandler.php │ ├── Collection.php │ ├── FilesCheck.php │ ├── MediaVersion.php │ ├── ModelTypeHints.php │ ├── ViewManifestMigration.php │ └── helpers.php ├── View │ ├── Compiler │ │ ├── Blade.php │ │ └── CompilerInterface.php │ ├── DataView │ │ ├── Csv.php │ │ ├── DataViewInterface.php │ │ ├── Html.php │ │ ├── Json.php │ │ └── Raw.php │ ├── Engine │ │ ├── AbstractEngine.php │ │ ├── BladeEngine.php │ │ ├── CompilingEngine.php │ │ ├── EngineInterface.php │ │ └── PhpEngine.php │ ├── Exception │ │ ├── AccessForbidden.php │ │ ├── CannotGetName.php │ │ ├── EmptyStack.php │ │ ├── ModelNotFound.php │ │ ├── PossiblySuhosin.php │ │ └── UnrecognisedExtension.php │ ├── View.php │ └── ViewTemplateFinder.php ├── ViewTemplates │ └── Common │ │ ├── browse.fef.blade.php │ │ ├── edit.fef.blade.php │ │ ├── user_select.j3.blade.php │ │ ├── user_select.j3.fef.blade.php │ │ ├── user_select.j4.blade.php │ │ ├── user_select.j4.fef.blade.php │ │ └── user_show.fef.blade.php ├── language │ └── index.html ├── script.fof.php ├── sql │ ├── mysql.xml │ ├── postgresql.xml │ └── sqlsrv.xml └── web.config ├── icon.png ├── phpunit-5.phar ├── phpunit.xml ├── plugins └── user │ └── foftoken │ ├── .htaccess │ ├── fields │ ├── fancyradio.php │ └── fofencryptedtoken.php │ ├── foftoken.php │ ├── foftoken.xml │ ├── foftoken │ └── foftoken.xml │ ├── language │ └── .gitinclude │ ├── script.php │ └── web.config ├── rector.php └── translations ├── library └── fof │ └── en-GB │ └── en-GB.lib_fof40.ini └── plugins └── user └── foftoken └── en-GB ├── en-GB.plg_user_foftoken.ini └── en-GB.plg_user_foftoken.sys.ini /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text eol=lf 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.php text eol=lf 7 | *.phps text eol=lf 8 | *.inc text eol=lf 9 | *.js text eol=lf 10 | *.css text eol=lf 11 | *.ini text eol=lf 12 | *.json text eol=lf 13 | *.htm text eol=lf 14 | *.html text eol=lf 15 | *.xml text eol=lf 16 | *.xslt text eol=lf 17 | *.svg text eol=lf 18 | *.txt text eol=lf 19 | *.md text eol=lf 20 | *.sh text eol=lf 21 | CHANGELOG text eol=lf 22 | README text eol=lf 23 | RELEASENOTES text eol=lf 24 | 25 | # Declare files that will always have CRLF line endings on checkout. 26 | *.sln text eol=crlf 27 | 28 | # Denote all files that are truly binary and should not be modified. 29 | *.acorn binary 30 | *.png binary 31 | *.jpg binary 32 | *.jpeg binary 33 | *.z binary 34 | *.gif binary 35 | *.jpa binary 36 | *.jps binary 37 | *.zip binary 38 | *.dll binary 39 | *.exe binary 40 | *.jar binary 41 | *.phar binary 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### phpStorm 2 | .idea/webServers.xml 3 | .idea/sshConfigs.xml 4 | .idea/dataSources.xml 5 | 6 | ### Composer 7 | # We can't include composer.lock since the testing framework dependencies vary by PHP version we are testing against 8 | composer.lock 9 | # The dependencies folder itself 10 | /vendor/ 11 | 12 | ### Automatically generated files 13 | # Library loader 14 | /fof/include.php 15 | /fof/file_fof40.xml 16 | /fof/version.txt 17 | # Internal language symlinks 18 | /fof/language/en-GB 19 | /plugins/user/foftoken/language/** 20 | 21 | ### Release packages 22 | /release/*.zip 23 | 24 | ### Test files 25 | # Temporary Joomla! installations, used by Travis CI 26 | /Tests/environments/** 27 | # Test coverage output files 28 | /Tests/coverage 29 | # Tests configuration 30 | /Tests/config.php 31 | # Log file, used when running tests under Travis CI 32 | /Tests/debug.txt 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Tests/environments/staging"] 2 | path = Tests/environments/staging 3 | url = git@github.com:joomla/joomla-cms.git 4 | branch = staging 5 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | FOF 4 -------------------------------------------------------------------------------- /.idea/FOF 4.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 13 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/composerJson.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/copyright/FOF.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/cssxfire.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/deployment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/dictionaries/nicholas.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/Generated_files.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/markdown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/phing.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | $USER_HOME$/.composer/vendor/bin/phing 14 | 15 | -------------------------------------------------------------------------------- /.idea/php-test-framework.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | -------------------------------------------------------------------------------- /.idea/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/scopes/Copyright.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/scopes/Plugin_CSS_Files.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/scopes/Plugin_JS_Files.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/sqldialects.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | git: 4 | submodules: false 5 | 6 | language: php 7 | php: 8 | - 8.0 9 | - 7.4 10 | - 7.3 11 | - 7.2 12 | 13 | env: 14 | - JVERSION_TEST=staging 15 | 16 | matrix: 17 | fast_finish: true 18 | allow_failures: 19 | - php: 8.0 20 | 21 | branches: 22 | only: 23 | - development 24 | - feature/fof4 25 | - debug-travis 26 | 27 | before_install: 28 | - git clone -b "$JVERSION_TEST" https://github.com/joomla/joomla-cms.git Tests/environments/"$JVERSION_TEST" 29 | 30 | install: 31 | - composer selfupdate 32 | - composer install 33 | 34 | before_script: 35 | - mysql -u root -e 'create database fof_test;' 36 | - mysql -u root -e "CREATE USER 'fof_db'@'localhost' IDENTIFIED BY 'fof';" 37 | - mysql -u root -e "GRANT ALL PRIVILEGES ON fof_test.* TO 'fof_db'@'%' IDENTIFIED BY 'fof';" 38 | - mysql -u root -e "GRANT ALL PRIVILEGES ON fof_test.* TO 'fof_db'@'localhost' IDENTIFIED BY 'fof';" 39 | - mysql -u root -e 'FLUSH PRIVILEGES;' 40 | 41 | after_script: 42 | - cat Tests/debug.txt 43 | 44 | notifications: 45 | email: false 46 | -------------------------------------------------------------------------------- /DESCRIPTION.html: -------------------------------------------------------------------------------- 1 |

2 | Maintenance release. 3 |

-------------------------------------------------------------------------------- /RELEASENOTES.html: -------------------------------------------------------------------------------- 1 |

2 | We regularly release new versions of FOF to fix known issues and introduce new features. You can find 3 | an overview of this version's changes below. 4 |

-------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | [ ] Refactor classes to include parameter and return value type hints 2 | [ ] View 3 | [ ] Engine/ 4 | [ ] DataView/ 5 | [ ] View 6 | [ ] ViewTemplateFinder 7 | [ ] Model 8 | 9 | 10 | [ ] Encrypt: unit test EncryptService 11 | 12 | [ ] Encrypt: can I add Sodium support to replace the defunct mcrypt support? 13 | 14 | [ ] Each renderer should add FEF extensions for the following elements: 15 | 16 | * `@sortgrid` 17 | * `@filedtitle` 18 | * `@modelfilter` 19 | * `@selectfilter` 20 | * `@searchfilter` 21 | 22 | The default implementation can go through JHtml, I guess? 23 | 24 | 25 | [ ] MAYBE Blade keywords for common form elements, e.g @startEditWrapper / @endEditWrapper, @label, @startEditField / @endEditField, @checkBoxField -- defined by each Renderer 26 | 27 | 28 | [ ] Rewrite scaffolding (Layout) to produce Blade templates -------------------------------------------------------------------------------- /Tests/Configuration/ConfigurationTest.php: -------------------------------------------------------------------------------- 1 | 15 | * @covers FOF40\Configuration\Configuration:: 16 | */ 17 | class ConfigurationTest extends FOFTestCase 18 | { 19 | /** @var array The data returned from parsing the XML file, used to test fetching data */ 20 | protected $data = []; 21 | 22 | /** 23 | * @return void 24 | */ 25 | protected function setUp() 26 | { 27 | self::$container->backEndPath = realpath(__DIR__ . '/../_data/configuration'); 28 | } 29 | 30 | /** 31 | * @covers FOF40\Configuration\Configuration::__construct 32 | * @covers FOF40\Configuration\Configuration::parseComponent 33 | * @covers FOF40\Configuration\Configuration::parseComponentArea 34 | * @covers FOF40\Configuration\Configuration::getDomains 35 | * @covers FOF40\Configuration\Configuration::get 36 | * 37 | * @return void 38 | */ 39 | public function testConstructor() 40 | { 41 | $x = self::$container->appConfig; 42 | 43 | $this->assertInstanceOf('\\FOF40\\Configuration\\Configuration', $x, 'Configuration object must be of correct type'); 44 | 45 | $actual = $x->get('models.Orders.field.enabled', null); 46 | 47 | $this->assertEquals('published', $actual, 'get() must return valid domain data'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/Event/ObserverTest.php: -------------------------------------------------------------------------------- 1 | dispatcher); 27 | 28 | $this->assertEquals($dummy, self::$attachArguments); 29 | $this->assertEquals($this->dispatcher, ReflectionHelper::getValue($dummy, 'subject')); 30 | } 31 | 32 | public function testGetObservableEvents() 33 | { 34 | $dummy = new FirstObserver($this->dispatcher); 35 | 36 | $observableEvents = $dummy->getObservableEvents(); 37 | 38 | $this->assertEquals([ 39 | 'returnConditional', 40 | 'identifyYourself', 41 | 'chain', 42 | ], $observableEvents); 43 | } 44 | 45 | protected function setUp() 46 | { 47 | $this->dispatcher = $this->getMockBuilder('\\FOF40\\Event\\Observable') 48 | ->disableOriginalConstructor() 49 | ->setMethods(['attach', 'detach', 'trigger']) 50 | ->getMock(); 51 | 52 | $this->dispatcher 53 | ->method('attach') 54 | ->will($this->returnCallback(function ($arg) { 55 | ObserverTest::$attachArguments = $arg; 56 | })); 57 | 58 | $this->dispatcher 59 | ->method('detach') 60 | ->willReturnSelf(); 61 | 62 | $this->dispatcher 63 | ->method('trigger') 64 | ->willReturn([]); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Tests/Factory/Magic/BaseFactoryTest.php: -------------------------------------------------------------------------------- 1 | 16 | * @covers FOF40\Factory\Magic\BaseFactory:: 17 | * @package FOF40\Tests\Factory 18 | */ 19 | class BaseFactoryTest extends FOFTestCase 20 | { 21 | /** 22 | * @covers FOF40\Factory\Magic\BaseFactory::__construct 23 | */ 24 | public function test__construct() 25 | { 26 | $container = static::$container; 27 | 28 | $factory = $this->getMockForAbstractClass('FOF40\Factory\Magic\BaseFactory', [$container]); 29 | 30 | $this->assertSame($container, ReflectionHelper::getValue($factory, 'container')); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/Helpers/Application/AppWithLanguageFilter.php: -------------------------------------------------------------------------------- 1 | languageFilter = $filter; 18 | } 19 | 20 | public function getLanguageFilter() 21 | { 22 | return $this->languageFilter; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Tests/Helpers/Application/MockApplicationCli.php: -------------------------------------------------------------------------------- 1 | getMockBuilder('\Joomla\CMS\Application\CliApplication') 55 | ->setMethods($methods) 56 | ->setConstructorArgs([]) 57 | ->setMockClassName('') 58 | ->getMock(); 59 | 60 | $mockObject = self::addBehaviours($test, $mockObject, $options); 61 | 62 | return $mockObject; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Tests/Helpers/Application/MockDocument.php: -------------------------------------------------------------------------------- 1 | getMockBuilder('\Joomla\CMS\Document\Document') 35 | ->setMethods($methods) 36 | ->setConstructorArgs([]) 37 | ->setMockClassName('') 38 | ->disableOriginalConstructor() 39 | ->getMock(); 40 | 41 | // Mock selected methods. 42 | $test->assignMockReturns( 43 | $mockObject, [ 44 | 'parse' => $mockObject, 45 | // An additional 'test' method for confirming this object is successfully mocked. 46 | 'test' => 'ok', 47 | ] 48 | ); 49 | 50 | return $mockObject; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tests/Helpers/ApplicationTestCase.php: -------------------------------------------------------------------------------- 1 | platform; 31 | 32 | if ($platform instanceof TestJoomlaPlatform) 33 | { 34 | $platform->reset(); 35 | } 36 | 37 | static::$container = null; 38 | } 39 | 40 | public static function rebuildContainer() 41 | { 42 | static::$container = null; 43 | static::$container = new TestContainer([ 44 | 'componentName' => 'com_fakeapp', 45 | ]); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Tests/Helpers/ClosureHelper.php: -------------------------------------------------------------------------------- 1 | function(){ return 'Foobar'; } 21 | * ) 22 | * 23 | * @param array $methods 24 | */ 25 | public function __construct(array $methods = []) 26 | { 27 | foreach ($methods as $method => $function) 28 | { 29 | $this->mockedMethods[$method] = $function; 30 | } 31 | } 32 | 33 | public function __call($method, $args) 34 | { 35 | if (isset($this->mockedMethods[$method])) 36 | { 37 | $func = $this->mockedMethods[$method]; 38 | 39 | // Let's pass an instance of ourselves, so we can manipulate other closures 40 | array_unshift($args, $this); 41 | 42 | return call_user_func_array($func, $args); 43 | } 44 | 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Tests/Helpers/Download/FakeBase.php: -------------------------------------------------------------------------------- 1 | allowedAuths); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Tests/Helpers/TestContainer.php: -------------------------------------------------------------------------------- 1 | contents. 16 | * Example: 17 | * 18 | * $paths = array( 19 | * 'administrator/components/com_foftest/views/bare', 20 | * 'administrator/components/com_foftest/views/bares', 21 | * 'administrator/components/com_foftest/views/foobar', 22 | * 'administrator/components/com_foftest/views/foobars/metadata.xml' 23 | * ); 24 | * 25 | * $contents = array( 26 | * 'metadata.xml' => 'your content goes here' 27 | * ); 28 | * 29 | * @param array $paths 30 | * @param array $contents 31 | * 32 | * @return array 33 | */ 34 | public static function createArrayDir($paths, $contents = []) 35 | { 36 | $tree = []; 37 | 38 | foreach ($paths as $path) 39 | { 40 | $pathParts = explode('/', $path); 41 | $subTree = [array_pop($pathParts)]; 42 | 43 | if (strpos($subTree[0], '.') !== false) 44 | { 45 | $content = ''; 46 | 47 | if (isset($contents[$subTree[0]])) 48 | { 49 | $content = $contents[$subTree[0]]; 50 | } 51 | 52 | $subTree = [$subTree[0] => $content]; 53 | } 54 | else 55 | { 56 | $subTree = [$subTree[0] => []]; 57 | } 58 | 59 | foreach (array_reverse($pathParts) as $dir) 60 | { 61 | $subTree = [$dir => $subTree]; 62 | } 63 | 64 | $tree = array_merge_recursive($tree, $subTree); 65 | } 66 | 67 | return $tree; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Tests/IP/IPHelperTest.php: -------------------------------------------------------------------------------- 1 | 18 | * @covers \FOF40\IP\IPHelper:: 19 | */ 20 | class IPHelperTest extends FOFTestCase 21 | { 22 | /** 23 | * @group Ip 24 | * @dataProvider \FOF40\Tests\IP\IpDataprovider::getDetectAndCleanIP 25 | */ 26 | public function testDetectAndCleanIP($test, $check) 27 | { 28 | $msg = 'Ip::detectIP %s - Case: ' . $check['case']; 29 | 30 | $ip = new IpStub(); 31 | 32 | $ip::$fakeIP = $test['fakeIP']; 33 | $ip::setUseFirstIpInChain($test['useFirst']); 34 | 35 | $result = $ip::detectAndCleanIP(); 36 | 37 | $this->assertEquals($check['result'], $result, $msg); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Tests/Layout/LayoutFileTestProvider.php: -------------------------------------------------------------------------------- 1 | ['.fof'], 21 | 'template' => 'system', 22 | 'baseDirs' => [ 23 | 'root' => realpath(__DIR__ . '/../_data/layout'), 24 | 'public' => realpath(__DIR__ . '/../_data/layout'), 25 | 'admin' => realpath(__DIR__ . '/../_data/layout/administrator'), 26 | 'tmp' => JoomlaFactory::getConfig()->get('tmp_path'), 27 | 'log' => JoomlaFactory::getConfig()->get('tmp_path'), 28 | ], 29 | ]; 30 | 31 | // $layoutId, $platformSetup, $expectedPath, $message 32 | return [ 33 | ['test.foo', $platformSetup, $fakeBase . '/test/foo.php', 'Getting a simple layout'], 34 | [ 35 | 'test.bar', $platformSetup, $fakeBase . '/test/bar.fof.php', 36 | 'Getting a simple layout with platform extension', 37 | ], 38 | [ 39 | 'test.overridden', $platformSetup, $templateBase . '/test/overridden.php', 40 | 'Getting a simple overridden layout without platform extension', 41 | ], 42 | [ 43 | 'test.baz', $platformSetup, $templateBase . '/test/baz.fof.php', 44 | 'Getting a simple overridden layout with a platform extension', 45 | ], 46 | [ 47 | 'test.bat', $platformSetup, $fakeBase . '/test/bat.fof.php', 48 | 'Platform extension has priority over template override without platform extension', 49 | ], 50 | ]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tests/Layout/LayoutHelperTestProvider.php: -------------------------------------------------------------------------------- 1 | ['.fof'], 24 | 'template' => 'system', 25 | 'baseDirs' => [ 26 | 'root' => realpath(__DIR__ . '/../_data/layout'), 27 | 'public' => realpath(__DIR__ . '/../_data/layout'), 28 | 'admin' => realpath(__DIR__ . '/../_data/layout/administrator'), 29 | 'tmp' => JoomlaFactory::getConfig()->get('tmp_path'), 30 | 'log' => JoomlaFactory::getConfig()->get('tmp_path'), 31 | ], 32 | ]; 33 | 34 | // $layoutId, $platformSetup, $expectedPath, $message 35 | return [ 36 | ['test.foo', $platformSetup, 'FOO', 'Getting a simple layout'], 37 | ['test.bar', $platformSetup, 'BAR.FOF', 'Getting a simple layout with platform extension'], 38 | [ 39 | 'test.overridden', $platformSetup, 'OVERRIDDEN', 40 | 'Getting a simple overridden layout without platform extension', 41 | ], 42 | ['test.baz', $platformSetup, 'BAZ.FOF', 'Getting a simple overridden layout with a platform extension'], 43 | [ 44 | 'test.bat', $platformSetup, 'BAT.FOF', 45 | 'Platform extension has priority over template override without platform extension', 46 | ], 47 | ]; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Behaviour/AccessDataprovider.php: -------------------------------------------------------------------------------- 1 | 'foftest_bare_id', 16 | 'table' => '#__foftest_bares', 17 | ], 18 | [ 19 | 'access' => false, 20 | ], 21 | ]; 22 | 23 | $data[] = [ 24 | [ 25 | 'tableid' => 'foftest_foobar_id', 26 | 'table' => '#__foftest_foobars', 27 | ], 28 | [ 29 | 'access' => true, 30 | ], 31 | ]; 32 | 33 | return $data; 34 | } 35 | 36 | public static function getTestOnAfterLoad() 37 | { 38 | // DataModel has not the access field 39 | $data[] = [ 40 | [ 41 | 'tableid' => 'foftest_bare_id', 42 | 'table' => '#__foftest_bares', 43 | 'mock' => [ 44 | 'userAccess' => '', 45 | 'access' => '', 46 | ], 47 | ], 48 | [ 49 | 'reset' => false, 50 | ], 51 | ]; 52 | 53 | // User has access to the data 54 | $data[] = [ 55 | [ 56 | 'tableid' => 'foftest_foobar_id', 57 | 'table' => '#__foftest_foobars', 58 | 'mock' => [ 59 | 'userAccess' => [10, 5, 1], 60 | 'access' => 10, 61 | ], 62 | ], 63 | [ 64 | 'reset' => false, 65 | ], 66 | ]; 67 | 68 | // No access 69 | $data[] = [ 70 | [ 71 | 'tableid' => 'foftest_foobar_id', 72 | 'table' => '#__foftest_foobars', 73 | 'mock' => [ 74 | 'userAccess' => [5, 1], 75 | 'access' => 10, 76 | ], 77 | ], 78 | [ 79 | 'reset' => true, 80 | ], 81 | ]; 82 | 83 | return $data; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Behaviour/ContentHistoryDataprovider.php: -------------------------------------------------------------------------------- 1 | [ 15 | 'save_history' => 1, 16 | ], 17 | 'check' => [ 18 | 'case' => 'Component enables history saving', 19 | 'store' => 1, 20 | ], 21 | ]; 22 | 23 | $data[] = [ 24 | 'input' => [ 25 | 'save_history' => 0, 26 | ], 27 | 'check' => [ 28 | 'case' => 'Component does not enable history saving', 29 | 'store' => 0, 30 | ], 31 | ]; 32 | 33 | return $data; 34 | } 35 | 36 | public static function getTestOnBeforeDelete() 37 | { 38 | $data[] = [ 39 | 'input' => [ 40 | 'save_history' => 1, 41 | ], 42 | 'check' => [ 43 | 'case' => 'Component enables history saving', 44 | 'delete' => 1, 45 | ], 46 | ]; 47 | 48 | $data[] = [ 49 | 'input' => [ 50 | 'save_history' => 0, 51 | ], 52 | 'check' => [ 53 | 'case' => 'Component does not enable history saving', 54 | 'delete' => 0, 55 | ], 56 | ]; 57 | 58 | return $data; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Behaviour/EnabledDataprovider.php: -------------------------------------------------------------------------------- 1 | '#__foftest_bares', 16 | 'tableid' => 'foftest_bare_id', 17 | ], 18 | [ 19 | 'case' => 'Table without enabled field', 20 | 'count' => 0, 21 | ], 22 | ]; 23 | 24 | $data[] = [ 25 | [ 26 | 'table' => '#__foftest_foobars', 27 | 'tableid' => 'foftest_foobar_id', 28 | ], 29 | [ 30 | 'case' => 'Table with enabled field', 31 | 'count' => 1, 32 | ], 33 | ]; 34 | 35 | return $data; 36 | } 37 | 38 | public static function getTestOnAfterLoad() 39 | { 40 | // DataModel has not the enabled field 41 | $data[] = [ 42 | [ 43 | 'tableid' => 'foftest_bare_id', 44 | 'table' => '#__foftest_bares', 45 | 'mock' => [ 46 | 'enabled' => 0, 47 | ], 48 | ], 49 | [ 50 | 'reset' => false, 51 | ], 52 | ]; 53 | 54 | // Enabled 55 | $data[] = [ 56 | [ 57 | 'tableid' => 'foftest_foobar_id', 58 | 'table' => '#__foftest_foobars', 59 | 'mock' => [ 60 | 'enabled' => 1, 61 | ], 62 | ], 63 | [ 64 | 'reset' => false, 65 | ], 66 | ]; 67 | 68 | // Not enabled 69 | $data[] = [ 70 | [ 71 | 'tableid' => 'foftest_foobar_id', 72 | 'table' => '#__foftest_foobars', 73 | 'mock' => [ 74 | 'enabled' => 0, 75 | ], 76 | ], 77 | [ 78 | 'reset' => true, 79 | ], 80 | ]; 81 | 82 | return $data; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Behaviour/OwnDataprovider.php: -------------------------------------------------------------------------------- 1 | 'foftest_foobar_id', 16 | 'table' => '#__foftest_foobars', 17 | ], 18 | [ 19 | 'case' => 'Table with created_by column', 20 | 'contains' => true, 21 | 'query' => "`created_by` = '99'", 22 | ], 23 | ]; 24 | 25 | $data[] = [ 26 | [ 27 | 'tableid' => 'foftest_bare_id', 28 | 'table' => '#__foftest_bares', 29 | ], 30 | [ 31 | 'case' => 'Table without created_by column', 32 | 'contains' => false, 33 | 'query' => "`created_by` = '99'", 34 | ], 35 | ]; 36 | 37 | return $data; 38 | } 39 | 40 | public static function getTestOnAfterLoad() 41 | { 42 | // DataModel has not the created_by field 43 | $data[] = [ 44 | [ 45 | 'tableid' => 'foftest_bare_id', 46 | 'table' => '#__foftest_bares', 47 | 'mock' => [ 48 | 'created_by' => '', 49 | ], 50 | ], 51 | [ 52 | 'reset' => false, 53 | ], 54 | ]; 55 | 56 | // User has access to the data 57 | $data[] = [ 58 | [ 59 | 'tableid' => 'foftest_foobar_id', 60 | 'table' => '#__foftest_foobars', 61 | 'mock' => [ 62 | 'created_by' => 99, 63 | ], 64 | ], 65 | [ 66 | 'reset' => false, 67 | ], 68 | ]; 69 | 70 | // No access 71 | $data[] = [ 72 | [ 73 | 'tableid' => 'foftest_foobar_id', 74 | 'table' => '#__foftest_foobars', 75 | 'mock' => [ 76 | 'created_by' => 10, 77 | ], 78 | ], 79 | [ 80 | 'reset' => true, 81 | ], 82 | ]; 83 | 84 | return $data; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Filter/BooleanDataprovider.php: -------------------------------------------------------------------------------- 1 | '', 16 | ], 17 | [ 18 | 'case' => 'Empty string', 19 | 'result' => true, 20 | ], 21 | ]; 22 | 23 | $data[] = [ 24 | [ 25 | 'value' => 123, 26 | ], 27 | [ 28 | 'case' => 'Integers', 29 | 'result' => false, 30 | ], 31 | ]; 32 | 33 | $data[] = [ 34 | [ 35 | 'value' => [], 36 | ], 37 | [ 38 | 'case' => 'Empty array', 39 | 'result' => false, 40 | ], 41 | ]; 42 | 43 | $data[] = [ 44 | [ 45 | 'value' => new stdClass(), 46 | ], 47 | [ 48 | 'case' => 'Object', 49 | 'result' => false, 50 | ], 51 | ]; 52 | 53 | $data[] = [ 54 | [ 55 | 'value' => null, 56 | ], 57 | [ 58 | 'case' => 'Null value', 59 | 'result' => true, 60 | ], 61 | ]; 62 | 63 | return $data; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Filter/BooleanTest.php: -------------------------------------------------------------------------------- 1 | 19 | * @covers FOF40\Model\DataModel\Filter\Boolean:: 20 | * @package FOF40\Tests\DataModel\Filter\Boolean 21 | */ 22 | class BooleanTest extends DatabaseTest 23 | { 24 | /** 25 | * @group BooleanFilter 26 | * @group BooleanFilterIsEmpty 27 | * @covers FOF40\Model\DataModel\Filter\Boolean::isEmpty 28 | * @dataProvider BooleanDataprovider::getTestIsEmpty 29 | */ 30 | public function testIsEmpty($test, $check) 31 | { 32 | $msg = 'Boolean::isEmpty %s - Case: ' . $check['case']; 33 | $filter = new Boolean(JoomlaFactory::getDbo(), (object) ['name' => 'test', 'type' => 'tinyint(1)']); 34 | 35 | $result = $filter->isEmpty($test['value']); 36 | 37 | $this->assertEquals($check['result'], $result, sprintf($msg, 'Failed to detect if a variable is empty')); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Filter/TextDataprovider.php: -------------------------------------------------------------------------------- 1 | '', 16 | ], 17 | [ 18 | 'case' => 'Empty value', 19 | 'result' => '', 20 | ], 21 | ]; 22 | 23 | $data[] = [ 24 | [ 25 | 'value' => 'foobar', 26 | ], 27 | [ 28 | 'case' => 'Valid value', 29 | 'result' => "(`test` LIKE '%foobar%')", 30 | ], 31 | ]; 32 | 33 | return $data; 34 | } 35 | 36 | public static function getTestExact() 37 | { 38 | $data[] = [ 39 | [ 40 | 'value' => '', 41 | ], 42 | [ 43 | 'case' => 'Empty value', 44 | 'result' => '', 45 | ], 46 | ]; 47 | 48 | $data[] = [ 49 | [ 50 | 'value' => 'foobar', 51 | ], 52 | [ 53 | 'case' => 'Valid value', 54 | 'result' => "(`test` LIKE 'foobar')", 55 | ], 56 | ]; 57 | 58 | return $data; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Relation/BelongsToDataprovider.php: -------------------------------------------------------------------------------- 1 | null, 16 | 'foreign' => null, 17 | ], 18 | [ 19 | 'case' => 'Local and foreign keys not passed', 20 | 'local' => 'fakeapp_parent_id', 21 | 'foreign' => 'fakeapp_parent_id', 22 | ], 23 | ]; 24 | 25 | $data[] = [ 26 | [ 27 | 'local' => 'local', 28 | 'foreign' => 'foreign', 29 | ], 30 | [ 31 | 'case' => 'Local and foreign keys passed', 32 | 'local' => 'local', 33 | 'foreign' => 'foreign', 34 | ], 35 | ]; 36 | 37 | $data[] = [ 38 | [ 39 | 'local' => 'local', 40 | 'foreign' => null, 41 | ], 42 | [ 43 | 'case' => 'Local key passed, foreign key not passed', 44 | 'local' => 'local', 45 | 'foreign' => 'fakeapp_parent_id', 46 | ], 47 | ]; 48 | 49 | $data[] = [ 50 | [ 51 | 'local' => null, 52 | 'foreign' => 'foreign', 53 | ], 54 | [ 55 | 'case' => 'Local key not passed, foreign key passed', 56 | 'local' => 'fakeapp_parent_id', 57 | 'foreign' => 'foreign', 58 | ], 59 | ]; 60 | 61 | return $data; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Relation/HasManyDataprovider.php: -------------------------------------------------------------------------------- 1 | null, 16 | 'foreign' => null, 17 | ], 18 | [ 19 | 'case' => 'Local and foreign keys not supplied', 20 | 'local' => 'fakeapp_parent_id', 21 | 'foreign' => 'fakeapp_parent_id', 22 | ], 23 | ]; 24 | 25 | $data[] = [ 26 | [ 27 | 'local' => 'local', 28 | 'foreign' => null, 29 | ], 30 | [ 31 | 'case' => 'Local key supplied', 32 | 'local' => 'local', 33 | 'foreign' => 'local', 34 | ], 35 | ]; 36 | 37 | $data[] = [ 38 | [ 39 | 'local' => null, 40 | 'foreign' => 'foreign', 41 | ], 42 | [ 43 | 'case' => 'Foreign key supplied', 44 | 'local' => 'fakeapp_parent_id', 45 | 'foreign' => 'foreign', 46 | ], 47 | ]; 48 | 49 | $data[] = [ 50 | [ 51 | 'local' => 'local', 52 | 'foreign' => 'foreign', 53 | ], 54 | [ 55 | 'case' => 'Local and foreign keys supplied', 56 | 'local' => 'local', 57 | 'foreign' => 'foreign', 58 | ], 59 | ]; 60 | 61 | return $data; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Tests/Model/DataModel/Relation/RelationDataprovider.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'filter' => true, 17 | 'data' => null, 18 | ], 19 | ], 20 | [ 21 | 'case' => 'Data is filtered', 22 | 'applyCallback' => true, 23 | 'count' => 3, 24 | ], 25 | ]; 26 | 27 | $data[] = [ 28 | [ 29 | 'mock' => [ 30 | 'filter' => false, 31 | 'data' => null, 32 | ], 33 | ], 34 | [ 35 | 'case' => 'Data is not filtered', 36 | 'applyCallback' => false, 37 | 'count' => 0, 38 | ], 39 | ]; 40 | 41 | $data[] = [ 42 | [ 43 | 'mock' => [ 44 | 'filter' => true, 45 | 'data' => new \FOF40\Model\DataModel\Collection([1]), 46 | ], 47 | ], 48 | [ 49 | 'case' => 'Data fetched from the internal cache', 50 | 'applyCallback' => false, 51 | 'count' => 1, 52 | ], 53 | ]; 54 | 55 | return $data; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Tests/README.md: -------------------------------------------------------------------------------- 1 | # Running tests 2 | In order to run the tests, you have to configure your environment: 3 | 4 | 1. Create a database for the tests 5 | 2. Install required libraries with Composer 6 | 7 | ### Create a database for the tests 8 | 9 | We need a database where we will create all the tables required by the tests. 10 | The best thing is to provide an empty database, the test suite will create all the needed tables. 11 | 12 | Once created, you have to copy the file `Tests/config.dist.php`, rename it to `Tests/config.php` and update its contents to point to the created database. 13 | 14 | For local testing (not using Travis CI) you need to put the latest Joomla! staging files somewhere and update the `site_root` line in your `Tests/config.php` file to point there. You do not need to install Joomla on that folder, this is automatically detected and done as part of the tests. 15 | 16 | ### Install required libraries with Composer 17 | 18 | You simply have to run `composer install` in order to install all the required libraries. If you want to update the composer dependencies, run `composer update`. Composer is not bundled in the repo. 19 | 20 | ### How to run tests 21 | 22 | From the `Tests` folder run 23 | ```bash 24 | ../vendor/bin/phpunit -c ../phpunit.xml 25 | ``` 26 | -------------------------------------------------------------------------------- /Tests/Stubs/Controller/DataControllerStub.php: -------------------------------------------------------------------------------- 1 | function(){ return 'Foobar'; } 25 | * ) 26 | * 27 | * @param $container 28 | * @param array $config 29 | * @param array $methods 30 | */ 31 | public function __construct(Container $container, array $config = [], array $methods = []) 32 | { 33 | foreach ($methods as $method => $function) 34 | { 35 | $this->mockedMethods[$method] = $function; 36 | } 37 | 38 | parent::__construct($container, $config); 39 | } 40 | 41 | public function __call($method, $args) 42 | { 43 | if (isset($this->mockedMethods[$method])) 44 | { 45 | $func = $this->mockedMethods[$method]; 46 | 47 | // Let's pass an instance of ourself, so we can manipulate other closures 48 | array_unshift($args, $this); 49 | 50 | return call_user_func_array($func, $args); 51 | } 52 | } 53 | 54 | /** 55 | * A mocked object will have a random name, that won't match the regex expression in the parent. 56 | * To prevent exceptions, we have to manually set the name 57 | * 58 | * @return string 59 | */ 60 | public function getName(): string 61 | { 62 | if (isset($this->mockedMethods['getName'])) 63 | { 64 | $func = $this->mockedMethods['getName']; 65 | 66 | return call_user_func_array($func, []); 67 | } 68 | 69 | return parent::getName(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Tests/Stubs/Dummyapp/Admin/fof.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | read 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Tests/Stubs/Event/FirstObserver.php: -------------------------------------------------------------------------------- 1 | myId); 20 | } 21 | 22 | public function identifyYourself() 23 | { 24 | return $this->myId; 25 | } 26 | 27 | public function chain($stuff) 28 | { 29 | if ($stuff == $this->myId) 30 | { 31 | return $this->myId; 32 | } 33 | 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Tests/Stubs/Event/SecondObserver.php: -------------------------------------------------------------------------------- 1 | myId = 'two'; 20 | } 21 | 22 | public function onlySecond() 23 | { 24 | return 'only second'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Tests/Stubs/Fakeapp/Admin/Controller/Bare.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /Tests/Stubs/Fakeapp/Site/Controller/DefaultDataController.php: -------------------------------------------------------------------------------- 1 | 'First item', 36 | 'second' => 'Second item', 37 | '1' => 'JYES', 38 | '0' => 'JNO', 39 | ]; 40 | 41 | return $options; 42 | } 43 | 44 | /** 45 | * This method is used in {@link GenericListTest::testGetOptions} to test fetching the options 46 | * from a class method 47 | */ 48 | public static function getOptionsWithKeys() 49 | { 50 | $options = [ 51 | ['value' => 'first', 'text' => 'First item'], 52 | ['value' => 'second', 'text' => 'Second item'], 53 | ]; 54 | 55 | return $options; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Tests/Stubs/Fakeapp/Site/Model/Groups.php: -------------------------------------------------------------------------------- 1 | 'First item', 35 | 'second' => 'Second item', 36 | ]; 37 | 38 | return $options; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Tests/Stubs/Joomla/JToolbarHelper.php: -------------------------------------------------------------------------------- 1 | value = $value; 40 | 41 | return $service; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/Stubs/Pimple/NonInvokable.php: -------------------------------------------------------------------------------- 1 | 36 | */ 37 | class Service 38 | { 39 | public $value; 40 | } 41 | -------------------------------------------------------------------------------- /Tests/Stubs/Session/FakeSession.php: -------------------------------------------------------------------------------- 1 | id; 28 | } 29 | 30 | public function setId($id) 31 | { 32 | $this->id = $id; 33 | } 34 | 35 | public function getName() 36 | { 37 | return $this->name; 38 | } 39 | 40 | public function setName($name) 41 | { 42 | return $this->name; 43 | } 44 | 45 | public function regenerate($destroy = false, $lifetime = null) 46 | { 47 | return true; 48 | } 49 | 50 | public function save() 51 | { 52 | } 53 | 54 | public function clear() 55 | { 56 | } 57 | } -------------------------------------------------------------------------------- /Tests/Stubs/Toolbar/ToolbarStub.php: -------------------------------------------------------------------------------- 1 | methodCounter['onFoobarsDummy'])) 21 | { 22 | $this->methodCounter['onFoobarsDummy']++; 23 | } 24 | else 25 | { 26 | $this->methodCounter['onFoobarsDummy'] = 1; 27 | } 28 | } 29 | 30 | public function onViews() 31 | { 32 | if (isset($this->methodCounter['onViews'])) 33 | { 34 | $this->methodCounter['onViews']++; 35 | } 36 | else 37 | { 38 | $this->methodCounter['onViews'] = 1; 39 | } 40 | } 41 | 42 | public function onTask() 43 | { 44 | if (isset($this->methodCounter['onTask'])) 45 | { 46 | $this->methodCounter['onTask']++; 47 | } 48 | else 49 | { 50 | $this->methodCounter['onTask'] = 1; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Tests/Stubs/Utils/IpStub.php: -------------------------------------------------------------------------------- 1 | function(){ return 'Foobar'; } 24 | * ) 25 | * 26 | * @param $container 27 | * @param array $config 28 | * @param array $methods 29 | */ 30 | public function __construct(Container $container, array $config = [], array $methods = []) 31 | { 32 | foreach ($methods as $method => $function) 33 | { 34 | $this->methods[$method] = $function; 35 | } 36 | 37 | parent::__construct($container, $config); 38 | } 39 | 40 | public function __call($method, $args) 41 | { 42 | if (isset($this->methods[$method])) 43 | { 44 | $func = $this->methods[$method]; 45 | 46 | // Let's pass an instance of ourself, so we can manipulate other closures 47 | array_unshift($args, $this); 48 | 49 | return call_user_func_array($func, $args); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tests/View/DataView/RawDataprovider.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'isCli' => false, 17 | ], 18 | ], 19 | [ 20 | 'case' => 'We are not in CLI', 21 | 'permissions' => (object) [ 22 | 'create' => false, 23 | 'edit' => false, 24 | 'editown' => false, 25 | 'editstate' => false, 26 | 'delete' => false, 27 | ], 28 | ], 29 | ]; 30 | 31 | $data[] = [ 32 | [ 33 | 'mock' => [ 34 | 'isCli' => true, 35 | ], 36 | ], 37 | [ 38 | 'case' => 'We are in CLI', 39 | 'permissions' => (object) [ 40 | 'create' => true, 41 | 'edit' => true, 42 | 'editown' => true, 43 | 'editstate' => true, 44 | 'delete' => true, 45 | ], 46 | ], 47 | ]; 48 | 49 | return $data; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Tests/_data/configuration/authentication.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | NOPE 13 | 14 | 15 | -------------------------------------------------------------------------------- /Tests/_data/configuration/container.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | NOPE 13 | 14 | 15 | -------------------------------------------------------------------------------- /Tests/_data/configuration/dispatcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | NOPE 13 | 14 | 15 | -------------------------------------------------------------------------------- /Tests/_data/configuration/models.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | checked_out 12 | checked_out_time 13 | ping,pong 14 | 15 | 16 | 17 | published 18 | 19 | 27 | 28 | foo,bar,baz 29 | 30 | 31 | folks 32 | locked 33 | locked_on 34 | foo,bar,baz 35 | 36 | -------------------------------------------------------------------------------- /Tests/_data/configuration/views.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | browse 12 | 13 | 14 | foobar.something 15 | 16 | 17 |