diff --git a/.gitignore b/.gitignore
index 8c2fd1f608..3350e520bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,22 +17,34 @@
# More details about excluding specific file on your local environment can be found
# in the official GitHub article: https://help.github.com/articles/ignoring-files/
+/.web-server-pid
+/app/config/parameters.yml
+/build/
+/phpunit.xml
+/var/*
+!/var/cache
+/var/cache/*
+!var/cache/.gitkeep
+!/var/logs
+/var/logs/*
+!var/logs/.gitkeep
+!/var/sessions
+/var/sessions/*
+!var/sessions/.gitkeep
+!var/SymfonyRequirements.php
/vendor/
+/web/bundles/
+
.php~
-/bin/behat
-/bin/phpunit
-/app/check.php
-/app/SymfonyRequirements.php
-/app/cache/
-/app/logs/
+
+# Legacy related ignores, that are generated by composer (settings not handled out of the box)
/ezpublish_legacy
-/app/config/parameters.yml
-/app/bootstrap.php.cache
-/doc/docker/entrypoint/*/*.sql
/web/index_treemenu.php
/web/index_rest.php
/web/index_cluster.php
-/web/bundles/
+
+/doc/docker/entrypoint/*/*.sql
+
/web/css/
/web/js/
web/fonts/
@@ -41,6 +53,7 @@ web/fonts/
/web/share
/web/var
/web/.htaccess
+
composer.phar
composer.lock
.buildpath
diff --git a/.platform.app.yaml b/.platform.app.yaml
index eb10a6a7b1..b6b945b587 100644
--- a/.platform.app.yaml
+++ b/.platform.app.yaml
@@ -36,9 +36,11 @@ disk: 2048
# The mounts that will be performed when the package is deployed.
mounts:
- "/app/cache": "shared:files/cache"
- "/app/logs": "shared:files/logs"
+ "/var/cache": "shared:files/cache"
+ "/var/logs": "shared:files/logs"
"/web/var": "shared:files/files"
+ # Might want to not mount this one, it will slow down sessions, if you need cluster use memcached/redis!
+ "/var/sessions": "shared:files/sessions"
# The hooks that will be performed when the package is deployed.
hooks:
@@ -61,10 +63,10 @@ hooks:
export SYMFONY_ENV=prod
fi
if [ ! -f web/var/.platform.installed ]; then
- php -d memory_limit=-1 app/console ezplatform:install --env=$SYMFONY_ENV $INSTALL_EZ_INSTALL_TYPE
+ php -d memory_limit=-1 bin/console ezplatform:install --env=$SYMFONY_ENV $INSTALL_EZ_INSTALL_TYPE
touch web/var/.platform.installed
fi
- app/console --env=$SYMFONY_ENV cache:clear
+ bin/console --env=$SYMFONY_ENV cache:clear
# The configuration of scheduled execution.
# see http://symfony.com/doc/current/components/console/introduction.html
diff --git a/.travis.yml b/.travis.yml
index 2602a3ddf7..e1b75e66b6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,11 +16,14 @@ env:
- SYMFONY_DEBUG=1
# list of behat arguments to test
matrix:
- - TEST_CMD="bin/behat -vv --profile=rest --suite=fullJson --tags=~@broken" COMPOSE_FILE="doc/docker/base-dev.yml:doc/docker/varnish.yml:doc/docker/selenium.yml" WEB_HOST="varnish"
+ # TMP disable usage of varnish until we figure out segmentation faulty issue on 2.0
+ #- TEST_CMD="bin/behat -vv --profile=rest --suite=fullJson --tags=~@broken" COMPOSE_FILE="doc/docker/base-dev.yml:doc/docker/varnish.yml:doc/docker/selenium.yml" WEB_HOST="varnish"
+ - TEST_CMD="bin/behat -vv --profile=rest --suite=fullJson --tags=~@broken" COMPOSE_FILE="doc/docker/base-dev.yml:doc/docker/selenium.yml"
- TEST_CMD="bin/behat -vv --profile=rest --suite=fullXml --tags=~@broken"
- TEST_CMD="bin/behat -vv --profile=core --tags=~@broken"
- TEST_CMD="bin/phpunit -v vendor/ezsystems/ezpublish-kernel/eZ/Bundle/EzPublishRestBundle/Tests/Functional" SYMFONY_CMD="ez:behat:create-language 'pol-PL' 'Polish (polski)'"
- - TEST_CMD="bin/behat -vv --profile=platformui --tags='@common'" COMPOSE_FILE="doc/docker/base-dev.yml:doc/docker/redis.yml:doc/docker/selenium.yml"
+ - TEST_CMD="bin/behat -v --profile=repository-forms --tags=~@broken" COMPOSE_FILE="doc/docker/base-dev.yml:doc/docker/redis.yml:doc/docker/selenium.yml"
+ - TEST_CMD="bin/behat -v --profile=behat --tags=~@broken"
# test only master (+ Pull requests)
branches:
@@ -34,16 +37,16 @@ before_install: ./bin/.travis/trusty/update_docker.sh
before_script:
# Internal auth token dedicated to testing with travis+composer on ezsystems repos, not for reuse!
- echo "{\"github-oauth\":{\"github.com\":\"d0285ed5c8644f30547572ead2ed897431c1fc09\"}}" > auth.json
- # In case of dev mode we'll need to install composer packages first
- - docker-compose -f doc/docker/install.yml up --abort-on-container-exit
- # Run (start containers and execute install command)
- - docker-compose up -d
+ # Setup eZ Platform inside docker container
+ - /bin/bash ./bin/.travis/trusty/setup_ezplatform.sh "${COMPOSE_FILE}"
+ # Execute Symfony command if injected into test matrix
+ - if [ "${SYMFONY_CMD}" != "" ] ; then docker-compose exec --user www-data app sh -c "bin/console ${SYMFONY_CMD}" ; fi
#- docker ps
#- docker-compose logs
# Execute test command, need to use sh to get right exit code (docker/compose/issues/3379)
# Behat will use behat.yml which is a copy of behat.yml.dist with hostnames update by doc/docker/selenium.yml
-script: docker-compose exec --user www-data app sh -c "php /scripts/wait_for_db.php; php $TEST_CMD"
+script: docker-compose exec --user www-data app sh -c "php $TEST_CMD"
after_failure:
# Will show us the last bit of the log of container's main processes
diff --git a/Dockerfile b/Dockerfile
index 9bff30112e..2e083599ad 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -17,7 +17,8 @@ RUN composer dump-autoload --optimize
# Next, remove everything we don't want to be copied to next build stage
# Clear cache again so env variables are taken into account on startup
-RUN rm -Rf app/logs/* app/cache/*/*
+RUN rm -Rf var/logs/* var/cache/*/*
+
# Looks like we need to keep web/bundles ( like web/bundles/ezstudioui/js/views/ezs-landingpageview.js ) or else
# urls like http://localhost:8080/_ezcombo?/bundles/ezstudioui/js/views/ezs-landingpageview.js&/tpl/handlebars/studiolandingpageconfigview-ez-template.js&/bundles/ezstudioui/js/views/ezs-landingpageconfigview.js&/tpl/handlebars/studiolayoutselectorview-ez-template.js&/bundles/ezstudioui/js/views/ezs-layoutselectorview.js&/tpl/handlebars/studiolandingpageconfigpopupformview-ez-template.js&/bundles/ezstudioui/js/views/forms/ezs-landingpageconfigpopupformview.js&/tpl/handlebars/landingpagecreatorview-ez-template.js&/bundles/ezsystemsformbuilder/js/models/fb-formfield-model.js&/bundles/ezsystemsformbuilder/js/lists/fb-formfields-modellist.js&/bundles/ezsystemsformbuilder/js/models/fb-formpage-model.js&/bundles/ezsystemsformbuilder/js/lists/fb-formpages-modellist.js&/bundles/ezsystemsformbuilder/js/models/fb-form-model.js&/tpl/handlebars/fbbasetabview-ez-template.js&/bundles/ezsystemsformbuilder/js/tabs/fb-base-tabview.js&/tpl/handlebars/fbpanelview-ez-template.js&/bundles/ezsystemsformbuilder/js/panels/fb-panelview.js
# will not work when loading http://localhost:8080/ez
@@ -34,6 +35,6 @@ ENV SYMFONY_ENV=prod
COPY --from=builder /var/www /var/www
# Fix permissions for www-data
-RUN chown -R www-data:www-data app/cache app/logs \
- && find app/cache app/logs -type d -print0 | xargs -0 chmod -R 775 \
- && find app/cache app/logs -type f -print0 | xargs -0 chmod -R 664
+RUN chown -R www-data:www-data var web/var \
+ && find var web/var -type d -print0 | xargs -0 chmod -R 775 \
+ && find var web/var -type f -print0 | xargs -0 chmod -R 664
diff --git a/app/.htaccess b/app/.htaccess
new file mode 100644
index 0000000000..fb1de45bdb
--- /dev/null
+++ b/app/.htaccess
@@ -0,0 +1,7 @@
+
+ Require all denied
+
+
+ Order deny,allow
+ Deny from all
+
diff --git a/app/AppKernel.php b/app/AppKernel.php
index 007ec741c9..d9706cbf80 100644
--- a/app/AppKernel.php
+++ b/app/AppKernel.php
@@ -5,16 +5,10 @@
class AppKernel extends Kernel
{
- /**
- * Returns an array of bundles to registers.
- *
- * @return array an array of bundle instances
- *
- * @api
- */
public function registerBundles()
{
- $bundles = array(
+ $bundles = [
+ // Symfony
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
@@ -23,58 +17,76 @@ public function registerBundles()
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
- new Tedivm\StashBundle\TedivmStashBundle(),
+ // Dependencies
new Hautelook\TemplatedUriBundle\HautelookTemplatedUriBundle(),
new Liip\ImagineBundle\LiipImagineBundle(),
new FOS\HttpCacheBundle\FOSHttpCacheBundle(),
+ new Nelmio\CorsBundle\NelmioCorsBundle(),
+ new Oneup\FlysystemBundle\OneupFlysystemBundle(),
+ new JMS\TranslationBundle\JMSTranslationBundle(),
+ new Knp\Bundle\MenuBundle\KnpMenuBundle(),
+ new Bazinga\Bundle\JsTranslationBundle\BazingaJsTranslationBundle(),
+ new FOS\JsRoutingBundle\FOSJsRoutingBundle(),
+ new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
+ // eZ Systems
new EzSystems\PlatformHttpCacheBundle\EzSystemsPlatformHttpCacheBundle(),
new eZ\Bundle\EzPublishCoreBundle\EzPublishCoreBundle(),
new eZ\Bundle\EzPublishLegacySearchEngineBundle\EzPublishLegacySearchEngineBundle(),
new eZ\Bundle\EzPublishIOBundle\EzPublishIOBundle(),
- new EzSystems\MultiFileUploadBundle\EzSystemsMultiFileUploadBundle(),
new eZ\Bundle\EzPublishRestBundle\EzPublishRestBundle(),
- new EzSystems\PlatformUIAssetsBundle\EzSystemsPlatformUIAssetsBundle(),
- new EzSystems\PlatformUIBundle\EzSystemsPlatformUIBundle(),
new EzSystems\EzSupportToolsBundle\EzSystemsEzSupportToolsBundle(),
- new Nelmio\CorsBundle\NelmioCorsBundle(),
- new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
- new Oneup\FlysystemBundle\OneupFlysystemBundle(),
new EzSystems\PlatformInstallerBundle\EzSystemsPlatformInstallerBundle(),
new EzSystems\RepositoryFormsBundle\EzSystemsRepositoryFormsBundle(),
new EzSystems\EzPlatformSolrSearchEngineBundle\EzSystemsEzPlatformSolrSearchEngineBundle(),
- new EzSystems\EzContentOnTheFlyBundle\EzSystemsEzContentOnTheFlyBundle(),
new EzSystems\EzPlatformDesignEngineBundle\EzPlatformDesignEngineBundle(),
- new Bazinga\Bundle\JsTranslationBundle\BazingaJsTranslationBundle(),
- new JMS\TranslationBundle\JMSTranslationBundle(),
+ new EzSystems\EzPlatformAdminUiBundle\EzPlatformAdminUiBundle(),
+ new EzSystems\EzPlatformAdminUiModulesBundle\EzPlatformAdminUiModulesBundle(),
+ new EzSystems\EzPlatformAdminUiAssetsBundle\EzPlatformAdminUiAssetsBundle(),
+ // Application
new AppBundle\AppBundle(),
- );
+ ];
switch ($this->getEnvironment()) {
case 'test':
case 'behat':
$bundles[] = new EzSystems\BehatBundle\EzSystemsBehatBundle();
$bundles[] = new EzSystems\PlatformBehatBundle\EzPlatformBehatBundle();
- // No break, test also needs dev bundles
+ // No break, test also needs dev bundles
case 'dev':
$bundles[] = new eZ\Bundle\EzPublishDebugBundle\EzPublishDebugBundle();
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
+ $bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
- $bundles[] = new Egulias\ListenersDebugCommandBundle\EguliasListenersDebugCommandBundle();
}
return $bundles;
}
- /**
- * Loads the container configuration.
- *
- * @param LoaderInterface $loader A LoaderInterface instance
- * @throws \RuntimeException when config file is not readable
- *
- * @api
- */
+ public function getRootDir()
+ {
+ return __DIR__;
+ }
+
+ public function getCacheDir()
+ {
+ if (!empty($_SERVER['SYMFONY_TMP_DIR'])) {
+ return dirname($_SERVER['SYMFONY_TMP_DIR']) . '/var/cache/' . $this->getEnvironment();
+ }
+
+ return dirname(__DIR__) . '/var/cache/' . $this->getEnvironment();
+ }
+
+ public function getLogDir()
+ {
+ if (!empty($_SERVER['SYMFONY_TMP_DIR'])) {
+ return dirname($_SERVER['SYMFONY_TMP_DIR']) . '/var/logs';
+ }
+
+ return dirname(__DIR__) . '/var/logs';
+ }
+
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir() . '/config/config_' . $this->getEnvironment() . '.yml');
diff --git a/app/cache/.keep b/app/Resources/views/.gitkeep
similarity index 100%
rename from app/cache/.keep
rename to app/Resources/views/.gitkeep
diff --git a/app/autoload.php b/app/autoload.php
deleted file mode 100644
index 79137cbb30..0000000000
--- a/app/autoload.php
+++ /dev/null
@@ -1,20 +0,0 @@
-setParameter('secret', $value);
-}
-
-// Mailer settings
-if ($value = getenv('MAILER_TRANSPORT')) {
- $container->setParameter('mailer_transport', $value);
-}
-
-if ($value = getenv('MAILER_HOST')) {
- $container->setParameter('mailer_host', $value);
-}
-
-if ($value = getenv('MAILER_USER')) {
- $container->setParameter('mailer_user', $value);
-}
-
-if ($value = getenv('MAILER_PASSWORD')) {
- $container->setParameter('mailer_password', $value);
-}
-
-// Database settings
-if ($value = getenv('DATABASE_DRIVER')) {
- $container->setParameter('database_driver', $value);
-}
-
-if ($value = getenv('DATABASE_HOST')) {
- $container->setParameter('database_host', $value);
-}
-
-if ($value = getenv('DATABASE_PORT')) {
- $container->setParameter('database_port', $value);
-}
-
-if ($value = getenv('DATABASE_NAME')) {
- $container->setParameter('database_name', $value);
-}
-
-if ($value = getenv('DATABASE_USER')) {
- $container->setParameter('database_user', $value);
-}
-
-if ($value = getenv('DATABASE_PASSWORD')) {
- $container->setParameter('database_password', $value);
-}
-
-// Search Engine settings
-if ($value = getenv('SEARCH_ENGINE')) {
- $container->setParameter('search_engine', $value);
-}
-
-if ($value = getenv('SOLR_DSN')) {
- $container->setParameter('solr_dsn', $value);
-}
-
-// Logging settings
-if ($value = getenv('LOG_TYPE')) {
- $container->setParameter('log_type', $value);
-}
-
-if ($value = getenv('LOG_PATH')) {
- $container->setParameter('log_path', $value);
-}
-
// Cache settings
-// Config validation by Stash prohbitis us from pre defining pools using drivers not supported by all systems
-// So we expose a env variable to load and use other pools when needed, additional pools can be added in cache_pool/ folder.
-if ($pool = getenv('CUSTOM_CACHE_POOL')) {
- $container->setParameter('cache_pool', $pool);
-
- if ($host = getenv('CACHE_HOST')) {
- $container->setParameter('cache_host', $host);
- }
-
- // Optional port settings in case not default
- if ($host = getenv('CACHE_MEMCACHED_PORT')) {
- $container->setParameter('cache_memcached_port', $host);
- } elseif ($host = getenv('CACHE_REDIS_PORT')) {
- $container->setParameter('cache_redis_port', $host);
- }
-
+// If CACHE_POOL env variable is set, check if there is a yml file that needs to be loaded for it
+if (($pool = getenv('CACHE_POOL')) && file_exists(__DIR__ . "/../cache_pool/${pool}.yml")) {
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../cache_pool'));
$loader->load($pool . '.yml');
}
-// HttpCache setting (for configuring http cache purging)
+// Params that needs to be set at compile time and thus can't use Symfony's env()
if ($purgeType = getenv('HTTPCACHE_PURGE_TYPE')) {
$container->setParameter('purge_type', $purgeType);
}
-if ($purgeServer = getenv('HTTPCACHE_PURGE_SERVER')) {
- // BC : In earlier versions, purge_type was set automatically if purge_server was set
- if ($purgeType === false) {
- $container->setParameter('purge_type', 'http');
- }
- $container->setParameter('purge_server', $purgeServer);
+if ($value = getenv('MAILER_TRANSPORT')) {
+ $container->setParameter('mailer_transport', $value);
}
-if ($value = getenv('HTTPCACHE_DEFAULT_TTL')) {
- $container->setParameter('httpcache_default_ttl', $value);
+if ($value = getenv('LOG_TYPE')) {
+ $container->setParameter('log_type', $value);
}
// EzSystemsRecommendationsBundle settings
+// @todo Move to use env() and params
if ($value = getenv('RECOMMENDATIONS_CUSTOMER_ID')) {
$container->setParameter('ez_recommendation.default.yoochoose.customer_id', $value);
}
diff --git a/app/config/ezplatform.yml b/app/config/ezplatform.yml
index eeaefd3366..aecd4ce5b1 100644
--- a/app/config/ezplatform.yml
+++ b/app/config/ezplatform.yml
@@ -13,9 +13,14 @@ ezpublish:
# Siteaccess configuration, with one siteaccess per default
siteaccess:
- list: [site]
+ list: [site, admin]
groups:
site_group: [site]
+
+ # WARNING: Do not remove or rename this group.
+ # It's used to distinguish common siteaccesses from admin ones.
+ # In case of multisite with multiple admin panels, remember to add any additional admin siteaccess to this group.
+ admin_group: [admin]
default_siteaccess: site
match:
URIElement: 1
@@ -23,8 +28,8 @@ ezpublish:
# System settings, grouped by siteaccess and/or siteaccess group
system:
site_group:
- # Pool to use for cache, needs to be different per repository (database).
- cache_pool_name: '%cache_pool%'
+ # Cache pool service, needs to be different per repository (database) on multi repository install.
+ cache_service_name: '%cache_pool%'
# These reflect the current installers, complete installation before you change them. For changing var_dir
# it is recommended to install clean, then change setting before you start adding binary content, otherwise you'll
# need to manually modify your database data to reflect this to avoid exceptions.
@@ -40,3 +45,18 @@ ezpublish:
# HttpCache purge server(s) setting, eg Varnish, for when ezpublish.http_cache.purge_type is set to 'http'.
http_cache:
purge_servers: ['%purge_server%']
+ # Temporary hard coding session name during v2 development
+ session:
+ name: eZSESSID
+
+ # WARNING: Do not remove or rename this group.
+ admin_group:
+ cache_service_name: '%cache_pool%'
+ var_dir: var/site
+ languages: [eng-GB]
+ content:
+ default_ttl: '%httpcache_default_ttl%'
+ http_cache:
+ purge_servers: ['%purge_server%']
+ session:
+ name: eZSESSID
diff --git a/app/config/ezplatform_test.yml b/app/config/ezplatform_test.yml
new file mode 100644
index 0000000000..967ac2e915
--- /dev/null
+++ b/app/config/ezplatform_test.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: ezplatform.yml }
diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist
index 0ff4cba476..08fc5a6253 100644
--- a/app/config/parameters.yml.dist
+++ b/app/config/parameters.yml.dist
@@ -1,13 +1,13 @@
# This file is a "template" of what your parameters.yml file should look like
parameters:
# A secret key that's used to generate certain security-related tokens
- secret: ThisEzPlatformTokenIsNotSoSecretChangeIt
+ env(SYMFONY_SECRET): ThisEzPlatformTokenIsNotSoSecretChangeIt
# Settings for database backend used by Doctrine DBAL
- # In turn used for Content Repository Persistence, and default database powered search engine
- database_driver: pdo_mysql
- database_host: localhost
- database_port: ~
- database_name: ezplatform
- database_user: root
- database_password:
+ # In turn used for default storage engine & default search engine (if legacy is configured as search engine)
+ env(DATABASE_DRIVER): pdo_mysql
+ env(DATABASE_HOST): localhost
+ env(DATABASE_PORT): ~
+ env(DATABASE_NAME): ezplatform
+ env(DATABASE_USER): root
+ env(DATABASE_PASSWORD):
diff --git a/app/config/routing.yml b/app/config/routing.yml
index 1dce3661eb..fddb4a66bc 100644
--- a/app/config/routing.yml
+++ b/app/config/routing.yml
@@ -8,32 +8,20 @@ login_check:
logout:
path: /logout
-_ezpublishRoutes:
+kernel.internal:
resource: '@EzPublishCoreBundle/Resources/config/routing/internal.yml'
-_ezpublishRestRoutes:
+kernel.rest:
resource: '@EzPublishRestBundle/Resources/config/routing.yml'
- prefix: '%ezpublish_rest.path_prefix%'
+ prefix: /api/ezp/v2
-_ezpublishRestOptionsRoutes:
- resource: '@EzPublishRestBundle/Resources/config/routing.yml'
- prefix: '%ezpublish_rest.path_prefix%'
- type: rest_options
-
-_liip_imagine:
- resource: '@LiipImagineBundle/Resources/config/routing.xml'
-
-_ezpublishPlatformUIRoutes:
- resource: '@eZPlatformUIBundle/Resources/config/routing.yml'
+ezplatform.admin_ui:
+ resource: '@EzPlatformAdminUiBundle/Resources/config/routing.yml'
+ defaults:
+ siteaccess_group_whitelist: '%admin_group_name%'
_ezplatformRepositoryFormsRoutes:
resource: '@EzSystemsRepositoryFormsBundle/Resources/config/routing.yml'
-_contentOnTheFly:
- resource: '@ContentOnTheFlyBundle/Resources/config/routing.yml'
- prefix: '%ezpublish_rest.path_prefix%'
-
-_multiFileUpload:
- resource: '@EzSystemsMultiFileUploadBundle/Resources/config/routing.yml'
- prefix: '%ezpublish_rest.path_prefix%'
-
+fos.js_routing:
+ resource: '@FOSJsRoutingBundle/Resources/config/routing/routing.xml'
diff --git a/app/config/security.yml b/app/config/security.yml
index 8f194241e4..429af06723 100644
--- a/app/config/security.yml
+++ b/app/config/security.yml
@@ -14,15 +14,6 @@ security:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
- ## WARNING
- ## Until https://jira.ez.no/browse/EZP-22192 is implemented,
- ## enabling basic auth in RESTÂ will prevent PlatformUI from working
-# ezpublish_rest:
-# pattern: ^/api/ezp/v2
-# stateless: true
-# ezpublish_http_basic:
-# realm: eZ Publish REST API
-
ezpublish_front:
pattern: ^/
anonymous: ~
@@ -31,5 +22,12 @@ security:
require_previous_session: false
logout: ~
- default:
+ main:
anonymous: ~
+ # activate different ways to authenticate
+
+ # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
+ #http_basic: ~
+
+ # https://symfony.com/doc/current/security/form_login_setup.html
+ #form_login: ~
diff --git a/app/config/services.yml b/app/config/services.yml
new file mode 100644
index 0000000000..63dc7a1580
--- /dev/null
+++ b/app/config/services.yml
@@ -0,0 +1,15 @@
+# Learn more about services, parameters and containers at
+# https://symfony.com/doc/current/service_container.html
+parameters:
+ #parameter_name: value
+
+services:
+ # default configuration for services in *this* file
+ _defaults:
+ # automatically injects dependencies in your services
+ autowire: true
+ # automatically registers your services as commands, event subscribers, etc.
+ autoconfigure: true
+ # this means you cannot fetch services directly from the container via $container->get()
+ # if you need to do this, you can override this setting on individual services
+ public: false
diff --git a/app/phpunit.xml.dist b/app/phpunit.xml.dist
deleted file mode 100644
index 5549ae627c..0000000000
--- a/app/phpunit.xml.dist
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
- ../src/*/*Bundle/Tests
- ../src/*/Bundle/*Bundle/Tests
- ../src/*Bundle/Tests
-
-
-
-
-
-
-
- ../src
-
- ../src/*/*Bundle/Resources
- ../src/*/*Bundle/Tests
- ../src/*/Bundle/*Bundle/Resources
- ../src/*/Bundle/*Bundle/Tests
-
-
-
-
diff --git a/behat.yml.dist b/behat.yml.dist
index a8a65961a3..4f237beaac 100644
--- a/behat.yml.dist
+++ b/behat.yml.dist
@@ -1,4 +1,3 @@
-# This file contains the default configuration for behat testing using EzSystems/BehatBundle
default:
calls:
error_reporting: -1 # Report all PHP errors
@@ -19,24 +18,19 @@ default:
Behat\Symfony2Extension:
kernel:
- bootstrap: app/autoload.php
+ bootstrap: vendor/autoload.php
path: app/AppKernel.php
class: AppKernel
env: behat
debug: false
- jarnaiz\JUnitFormatter\JUnitFormatterExtension:
- filename: report.xml
- outputDir: %paths.base%/app/logs/junit
-
EzSystems\PlatformBehatBundle\ServiceContainer\EzBehatExtension: ~
- # default profile: no suites
suites: ~
imports:
- vendor/ezsystems/ezpublish-kernel/eZ/Bundle/EzPublishCoreBundle/behat_suites.yml
- vendor/ezsystems/ezpublish-kernel/eZ/Bundle/EzPublishRestBundle/behat_suites.yml
- - vendor/ezsystems/behatbundle/EzSystems/BehatBundle/behat_suites.yml
- - vendor/ezsystems/platform-ui-bundle/behat_suites.yml
- vendor/ezsystems/repository-forms/behat_suites.yml
+ - vendor/ezsystems/ezplatform-admin-ui/behat_suites.yml
+ - vendor/ezsystems/behatbundle/EzSystems/BehatBundle/behat_suites.yml
diff --git a/bin/.travis/parameters.yml b/bin/.travis/parameters.yml
index 67ecd0bb76..b047a671b1 100644
--- a/bin/.travis/parameters.yml
+++ b/bin/.travis/parameters.yml
@@ -1,5 +1,5 @@
# Only settings different then parameters.yml.dist, buildParameters will inject those we don't define from there!
parameters:
- database_name: behattestdb
- database_user: ezp
- database_password: ezp
+ env(DATABASE_NAME): behattestdb
+ env(DATABASE_USER): ezp
+ env(DATABASE_PASSWORD): ezp
diff --git a/bin/.travis/trusty/setup_ezplatform.sh b/bin/.travis/trusty/setup_ezplatform.sh
new file mode 100755
index 0000000000..1ed53517d7
--- /dev/null
+++ b/bin/.travis/trusty/setup_ezplatform.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+# This script provides setup steps needed to build eZ Platform docker containers ready to execute
+# functional and acceptance (behat) tests.
+#
+# Example usage:
+# $ ./bin/.travis/trusty/setup_ezplatform.sh "${COMPOSE_FILE}" "${INSTALL_TYPE}" ["${DEPENDENCY_PACKAGE_DIR}"]
+#
+# Arguments:
+# - ${COMPOSE_FILE} compose file(s) paths
+# - ${INSTALL_TYPE} optional, eZ Platform install type ("clean") will take from .env if not set
+# - ${DEPENDENCY_PACKAGE_DIR} optional, directory containing existing eZ Platform dependency package
+
+# Determine eZ Platform Build dir as relative to current script path
+EZPLATFORM_BUILD_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../.." && pwd )"
+
+# Source .env first to make sure we don't override any variables
+. ${EZPLATFORM_BUILD_DIR}/.env
+
+DEPENDENCY_PACKAGE_DIR=$3
+
+if [[ -z "${1}" ]]; then
+ COMPOSE_FILE=$COMPOSE_FILE
+else
+ COMPOSE_FILE=$1
+fi
+
+if [[ -z "${2}" ]]; then
+ INSTALL_TYPE=$INSTALL_EZ_INSTALL_TYPE
+else
+ INSTALL_TYPE=$2
+fi
+
+if [[ -n "${DEPENDENCY_PACKAGE_DIR}" ]]; then
+ # Get details about dependency package
+ DEPENDENCY_PACKAGE_NAME=`php -r "echo json_decode(file_get_contents('${DEPENDENCY_PACKAGE_DIR}/composer.json'))->name;"`
+
+ if [[ -z "${DEPENDENCY_PACKAGE_NAME}" ]]; then
+ echo 'Missing composer package name of tested dependency' >&2
+ exit 2
+ fi
+fi
+
+echo '> Preparing eZ Platform container using the following setup:'
+echo "- EZPLATFORM_BUILD_DIR=${EZPLATFORM_BUILD_DIR}"
+echo "- COMPOSE_FILE=${COMPOSE_FILE}"
+if [[ -n "${DEPENDENCY_PACKAGE_NAME}" ]]; then
+ echo "- DEPENDENCY_PACKAGE_NAME=${DEPENDENCY_PACKAGE_NAME}"
+fi
+
+echo '> Remove XDebug PHP extension'
+phpenv config-rm xdebug.ini
+
+echo "> Start docker containers specified by ${COMPOSE_FILE}"
+docker-compose up -d
+docker-compose exec app sh -c 'chown -R www-data:www-data /var/www'
+
+echo '> Run composer install inside docker app container'
+docker-compose exec --user www-data app sh -c 'COMPOSER_HOME=$HOME/.composer composer install --no-suggest --no-progress --no-interaction --prefer-dist --optimize-autoloader'
+
+# Handle dependency if needed
+if [[ -n "${DEPENDENCY_PACKAGE_NAME}" ]]; then
+ # check if dependency exists for current meta-package version
+ if [[ ! -d "./vendor/${DEPENDENCY_PACKAGE_NAME}" ]]; then
+ echo "Testing dependency failed: package ${DEPENDENCY_PACKAGE_NAME} does not exist" >&2
+ exit 3
+ fi
+
+ echo "> Overwrite ./vendor/${DEPENDENCY_PACKAGE_NAME} with ${DEPENDENCY_PACKAGE_DIR}"
+ if ! (sudo rm -rf "./vendor/${DEPENDENCY_PACKAGE_NAME}" && sudo mv ${DEPENDENCY_PACKAGE_DIR} "./vendor/${DEPENDENCY_PACKAGE_NAME}"); then
+ echo 'Overwrite failed' >&2
+ exit 4
+ fi
+
+ echo '> Clear Symfony cache inside docker app container'
+ docker-compose exec --user www-data app sh -c 'php ./bin/console cache:clear --no-warmup && php ./bin/console cache:warmup'
+fi
+
+echo '> Install data'
+docker-compose exec --user www-data app sh -c "php /scripts/wait_for_db.php; php bin/console ezplatform:install ${INSTALL_TYPE}"
+
+echo '> Done, ready to run tests'
diff --git a/bin/.travis/trusty/setup_from_external_repo.sh b/bin/.travis/trusty/setup_from_external_repo.sh
index 86d0df97e1..280f95236f 100755
--- a/bin/.travis/trusty/setup_from_external_repo.sh
+++ b/bin/.travis/trusty/setup_from_external_repo.sh
@@ -1,5 +1,7 @@
#!/bin/bash
+# @deprecated since 2.0, use ./bin/.travis/trusty/setup_ezplatform.sh
+#
# This script is meant to be reused from other repos that needs to run behat tests.
#
# It assumes you have already checked pout ezplatform (to get access to this script) and
@@ -21,6 +23,8 @@
#
# script: docker-compose run -u www-data --rm behatphpcli bin/behat --profile=rest --suite=fullJson --tags=~@broken
+echo 'The script setup_from_external_repo is deprecated. Use ./bin/.travis/trusty/setup_ezplatform.sh instead.' >&2
+
REPO_DIR=$1
COMPOSER_REQUIRE=${@:2}
@@ -60,10 +64,10 @@ if [ "$RUN_INSTALL" = "1" ] ; then
echo "> Run composer install"
composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader
mkdir -p web/var
- rm -Rf app/logs/* app/cache/*/*
- sudo chown -R www-data:www-data app/cache app/logs web/var
- find app/cache app/logs web/var -type d | xargs chmod -R 775
- find app/cache app/logs web/var -type f | xargs chmod -R 664
+ rm -Rf var/logs/* var/cache/*/*
+ sudo chown -R www-data:www-data var/cache var/logs web/var
+ find var/cache var/logs web/var -type d | xargs chmod -R 775
+ find var/cache var/logs web/var -type f | xargs chmod -R 664
# Do NOT use this for your prod setup, this is done like this for behat
sudo chown -R www-data:www-data app/config src
#docker-compose -f doc/docker/install.yml up --abort-on-container-exit
@@ -73,6 +77,6 @@ INSTALL_EZ_INSTALL_TYPE=${INSTALL_EZ_INSTALL_TYPE:-clean}
echo "> Start containers and install data"
docker-compose up -d
-docker-compose exec --user www-data app sh -c "php /scripts/wait_for_db.php; php app/console ezplatform:install $INSTALL_EZ_INSTALL_TYPE"
+docker-compose exec --user www-data app sh -c "php /scripts/wait_for_db.php; php bin/console ezplatform:install $INSTALL_EZ_INSTALL_TYPE"
echo "> Done, ready to run behatphpcli container"
diff --git a/app/console b/bin/console
similarity index 58%
rename from app/console
rename to bin/console
index 58b61953f0..5af600e5c1 100755
--- a/app/console
+++ b/bin/console
@@ -1,8 +1,13 @@
#!/usr/bin/env php
getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
-$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
+$env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev');
+$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod';
+
if ($debug) {
Debug::enable();
}
diff --git a/bin/symfony_requirements b/bin/symfony_requirements
new file mode 100755
index 0000000000..a7bf65a1b8
--- /dev/null
+++ b/bin/symfony_requirements
@@ -0,0 +1,146 @@
+#!/usr/bin/env php
+getPhpIniConfigPath();
+
+echo_title('Symfony Requirements Checker');
+
+echo '> PHP is using the following php.ini file:'.PHP_EOL;
+if ($iniPath) {
+ echo_style('green', ' '.$iniPath);
+} else {
+ echo_style('yellow', ' WARNING: No configuration file (php.ini) used by PHP!');
+}
+
+echo PHP_EOL.PHP_EOL;
+
+echo '> Checking Symfony requirements:'.PHP_EOL.' ';
+
+$messages = array();
+foreach ($symfonyRequirements->getRequirements() as $req) {
+ if ($helpText = get_error_message($req, $lineSize)) {
+ echo_style('red', 'E');
+ $messages['error'][] = $helpText;
+ } else {
+ echo_style('green', '.');
+ }
+}
+
+$checkPassed = empty($messages['error']);
+
+foreach ($symfonyRequirements->getRecommendations() as $req) {
+ if ($helpText = get_error_message($req, $lineSize)) {
+ echo_style('yellow', 'W');
+ $messages['warning'][] = $helpText;
+ } else {
+ echo_style('green', '.');
+ }
+}
+
+if ($checkPassed) {
+ echo_block('success', 'OK', 'Your system is ready to run Symfony projects');
+} else {
+ echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects');
+
+ echo_title('Fix the following mandatory requirements', 'red');
+
+ foreach ($messages['error'] as $helpText) {
+ echo ' * '.$helpText.PHP_EOL;
+ }
+}
+
+if (!empty($messages['warning'])) {
+ echo_title('Optional recommendations to improve your setup', 'yellow');
+
+ foreach ($messages['warning'] as $helpText) {
+ echo ' * '.$helpText.PHP_EOL;
+ }
+}
+
+echo PHP_EOL;
+echo_style('title', 'Note');
+echo ' The command console could use a different php.ini file'.PHP_EOL;
+echo_style('title', '~~~~');
+echo ' than the one used with your web server. To be on the'.PHP_EOL;
+echo ' safe side, please check the requirements from your web'.PHP_EOL;
+echo ' server using the ';
+echo_style('yellow', 'web/config.php');
+echo ' script.'.PHP_EOL;
+echo PHP_EOL;
+
+exit($checkPassed ? 0 : 1);
+
+function get_error_message(Requirement $requirement, $lineSize)
+{
+ if ($requirement->isFulfilled()) {
+ return;
+ }
+
+ $errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL.' ').PHP_EOL;
+ $errorMessage .= ' > '.wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL.' > ').PHP_EOL;
+
+ return $errorMessage;
+}
+
+function echo_title($title, $style = null)
+{
+ $style = $style ?: 'title';
+
+ echo PHP_EOL;
+ echo_style($style, $title.PHP_EOL);
+ echo_style($style, str_repeat('~', strlen($title)).PHP_EOL);
+ echo PHP_EOL;
+}
+
+function echo_style($style, $message)
+{
+ // ANSI color codes
+ $styles = array(
+ 'reset' => "\033[0m",
+ 'red' => "\033[31m",
+ 'green' => "\033[32m",
+ 'yellow' => "\033[33m",
+ 'error' => "\033[37;41m",
+ 'success' => "\033[37;42m",
+ 'title' => "\033[34m",
+ );
+ $supports = has_color_support();
+
+ echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : '');
+}
+
+function echo_block($style, $title, $message)
+{
+ $message = ' '.trim($message).' ';
+ $width = strlen($message);
+
+ echo PHP_EOL.PHP_EOL;
+
+ echo_style($style, str_repeat(' ', $width));
+ echo PHP_EOL;
+ echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT));
+ echo PHP_EOL;
+ echo_style($style, $message);
+ echo PHP_EOL;
+ echo_style($style, str_repeat(' ', $width));
+ echo PHP_EOL;
+}
+
+function has_color_support()
+{
+ static $support;
+
+ if (null === $support) {
+ if (DIRECTORY_SEPARATOR == '\\') {
+ $support = false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
+ } else {
+ $support = function_exists('posix_isatty') && @posix_isatty(STDOUT);
+ }
+ }
+
+ return $support;
+}
diff --git a/composer.json b/composer.json
index a9879201cf..127b4844ee 100644
--- a/composer.json
+++ b/composer.json
@@ -24,55 +24,53 @@
"files": [ "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php" ]
},
"require": {
- "php": "~5.6|~7.0",
- "symfony/symfony": "~2.8",
- "twig/extensions": "~1.4",
+ "php": "^7.1",
+ "symfony/symfony": "3.4.0",
+ "twig/twig": "^1.0||^2.0",
+ "twig/extensions": "^1.5.0",
"symfony/assetic-bundle": "~2.8",
"symfony/swiftmailer-bundle": "~2.5",
- "symfony/monolog-bundle": "~2.12|~3.0",
- "sensio/distribution-bundle": "^3.0.36|^4.0.6|^5.0",
- "sensio/generator-bundle": "^2.3|^3.0",
+ "symfony/monolog-bundle": "^3.1.0",
+ "doctrine/doctrine-bundle": "^1.6",
+ "doctrine/orm": "^2.5",
+ "sensio/distribution-bundle": "^5.0.19",
"incenteev/composer-parameter-handler": "~2.1",
- "tedivm/stash-bundle": "~0.6",
- "ezsystems/ezpublish-kernel": "^6.13@dev",
- "ezsystems/repository-forms": "^1.10@dev",
+ "ezsystems/ezpublish-kernel": "^7.0@dev",
+ "ezsystems/repository-forms": "^2.0@dev",
"ezsystems/ezplatform-solr-search-engine": "^1.5@dev",
- "ezsystems/platform-ui-bundle": "^1.13@dev",
- "ezsystems/ez-support-tools": "~0.1.3@dev",
+ "ezsystems/ez-support-tools": "^0.2@dev",
"ezsystems/ezplatform-http-cache": "^0.4@dev",
- "ezplatform-i18n/ezplatform-i18n-ach_ug": "^1.4@dev",
- "ezsystems/ezplatform-multi-file-upload": "^0.1",
+ "ezsystems/ezplatform-admin-ui": "^1.0@dev",
+ "ezsystems/ezplatform-admin-ui-modules": "^1.0@dev",
+ "ezsystems/ezplatform-admin-ui-assets": "^0.4",
"ezsystems/ezplatform-design-engine": "^1.1",
- "egulias/listeners-debug-command-bundle": "~1.9",
- "white-october/pagerfanta-bundle": "1.0.*",
- "hautelook/templated-uri-bundle": "~1.0 | ~2.0",
- "doctrine/doctrine-bundle": "~1.5",
- "sensio/framework-extra-bundle": "~3.0",
- "ezsystems/content-on-the-fly-prototype": "~0.1.11",
+ "knplabs/knp-menu-bundle": "^2.1",
+ "sensio/framework-extra-bundle": "^3.0.2",
"willdurand/js-translation-bundle": "^2.6.4",
- "roave/security-advisories": "dev-master"
+ "oneup/flysystem-bundle": "^2.0",
+ "friendsofsymfony/jsrouting-bundle": "^1.4",
+ "white-october/pagerfanta-bundle": "^1.1",
+ "roave/security-advisories": "dev-master",
+ "leafo/scssphp": "^0.7"
},
"require-dev": {
- "ezsystems/ezplatform-i18n": "^1.4@dev",
"behat/behat": "~3.2",
"behat/symfony2-extension": "~2.0",
"behat/mink-extension": "~2.0",
"behat/mink-goutte-driver": "~1.0",
"behat/mink-selenium2-driver": "~1.0",
- "jarnaiz/behat-junit-formatter": "^1.3",
- "ezsystems/behatbundle": "^6.3"
- },
- "suggest": {
- "ezsystems/legacy-bridge": "Provides the full legacy backoffice and legacy features"
+ "ezsystems/behatbundle": "^6.5",
+ "phpunit/phpunit": "^6.4",
+ "sensio/generator-bundle": "~3.1",
+ "symfony/phpunit-bridge": "~3.2"
},
"scripts": {
"symfony-scripts": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
- "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"eZ\\Bundle\\EzPublishCoreBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
- "eZ\\Bundle\\EzPublishCoreBundle\\Composer\\ScriptHandler::dumpAssets",
- "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
+ "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
+ "@php bin/console assetic:dump"
],
"post-install-cmd": [
"@symfony-scripts"
@@ -85,20 +83,22 @@
]
},
"config": {
- "process-timeout": 3000,
- "bin-dir": "bin"
+ "bin-dir": "bin",
+ "sort-packages": true
},
"extra": {
"symfony-app-dir": "app",
+ "symfony-bin-dir": "bin",
+ "symfony-var-dir": "var",
"symfony-web-dir": "web",
- "___symfony-assets-install": "One of 'symlink', 'relative' (symlinks) or 'hard'",
+ "symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"incenteev-parameters": {
"keep-outdated": true,
"file": "app/config/parameters.yml"
},
"branch-alias": {
- "dev-master": "1.13.x-dev"
+ "dev-master": "2.0.x-dev"
}
}
}
diff --git a/doc/apache2/vhost.template b/doc/apache2/vhost.template
index 276eb2306c..49c473b809 100644
--- a/doc/apache2/vhost.template
+++ b/doc/apache2/vhost.template
@@ -72,11 +72,6 @@
# For FastCGI mode or when using PHP-FPM, to get basic auth working.
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
- # Needed for ci testing, you can optionally remove this.
- RewriteCond %{ENV:SYMFONY_ENV} "behat"
- RewriteCond %{REQUEST_URI} ^/php5-fcgi(.*)
- RewriteRule . - [L]
-
# Cluster/streamed files rewrite rules. Enable on cluster with DFS as a binary data handler
#RewriteRule ^/var/([^/]+/)?storage/images(-versioned)?/.* /app.php [L]
diff --git a/doc/docker/README.md b/doc/docker/README.md
index 4664c6514c..530c3c6776 100644
--- a/doc/docker/README.md
+++ b/doc/docker/README.md
@@ -77,7 +77,7 @@ docker-compose build dataset-vardir dataset-dbdump
docker-compose up -d --force-recreate
```
-After some 5-10 seconds you should be able to browse the site on `localhost:8080` and the backend on `localhost:8080/ez`.
+After some 5-10 seconds you should be able to browse the site on `localhost:8080` and the backend on `localhost:8080/admin`.
### Development "mount" use
@@ -100,7 +100,7 @@ docker-compose up -d --force-recreate
```
-After some 5-10 seconds you should be able to browse the site on `localhost:8080` and the backend on `localhost:8080/ez`.
+After some 5-10 seconds you should be able to browse the site on `localhost:8080` and the backend on `localhost:8080/admin`.
### Behat and Selenium use
diff --git a/doc/docker/install.yml b/doc/docker/install.yml
index 7033570fb0..419ad3f848 100644
--- a/doc/docker/install.yml
+++ b/doc/docker/install.yml
@@ -34,12 +34,12 @@ services:
composer install --no-progress --no-interaction --prefer-dist --no-suggest --optimize-autoloader;
mkdir -p web/var;
php /scripts/wait_for_db.php;
- php app/console ezplatform:install ${INSTALL_EZ_INSTALL_TYPE};
- if [ \"$SYMFONY_CMD\" != '' ]; then echo '> Executing' \"$SYMFONY_CMD\"; php app/console $SYMFONY_CMD; fi;
- rm -Rf app/logs/* app/cache/*/*;
- chown -R www-data:www-data app/cache app/logs web/var;
- find app/cache app/logs web/var -type d -print0 | xargs -0 chmod -R 775;
- find app/cache app/logs web/var -type f -print0 | xargs -0 chmod -R 664;
+ php bin/console ezplatform:install ${INSTALL_EZ_INSTALL_TYPE};
+ if [ \"$SYMFONY_CMD\" != '' ]; then echo '> Executing' \"$SYMFONY_CMD\"; php bin/console $SYMFONY_CMD; fi;
+ rm -Rf var/logs/* var/cache/*/*;
+ chown -R www-data:www-data var/cache var/logs web/var;
+ find var/cache var/logs web/var -type d -print0 | xargs -0 chmod -R 775;
+ find var/cache var/logs web/var -type f -print0 | xargs -0 chmod -R 664;
chown -R www-data:www-data app/config src;
echo 'Dumping database into doc/docker/entrypoint/mysql/2_dump.sql for use by mysql on startup.';
mysqldump -u $$DATABASE_USER --password=$$DATABASE_PASSWORD -h $$DATABASE_HOST --add-drop-table --extended-insert --protocol=tcp $$DATABASE_NAME > doc/docker/entrypoint/mysql/2_dump.sql"
diff --git a/doc/docker/redis.yml b/doc/docker/redis.yml
index 0daa26df94..1a0c59c0df 100644
--- a/doc/docker/redis.yml
+++ b/doc/docker/redis.yml
@@ -10,8 +10,8 @@ services:
depends_on:
- redis
environment:
- - CUSTOM_CACHE_POOL=singleredis
- - CACHE_HOST=redis
+ - CACHE_POOL=cache.redis
+ - CACHE_DSN=redis:6379
redis:
image: ${REDIS_IMAGE}
diff --git a/doc/varnish/varnish.md b/doc/varnish/varnish.md
index 628c47965e..264df7a7ed 100644
--- a/doc/varnish/varnish.md
+++ b/doc/varnish/varnish.md
@@ -10,8 +10,6 @@ Recommended VCL base files
For Varnish to work properly with eZ, you'll need to use the following VCL as starting point:
* [eZ Platform 1.7+ with Varnish 4.x/5.x with xkey VMOD](vcl/varnish4_xkey.vcl)
-* [eZ 5.4+ / 2014.09+ with Varnish 4/5 using builtin BAN](vcl/varnish4_ban.vcl) _(Deprecated in favour of xkey version)_
-* [eZ 5.4+ / 2014.09+ with Varnish 3 using builtin BAN](vcl/varnish3_ban.vcl) _(Deprecated in favour of xkey version)_
> **Note:** Http cache management is done with the help of [FOSHttpCacheBundle](http://foshttpcachebundle.readthedocs.org/).
diff --git a/doc/varnish/vcl/varnish3_ban.vcl b/doc/varnish/vcl/varnish3_ban.vcl
deleted file mode 100644
index 0517ded56a..0000000000
--- a/doc/varnish/vcl/varnish3_ban.vcl
+++ /dev/null
@@ -1,209 +0,0 @@
-// Varnish 3 style - eZ 5.4+ / 2014.09+
-// Complete VCL example
-// DEPRECATED: For faster, and over time more stable setup look to ezplatform-http-cache and Varnish xkey use.
-
-// For customizing your backend and acl rules see parameters.yml
-include "parameters.vcl";
-
-// Called at the beginning of a request, after the complete request has been received
-sub vcl_recv {
-
- // Set the backend
- set req.backend = ezplatform;
-
- // Advertise Symfony for ESI support
- set req.http.Surrogate-Capability = "abc=ESI/1.0";
-
- // Add a unique header containing the client address (only for master request)
- // Please note that /_fragment URI can change in Symfony configuration
- if (!req.url ~ "^/_fragment") {
- if (req.http.x-forwarded-for) {
- set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
- } else {
- set req.http.X-Forwarded-For = client.ip;
- }
- }
-
- // Trigger cache purge if needed
- call ez_purge;
-
- // Don't cache requests other than GET and HEAD.
- if (req.request != "GET" && req.request != "HEAD") {
- return (pass);
- }
-
- // Normalize the Accept-Encoding headers
- if (req.http.Accept-Encoding) {
- if (req.http.Accept-Encoding ~ "gzip") {
- set req.http.Accept-Encoding = "gzip";
- } elsif (req.http.Accept-Encoding ~ "deflate") {
- set req.http.Accept-Encoding = "deflate";
- } else {
- unset req.http.Accept-Encoding;
- }
- }
-
- // Don't cache Authenticate & Authorization
- // You may remove this when using REST API with basic auth.
- if (req.http.Authenticate || req.http.Authorization) {
- if (client.ip ~ debuggers) {
- set req.http.X-Debug = "Not Cached according to configuration (Authorization)";
- }
- return(pass);
- }
-
- // Do a standard lookup on assets
- // Note that file extension list below is not extensive, so consider completing it to fit your needs.
- if (req.url ~ "\.(css|js|gif|jpe?g|bmp|png|tiff?|ico|img|tga|wmf|svg|swf|ico|mp3|mp4|m4a|ogg|mov|avi|wmv|zip|gz|pdf|ttf|eot|wof)$") {
- return (lookup);
- }
-
- // Retrieve client user hash and add it to the forwarded request.
- call ez_user_hash;
-
- // If it passes all these tests, do a lookup anyway.
- return (lookup);
-}
-
-// Called when the requested object has been retrieved from the backend
-sub vcl_fetch {
-
- if (req.restarts == 0
- && req.http.accept ~ "application/vnd.fos.user-context-hash"
- && beresp.status >= 500
- ) {
- error 503 "Hash error";
- }
-
- // Optimize to only parse the Response contents from Symfony
- if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
- unset beresp.http.Surrogate-Control;
- set beresp.do_esi = true;
- }
-
- // Respect the Cache-Control=private header from the backend
- if (beresp.http.Cache-Control ~ "no-cache|no-store|private") {
- set beresp.ttl = 120s;
- return (hit_for_pass);
- }
-
- return (deliver);
-}
-
-// Handle purge
-// You may add FOSHttpCacheBundle tagging rules
-// See http://foshttpcache.readthedocs.org/en/latest/varnish-configuration.html#id4
-sub ez_purge {
-
- if (req.request == "BAN") {
- if (!client.ip ~ invalidators) {
- error 405 "Method not allowed";
- }
-
- if (req.http.X-Location-Id) {
- ban( "obj.http.X-Location-Id ~ " + req.http.X-Location-Id);
- if (client.ip ~ debuggers) {
- set req.http.X-Debug = "Ban done for content connected to LocationId " + req.http.X-Location-Id;
- }
- error 200 "Banned";
- }
- }
-}
-
-// Sub-routine to get client user hash, for context-aware HTTP cache.
-sub ez_user_hash {
-
- // Prevent tampering attacks on the hash mechanism
- if (req.restarts == 0
- && (req.http.accept ~ "application/vnd.fos.user-context-hash"
- || req.http.x-user-hash
- )
- ) {
- error 400;
- }
-
- if (req.restarts == 0 && (req.request == "GET" || req.request == "HEAD")) {
- // Get User (Context) hash, for varying cache by what user has access to.
- // https://doc.ez.no/display/EZP/Context+aware+HTTP+cache
-
- // Anonymous user w/o session => Use hardcoded anonymous hash to avoid backend lookup for hash
- if (req.http.Cookie !~ "eZSESSID" && !req.http.authorization) {
- // You may update this hash with the actual one for anonymous user
- // to get a better cache hit ratio across anonymous users.
- // Note: You should then update it every time anonymous user rights change.
- set req.http.X-User-Hash = "38015b703d82206ebc01d17a39c727e5";
- }
- // Pre-authenticate request to get shared cache, even when authenticated
- else {
- set req.http.x-fos-original-url = req.url;
- set req.http.x-fos-original-accept = req.http.accept;
- set req.http.x-fos-original-cookie = req.http.cookie;
- // Clean up cookie for the hash request to only keep session cookie, as hash cache will vary on cookie.
- set req.http.cookie = ";" + req.http.cookie;
- set req.http.cookie = regsuball(req.http.cookie, "; +", ";");
- set req.http.cookie = regsuball(req.http.cookie, ";(eZSESSID[^=]*)=", "; \1=");
- set req.http.cookie = regsuball(req.http.cookie, ";[^ ][^;]*", "");
- set req.http.cookie = regsuball(req.http.cookie, "^[; ]+|[; ]+$", "");
-
- set req.http.accept = "application/vnd.fos.user-context-hash";
- set req.url = "/_fos_user_context_hash";
-
- // Force the lookup, the backend must tell how to cache/vary response containing the user hash
-
- return (lookup);
- }
- }
-
- // Rebuild the original request which now has the hash.
- if (req.restarts > 0
- && req.http.accept == "application/vnd.fos.user-context-hash"
- ) {
- set req.url = req.http.x-fos-original-url;
- set req.http.accept = req.http.x-fos-original-accept;
- set req.http.cookie = req.http.x-fos-original-cookie;
-
- unset req.http.x-fos-original-url;
- unset req.http.x-fos-original-accept;
- unset req.http.x-fos-original-cookie;
-
- // Force the lookup, the backend must tell not to cache or vary on the
- // user hash to properly separate cached data.
-
- return (lookup);
- }
-}
-
-sub vcl_deliver {
- // On receiving the hash response, copy the hash header to the original
- // request and restart.
- if (req.restarts == 0
- && resp.http.content-type ~ "application/vnd.fos.user-context-hash"
- && resp.status == 200
- ) {
- set req.http.x-user-hash = resp.http.x-user-hash;
-
- return (restart);
- }
-
- // If we get here, this is a real response that gets sent to the client.
-
- // Remove the vary on context user hash, this is nothing public. Keep all
- // other vary headers.
- set resp.http.Vary = regsub(resp.http.Vary, "(?i),? *x-user-hash *", "");
- set resp.http.Vary = regsub(resp.http.Vary, "^, *", "");
- if (resp.http.Vary == "") {
- unset resp.http.Vary;
- }
-
- // Sanity check to prevent ever exposing the hash to a client.
- unset resp.http.x-user-hash;
-
- if (client.ip ~ debuggers) {
- if (obj.hits > 0) {
- set resp.http.X-Cache = "HIT";
- set resp.http.X-Cache-Hits = obj.hits;
- } else {
- set resp.http.X-Cache = "MISS";
- }
- }
-}
diff --git a/doc/varnish/vcl/varnish4_ban.vcl b/doc/varnish/vcl/varnish4_ban.vcl
deleted file mode 100644
index cebae6cccb..0000000000
--- a/doc/varnish/vcl/varnish4_ban.vcl
+++ /dev/null
@@ -1,205 +0,0 @@
-// Varnish 4 style - eZ 5.4+ / 2014.09+
-// Complete VCL example
-// DEPRECATED: For faster, and over time more stable setup look to ezplatform-http-cache and Varnish xkey use.
-
-vcl 4.0;
-
-// For customizing your backend and acl rules see parameters.yml
-include "parameters.vcl";
-
-// Called at the beginning of a request, after the complete request has been received
-sub vcl_recv {
-
- // Set the backend
- set req.backend_hint = ezplatform;
-
- // Advertise Symfony for ESI support
- set req.http.Surrogate-Capability = "abc=ESI/1.0";
-
- // Add a unique header containing the client address (only for master request)
- // Please note that /_fragment URI can change in Symfony configuration
- if (!req.url ~ "^/_fragment") {
- if (req.http.x-forwarded-for) {
- set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
- } else {
- set req.http.X-Forwarded-For = client.ip;
- }
- }
-
- // Trigger cache purge if needed
- call ez_purge;
-
- // Don't cache requests other than GET and HEAD.
- if (req.method != "GET" && req.method != "HEAD") {
- return (pass);
- }
-
- // Normalize the Accept-Encoding headers
- if (req.http.Accept-Encoding) {
- if (req.http.Accept-Encoding ~ "gzip") {
- set req.http.Accept-Encoding = "gzip";
- } elsif (req.http.Accept-Encoding ~ "deflate") {
- set req.http.Accept-Encoding = "deflate";
- } else {
- unset req.http.Accept-Encoding;
- }
- }
-
- // Don't cache Authenticate & Authorization
- // You may remove this when using REST API with basic auth.
- if (req.http.Authenticate || req.http.Authorization) {
- if (client.ip ~ debuggers) {
- set req.http.X-Debug = "Not Cached according to configuration (Authorization)";
- }
- return (hash);
- }
-
- // Do a standard lookup on assets
- // Note that file extension list below is not extensive, so consider completing it to fit your needs.
- if (req.url ~ "\.(css|js|gif|jpe?g|bmp|png|tiff?|ico|img|tga|wmf|svg|swf|ico|mp3|mp4|m4a|ogg|mov|avi|wmv|zip|gz|pdf|ttf|eot|wof)$") {
- return (hash);
- }
-
- // Retrieve client user hash and add it to the forwarded request.
- call ez_user_hash;
-
- // If it passes all these tests, do a lookup anyway.
- return (hash);
-}
-
-// Called when the requested object has been retrieved from the backend
-sub vcl_backend_response {
-
- if (bereq.http.accept ~ "application/vnd.fos.user-context-hash"
- && beresp.status >= 500
- ) {
- return (abandon);
- }
-
- // Optimize to only parse the Response contents from Symfony
- if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
- unset beresp.http.Surrogate-Control;
- set beresp.do_esi = true;
- }
-
- // Allow stale content, in case the backend goes down or cache is not fresh any more
- // make Varnish keep all objects for 1 hours beyond their TTL
- set beresp.grace = 1h;
-}
-
-// Handle purge
-// You may add FOSHttpCacheBundle tagging rules
-// See http://foshttpcache.readthedocs.org/en/latest/varnish-configuration.html#id4
-sub ez_purge {
-
- if (req.method == "BAN") {
- if (!client.ip ~ invalidators) {
- return (synth(405, "Method not allowed"));
- }
-
- if (req.http.X-Location-Id) {
- ban("obj.http.X-Location-Id ~ " + req.http.X-Location-Id);
- if (client.ip ~ debuggers) {
- set req.http.X-Debug = "Ban done for content connected to LocationId " + req.http.X-Location-Id;
- }
- return (synth(200, "Banned"));
- }
- }
-}
-
-// Sub-routine to get client user hash, for context-aware HTTP cache.
-sub ez_user_hash {
-
- // Prevent tampering attacks on the hash mechanism
- if (req.restarts == 0
- && (req.http.accept ~ "application/vnd.fos.user-context-hash"
- || req.http.x-user-hash
- )
- ) {
- return (synth(400));
- }
-
- if (req.restarts == 0 && (req.method == "GET" || req.method == "HEAD")) {
- // Get User (Context) hash, for varying cache by what user has access to.
- // https://doc.ez.no/display/EZP/Context+aware+HTTP+cache
-
- // Anonymous user w/o session => Use hardcoded anonymous hash to avoid backend lookup for hash
- if (req.http.Cookie !~ "eZSESSID" && !req.http.authorization) {
- // You may update this hash with the actual one for anonymous user
- // to get a better cache hit ratio across anonymous users.
- // Note: You should then update it every time anonymous user rights change.
- set req.http.X-User-Hash = "38015b703d82206ebc01d17a39c727e5";
- }
- // Pre-authenticate request to get shared cache, even when authenticated
- else {
- set req.http.x-fos-original-url = req.url;
- set req.http.x-fos-original-accept = req.http.accept;
- set req.http.x-fos-original-cookie = req.http.cookie;
- // Clean up cookie for the hash request to only keep session cookie, as hash cache will vary on cookie.
- set req.http.cookie = ";" + req.http.cookie;
- set req.http.cookie = regsuball(req.http.cookie, "; +", ";");
- set req.http.cookie = regsuball(req.http.cookie, ";(eZSESSID[^=]*)=", "; \1=");
- set req.http.cookie = regsuball(req.http.cookie, ";[^ ][^;]*", "");
- set req.http.cookie = regsuball(req.http.cookie, "^[; ]+|[; ]+$", "");
-
- set req.http.accept = "application/vnd.fos.user-context-hash";
- set req.url = "/_fos_user_context_hash";
-
- // Force the lookup, the backend must tell how to cache/vary response containing the user hash
-
- return (hash);
- }
- }
-
- // Rebuild the original request which now has the hash.
- if (req.restarts > 0
- && req.http.accept == "application/vnd.fos.user-context-hash"
- ) {
- set req.url = req.http.x-fos-original-url;
- set req.http.accept = req.http.x-fos-original-accept;
- set req.http.cookie = req.http.x-fos-original-cookie;
-
- unset req.http.x-fos-original-url;
- unset req.http.x-fos-original-accept;
- unset req.http.x-fos-original-cookie;
-
- // Force the lookup, the backend must tell not to cache or vary on the
- // user hash to properly separate cached data.
-
- return (hash);
- }
-}
-
-sub vcl_deliver {
- // On receiving the hash response, copy the hash header to the original
- // request and restart.
- if (req.restarts == 0
- && resp.http.content-type ~ "application/vnd.fos.user-context-hash"
- ) {
- set req.http.x-user-hash = resp.http.x-user-hash;
-
- return (restart);
- }
-
- // If we get here, this is a real response that gets sent to the client.
-
- // Remove the vary on context user hash, this is nothing public. Keep all
- // other vary headers.
- set resp.http.Vary = regsub(resp.http.Vary, "(?i),? *x-user-hash *", "");
- set resp.http.Vary = regsub(resp.http.Vary, "^, *", "");
- if (resp.http.Vary == "") {
- unset resp.http.Vary;
- }
-
- // Sanity check to prevent ever exposing the hash to a client.
- unset resp.http.x-user-hash;
-
- if (client.ip ~ debuggers) {
- if (obj.hits > 0) {
- set resp.http.X-Cache = "HIT";
- set resp.http.X-Cache-Hits = obj.hits;
- } else {
- set resp.http.X-Cache = "MISS";
- }
- }
-}
diff --git a/doc/varnish/vcl/varnish4_xkey.vcl b/doc/varnish/vcl/varnish4_xkey.vcl
index 981e2a8b00..ff19f6936a 100644
--- a/doc/varnish/vcl/varnish4_xkey.vcl
+++ b/doc/varnish/vcl/varnish4_xkey.vcl
@@ -26,10 +26,6 @@ sub vcl_recv {
// Add a Surrogate-Capability header to announce ESI support.
set req.http.Surrogate-Capability = "abc=ESI/1.0";
- // Varnish, in its default configuration, sends the X-Forwarded-For header but does not filter out Forwarded header
- // To be removed in Symfony 3.3
- unset req.http.Forwarded;
-
// Ensure that the Symfony Router generates URLs correctly with Varnish
if (req.http.X-Forwarded-Proto == "https" ) {
set req.http.X-Forwarded-Port = "443";
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000000..5a12e6762f
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+ tests
+
+
+
+
+
+ src
+
+ src/*Bundle/Resources
+ src/*/*Bundle/Resources
+ src/*/Bundle/*Bundle/Resources
+
+
+
+
diff --git a/src/.htaccess b/src/.htaccess
new file mode 100644
index 0000000000..fb1de45bdb
--- /dev/null
+++ b/src/.htaccess
@@ -0,0 +1,7 @@
+
+ Require all denied
+
+
+ Order deny,allow
+ Deny from all
+
diff --git a/app/logs/.keep b/var/cache/.gitkeep
similarity index 100%
rename from app/logs/.keep
rename to var/cache/.gitkeep
diff --git a/var/logs/.gitkeep b/var/logs/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/sessions/.gitkeep b/var/sessions/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/web/app.php b/web/app.php
index b8a2e86830..c2bbb3dd0c 100644
--- a/web/app.php
+++ b/web/app.php
@@ -5,6 +5,7 @@
// Ensure UTF-8 is used in string operations
setlocale(LC_CTYPE, 'C.UTF-8');
+require __DIR__ . '/../vendor/autoload.php';
// Environment is taken from "SYMFONY_ENV" variable, if not set, defaults to "prod"
$environment = getenv('SYMFONY_ENV');
@@ -18,27 +19,12 @@
$useDebugging = $environment === 'dev';
}
-// Depending on SYMFONY_CLASSLOADER_FILE use custom class loader, otherwise use bootstrap cache, or autoload in debug
-if ($loaderFile = getenv('SYMFONY_CLASSLOADER_FILE')) {
- require_once $loaderFile;
-} else {
- require_once __DIR__ . '/../app/autoload.php';
- if (!$useDebugging) {
- require_once __DIR__ . '/../app/bootstrap.php.cache';
- }
-}
-
if ($useDebugging) {
Debug::enable();
}
$kernel = new AppKernel($environment, $useDebugging);
-// we don't want to use the classes cache if we are in a debug session
-if (!$useDebugging) {
- $kernel->loadClassCache();
-}
-
// Depending on the SYMFONY_HTTP_CACHE environment variable, tells whether the internal HTTP Cache mechanism is to be used.
// If not set, or "", it is auto activated if _not_ in "dev" environment.
if (($useHttpCache = getenv('SYMFONY_HTTP_CACHE')) === false || $useHttpCache === '') {
@@ -47,23 +33,19 @@
// Load HTTP Cache ...
if ($useHttpCache) {
- // The standard HttpCache implementation can be overridden by setting the SYMFONY_HTTP_CACHE_CLASS environment variable.
- // NOTE: Make sure to setup composer config so it is *autoloadable*, or use "SYMFONY_CLASSLOADER_FILE" for this.
- if ($httpCacheClass = getenv('SYMFONY_HTTP_CACHE_CLASS')) {
- $kernel = new $httpCacheClass($kernel);
- } else {
- $kernel = new AppCache($kernel);
- }
-}
+ $kernel = new AppCache($kernel);
-$request = Request::createFromGlobals();
+ // When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter
+ Request::enableHttpMethodParameterOverride();
-// If you are behind one or more trusted reverse proxies, you might want to set them in SYMFONY_TRUSTED_PROXIES environment
-// variable in order to get correct client IP
-if ($trustedProxies = getenv('SYMFONY_TRUSTED_PROXIES')) {
- Request::setTrustedProxies(explode(',', $trustedProxies));
+ // If you are behind one or more trusted reverse proxies, you might want to set them in SYMFONY_TRUSTED_PROXIES environment
+ // variable in order to get correct client IP. NOTE: As per Symfony doc you will need to customize these lines for your proxy!
+ if ($trustedProxies = getenv('SYMFONY_TRUSTED_PROXIES')) {
+ Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL);
+ }
}
+$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
diff --git a/web/app_dev.php b/web/app_dev.php
index 836db57f9c..80b5241ca4 100644
--- a/web/app_dev.php
+++ b/web/app_dev.php
@@ -2,11 +2,16 @@
// This file is mainly here for use with symfony server commands.
// Recommended rewrite rules for apache and nginx does not use this.
+// If you don't want to setup permissions the proper way (in dev), just uncomment the following PHP line
+// read https://symfony.com/doc/current/setup.html#checking-symfony-application-configuration-and-setup
+// for more information
+//umask(0000);
+
// This check prevents access to debug front controllers that are deployed by accident to production servers.
-// Feel free to remove this, extend it, or make something more sophisticated at your own risk.
+// Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
- || !(in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1']) || PHP_SAPI === 'cli-server')
+ || !(in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'], true) || PHP_SAPI === 'cli-server')
) {
header('HTTP/1.0 403 Forbidden');
exit('You are not allowed to access this file. Check ' . basename(__FILE__) . ' for more information.');