From f3e585631259c7e4a984725705b2102101f58ab1 Mon Sep 17 00:00:00 2001 From: Vladimir Tsykun Date: Mon, 9 Jul 2018 17:27:47 +0300 Subject: [PATCH] Private packgist: - Symfony 3.4 LTS Upgrade - remove HWIOBundle, NelmioCorsBundle, NelmioSecurityBundle - don't delete package if github return 404 - disallow robots.txt - do not replace ssh on https for github repository - other fixes --- .gitignore | 49 +- app/.gitignore | 1 + app/AppKernel.php | 26 +- .../views/Profile/edit_content.html.twig | 12 +- .../views/Profile/show.html.twig | 13 +- .../views/Security}/login.html.twig | 13 +- .../views/Connect/connect_success.html.twig | 9 - .../views/Connect/registration.html.twig | 21 - .../Connect/registration_success.html.twig | 9 - .../HWIOAuthBundle/views/layout.html.twig | 7 - app/autoload.php | 23 - app/check.php | 84 - app/config/config.yml | 38 +- app/config/config_dev.yml | 4 - app/config/config_prod.yml | 48 - app/config/parameters.yml.dist | 23 +- app/config/routing.yml | 24 +- app/config/security.yml | 19 +- {app => bin}/console | 13 +- bin/symfony_requirements | 146 ++ composer.json | 27 +- composer.lock | 1928 ++++++++--------- .../WebBundle/Command/DumpPackagesCommand.php | 95 - .../Command/IndexPackagesCommand.php | 298 --- .../WebBundle/Command/RunWorkersCommand.php | 1 - .../Command/UpdatePackagesCommand.php | 11 +- .../WebBundle/Controller/ApiController.php | 23 +- .../WebBundle/Controller/GroupController.php | 4 +- .../Controller/PackageController.php | 120 +- .../Controller/ProviderController.php | 34 +- .../WebBundle/Controller/UserController.php | 27 +- .../WebBundle/Controller/WebController.php | 69 +- .../Security/ApiHttpBasicFactory.php | 35 +- .../WebBundle/Entity/GroupRepository.php | 7 +- src/Packagist/WebBundle/Entity/Package.php | 12 +- .../WebBundle/Entity/PackageRepository.php | 52 +- src/Packagist/WebBundle/Entity/User.php | 35 + src/Packagist/WebBundle/Entity/Version.php | 2 +- .../Handler/OAuthRegistrationFormHandler.php | 99 - .../Form/Type/PackagePermissionType.php | 2 +- .../WebBundle/Form/Type/PackageType.php | 2 +- src/Packagist/WebBundle/Menu/MenuBuilder.php | 2 +- .../WebBundle/Model/ValidatingArrayLoader.php | 32 + .../WebBundle/Package/ArchiveManager.php | 26 - .../WebBundle/Package/InMemoryDumper.php | 7 +- .../WebBundle/Package/SymlinkDumper.php | 726 ------- src/Packagist/WebBundle/Package/Updater.php | 39 +- .../WebBundle/PackagistWebBundle.php | 3 + .../WebBundle/Resources/config/security.yml | 3 +- .../WebBundle/Resources/config/services.yml | 21 +- .../WebBundle/Resources/public/css/main.css | 24 +- .../Resources/public/img/logo-small.png | Bin 4573 -> 15543 bytes .../WebBundle/Resources/public/img/logo.png | Bin 65810 -> 126405 bytes .../WebBundle/Resources/public/js/search.js | 203 -- .../Resources/translations/messages.en.yml | 4 +- .../Resources/views/About/about.html.twig | 7 +- .../Resources/views/Group/index.html.twig | 22 +- .../Resources/views/Package/package.html.twig | 108 + .../views/Package/viewPackage.html.twig | 10 +- .../Resources/views/User/profile.html.twig | 44 +- .../Resources/views/Web/index.html.twig | 68 +- .../Resources/views/Web/search.html.twig | 21 +- .../WebBundle/Resources/views/forms.html.twig | 4 +- .../Resources/views/layout.html.twig | 47 +- .../Security/Acl/PackagesAclVoter.php | 18 +- .../Security/Api/ApiTokenProvider.php | 8 +- .../Security/Provider/UserProvider.php | 56 +- .../WebBundle/Service/DistConfig.php | 46 +- .../WebBundle/Service/DistManager.php | 92 + .../WebBundle/Service/UpdaterWorker.php | 71 +- .../WebBundle/Twig/PackagistExtension.php | 22 +- .../WebBundle/Util/UserManipulator.php | 6 +- var/SymfonyRequirements.php | 810 +++++++ web/app.php | 19 +- web/app_dev.php | 16 +- web/apple-touch-icon-precomposed.png | Bin 8307 -> 0 bytes web/apple-touch-icon.png | Bin 8307 -> 0 bytes web/favicon.ico | Bin 20603 -> 5430 bytes web/robots.txt | 4 +- web/search.osd | 14 - web/touch-icon-192x192.png | Bin 8930 -> 0 bytes 81 files changed, 2795 insertions(+), 3273 deletions(-) create mode 100644 app/.gitignore rename app/Resources/{HWIOAuthBundle/views/Connect => FOSUserBundle/views/Security}/login.html.twig (81%) delete mode 100644 app/Resources/HWIOAuthBundle/views/Connect/connect_success.html.twig delete mode 100644 app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig delete mode 100644 app/Resources/HWIOAuthBundle/views/Connect/registration_success.html.twig delete mode 100644 app/Resources/HWIOAuthBundle/views/layout.html.twig delete mode 100644 app/autoload.php delete mode 100644 app/check.php rename {app => bin}/console (60%) create mode 100755 bin/symfony_requirements delete mode 100644 src/Packagist/WebBundle/Command/DumpPackagesCommand.php delete mode 100644 src/Packagist/WebBundle/Command/IndexPackagesCommand.php delete mode 100644 src/Packagist/WebBundle/Form/Handler/OAuthRegistrationFormHandler.php create mode 100644 src/Packagist/WebBundle/Model/ValidatingArrayLoader.php delete mode 100644 src/Packagist/WebBundle/Package/ArchiveManager.php delete mode 100644 src/Packagist/WebBundle/Package/SymlinkDumper.php delete mode 100644 src/Packagist/WebBundle/Resources/public/js/search.js create mode 100644 src/Packagist/WebBundle/Resources/views/Package/package.html.twig create mode 100644 src/Packagist/WebBundle/Service/DistManager.php create mode 100644 var/SymfonyRequirements.php delete mode 100644 web/apple-touch-icon-precomposed.png delete mode 100644 web/apple-touch-icon.png delete mode 100644 web/search.osd delete mode 100644 web/touch-icon-192x192.png diff --git a/.gitignore b/.gitignore index 649243bf..ed5e730e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,31 @@ -web/bundles/ -web/packages*.json -web/providers-*.json -web/p/ -app/config/parameters.yml -app/bootstrap* -app/cache/* -app/logs/* -bin/ -build/ -vendor/ -/.settings -/.buildpath -/.project -/.idea -composer.phar -/nbproject -.php_cs.cache +/web/bundles +/web/css +/web/js +/web/composer +/web/images +/web/uploads/users/* +/web/media/cache +/web/build.js +/var/password.dat +/var/password.json +/password.json +behat.yml +/.web-server-pid +/app/config/parameters.yml +/build/ +.idea +/phpunit.xml +/var/* +/var/cache/* +!var/cache/.gitkeep +!var/hook/.gitkeep +!var/hook/* +/var/logs/* +!var/logs/.gitkeep +!/var/sessions +/var/sessions/* +!var/sessions/.gitkeep +!var/SymfonyRequirements.php +/vendor/ +/web/bundles/ +/var/bin/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 00000000..249cf8f0 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/zipball/ diff --git a/app/AppKernel.php b/app/AppKernel.php index a0e3351c..4645f398 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -17,12 +17,9 @@ public function registerBundles() new Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle(), new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new FOS\UserBundle\FOSUserBundle(), - new HWI\Bundle\OAuthBundle\HWIOAuthBundle(), new Snc\RedisBundle\SncRedisBundle(), new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(), - new Nelmio\SecurityBundle\NelmioSecurityBundle(), new Knp\Bundle\MenuBundle\KnpMenuBundle(), - new Nelmio\CorsBundle\NelmioCorsBundle(), new Packagist\WebBundle\PackagistWebBundle(), ); @@ -34,8 +31,29 @@ public function registerBundles() return $bundles; } + public function getRootDir() + { + return __DIR__; + } + + public function getCacheDir() + { + return dirname(__DIR__).'/var/cache/'.$this->getEnvironment(); + } + + public function getLogDir() + { + return dirname(__DIR__).'/var/logs'; + } + public function registerContainerConfiguration(LoaderInterface $loader) { - $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); + $loader->load(function (\Symfony\Component\DependencyInjection\ContainerBuilder $container) { + $container->setParameter('container.autowiring.strict_mode', true); + $container->setParameter('container.dumper.inline_class_loader', true); + + $container->addObjectResource($this); + }); + $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml'); } } diff --git a/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig b/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig index 0dc16820..0ee2f394 100644 --- a/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig +++ b/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig @@ -1,4 +1,4 @@ -
+{{ form_start(form, {'attr': {'class': 'fos_user_profile_edit col-md-6', 'action': path('fos_user_profile_edit') }}) }} {{ form_errors(form) }}
@@ -40,15 +40,7 @@ -
- -
Using GitHub:
- - - - {{ (app.user.githubId ? 'profile.accounts_connected' : 'profile.connect_accounts')|trans }} - - +{{ form_end(form) }}
diff --git a/app/Resources/FOSUserBundle/views/Profile/show.html.twig b/app/Resources/FOSUserBundle/views/Profile/show.html.twig index 9dd48acb..0f7bd9a6 100644 --- a/app/Resources/FOSUserBundle/views/Profile/show.html.twig +++ b/app/Resources/FOSUserBundle/views/Profile/show.html.twig @@ -4,22 +4,25 @@ {% block fos_user_content %}
+ {% set isAdmin = is_granted('ROLE_ADMIN') %} {%- if app.user.apiToken %}

{{ 'profile.your_api_token'|trans }}

- +
-

{{ 'profile.api_token_explain'|trans({ '%path_about%':path('about') })|raw }}

- -
+

You need to authenticate to access their Composer repository, for example to enter credentials run command:

+
+composer config --global --auth http-basic.{{ app.request.getHttpHost() }} {{ user.username }} {{ user.apiToken }}
+        
+

The storage can be done either globally in the COMPOSER_HOME/auth.json file


{%- endif %} - {% if is_granted('ROLE_ADMIN') %} + {% if isAdmin %} {% embed "PackagistWebBundle:Web:list.html.twig" with {noLayout: 'true', showAutoUpdateWarning: true} %} {% block content_title %}

{{ 'packages.yours'|trans }}

diff --git a/app/Resources/HWIOAuthBundle/views/Connect/login.html.twig b/app/Resources/FOSUserBundle/views/Security/login.html.twig similarity index 81% rename from app/Resources/HWIOAuthBundle/views/Connect/login.html.twig rename to app/Resources/FOSUserBundle/views/Security/login.html.twig index 173c1243..0abcccc8 100644 --- a/app/Resources/HWIOAuthBundle/views/Connect/login.html.twig +++ b/app/Resources/FOSUserBundle/views/Security/login.html.twig @@ -18,11 +18,11 @@
{% if error is defined and error is not empty %}
- {{ error }} + {{ error.messageKey|trans(error.messageData, 'security') }}
{% endif %} -
+
@@ -58,13 +58,4 @@
{% endif %} - - {% for owner in hwi_oauth_resource_owners() %} - {% if not app.user %} -
- {% endif %} -
- Login with {{ owner | trans({}, 'HWIOAuthBundle') }}{% if not loop.last %}
{% endif %} -
- {% endfor %} {% endblock %} diff --git a/app/Resources/HWIOAuthBundle/views/Connect/connect_success.html.twig b/app/Resources/HWIOAuthBundle/views/Connect/connect_success.html.twig deleted file mode 100644 index 649eb53d..00000000 --- a/app/Resources/HWIOAuthBundle/views/Connect/connect_success.html.twig +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'HWIOAuthBundle::layout.html.twig' %} - -{% block hwi_oauth_content %} -
-

GitHub Login

-

{{ 'header.success' | trans({'%name%': userInformation.realName}, 'HWIOAuthBundle') }}

-

Continue to your profile.

-
-{% endblock hwi_oauth_content %} diff --git a/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig b/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig deleted file mode 100644 index 2e95adb3..00000000 --- a/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'HWIOAuthBundle::layout.html.twig' %} - -{% block hwi_oauth_content %} -
-

{{ 'header.register' | trans({'%name%': userInformation.realName}, 'HWIOAuthBundle') }}

-
-
- - {{ form_widget(form) }} -
- - {{ 'connect.registration.cancel' | trans({}, 'HWIOAuthBundle') }} -
- -
-
- {% if userInformation.profilePicture is not empty %} - - {% endif %} -
-{% endblock hwi_oauth_content %} diff --git a/app/Resources/HWIOAuthBundle/views/Connect/registration_success.html.twig b/app/Resources/HWIOAuthBundle/views/Connect/registration_success.html.twig deleted file mode 100644 index fd03e59d..00000000 --- a/app/Resources/HWIOAuthBundle/views/Connect/registration_success.html.twig +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'HWIOAuthBundle::layout.html.twig' %} - -{% block hwi_oauth_content %} -
-

GitHub Login

-

{{ 'header.registration_success' | trans({'%username%': app.user.username}, 'HWIOAuthBundle') }}

-

Continue to your profile.

-
-{% endblock hwi_oauth_content %} diff --git a/app/Resources/HWIOAuthBundle/views/layout.html.twig b/app/Resources/HWIOAuthBundle/views/layout.html.twig deleted file mode 100644 index 236d8bde..00000000 --- a/app/Resources/HWIOAuthBundle/views/layout.html.twig +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'PackagistWebBundle::layout.html.twig' %} - -{% block content %} -
- {% block hwi_oauth_content %}{% endblock %} -
-{% endblock %} diff --git a/app/autoload.php b/app/autoload.php deleted file mode 100644 index f101d984..00000000 --- a/app/autoload.php +++ /dev/null @@ -1,23 +0,0 @@ -You must set up the project dependencies by running composer install

- -EOF; - - if (PHP_SAPI === 'cli') { - $message = strip_tags($message); - } - - die($message); -} - -AnnotationRegistry::registerLoader(array($loader, 'loadClass')); - -return $loader; diff --git a/app/check.php b/app/check.php deleted file mode 100644 index c10f1ab2..00000000 --- a/app/check.php +++ /dev/null @@ -1,84 +0,0 @@ -='), sprintf('Checking that PHP version is at least 5.3.2 (%s installed)', phpversion()), 'Install PHP 5.3.2 or newer (current version is '.phpversion(), true); -check(ini_get('date.timezone'), 'Checking that the "date.timezone" setting is set', 'Set the "date.timezone" setting in php.ini (like Europe/Paris)', true); -check(is_writable(__DIR__.'/../app/cache'), sprintf('Checking that app/cache/ directory is writable'), 'Change the permissions of the app/cache/ directory so that the web server can write in it', true); -check(is_writable(__DIR__.'/../app/logs'), sprintf('Checking that the app/logs/ directory is writable'), 'Change the permissions of the app/logs/ directory so that the web server can write in it', true); -check(function_exists('json_encode'), 'Checking that the json_encode() is available', 'Install and enable the json extension', true); - -// warnings -echo_title("Optional checks"); -check(class_exists('DomDocument'), 'Checking that the PHP-XML module is installed', 'Install and enable the php-xml module', false); -check(defined('LIBXML_COMPACT'), 'Checking that the libxml version is at least 2.6.21', 'Upgrade your php-xml module with a newer libxml', false); -check(function_exists('token_get_all'), 'Checking that the token_get_all() function is available', 'Install and enable the Tokenizer extension (highly recommended)', false); -check(function_exists('mb_strlen'), 'Checking that the mb_strlen() function is available', 'Install and enable the mbstring extension', false); -check(function_exists('iconv'), 'Checking that the iconv() function is available', 'Install and enable the iconv extension', false); -check(function_exists('utf8_decode'), 'Checking that the utf8_decode() is available', 'Install and enable the XML extension', false); -check(function_exists('posix_isatty'), 'Checking that the posix_isatty() is available', 'Install and enable the php_posix extension (used to colorized the CLI output)', false); -check(class_exists('Locale'), 'Checking that the intl extension is available', 'Install and enable the intl extension (used for validators)', false); - -$accelerator = - (function_exists('apc_store') && ini_get('apc.enabled')) - || - function_exists('eaccelerator_put') && ini_get('eaccelerator.enable') - || - function_exists('xcache_set') -; -check($accelerator, 'Checking that a PHP accelerator is installed', 'Install a PHP accelerator like APC (highly recommended)', false); - -check(!ini_get('short_open_tag'), 'Checking that php.ini has short_open_tag set to off', 'Set short_open_tag to off in php.ini', false); -check(!ini_get('magic_quotes_gpc'), 'Checking that php.ini has magic_quotes_gpc set to off', 'Set magic_quotes_gpc to off in php.ini', false); -check(!ini_get('register_globals'), 'Checking that php.ini has register_globals set to off', 'Set register_globals to off in php.ini', false); -check(!ini_get('session.auto_start'), 'Checking that php.ini has session.auto_start set to off', 'Set session.auto_start to off in php.ini', false); - -echo_title("Optional checks (Doctrine)"); - -check(class_exists('PDO'), 'Checking that PDO is installed', 'Install PDO (mandatory for Doctrine)', false); -if (class_exists('PDO')) { - $drivers = PDO::getAvailableDrivers(); - check(count($drivers), 'Checking that PDO has some drivers installed: '.implode(', ', $drivers), 'Install PDO drivers (mandatory for Doctrine)'); -} - -/** - * Checks a configuration. - */ -function check($boolean, $message, $help = '', $fatal = false) -{ - echo $boolean ? " OK " : sprintf("\n\n[[%s]] ", $fatal ? ' ERROR ' : 'WARNING'); - echo sprintf("$message%s\n", $boolean ? '' : ': FAILED'); - - if (!$boolean) { - echo " *** $help ***\n"; - if ($fatal) { - die("You must fix this problem before resuming the check.\n"); - } - } -} - -function echo_title($title) -{ - echo "\n** $title **\n\n"; -} diff --git a/app/config/config.yml b/app/config/config.yml index 3efe2b65..53ebd72d 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -33,7 +33,6 @@ twig: debug: '%kernel.debug%' strict_variables: '%kernel.debug%' globals: - google_analytics: '%google_analytics%' packagist_host: '%packagist_host%' # Doctrine Configuration @@ -44,6 +43,7 @@ doctrine: dbname: '%database_name%' user: '%database_user%' password: '%database_password%' + port: '%database_port%' # See https://github.com/sonata-project/SonataAdminBundle/issues/3342 orm: auto_generate_proxy_classes: '%kernel.debug%' @@ -105,6 +105,7 @@ swiftmailer: password: '%mailer_password%' encryption: '%mailer_encryption%' auth_mode: '%mailer_auth_mode%' + port: '%mailer_port%' spool: { type: memory } fos_user: @@ -117,40 +118,7 @@ fos_user: sender_name: '%mailer_from_name%' profile: form: - type: packagist_user_profile - -hwi_oauth: - firewall_names: [main] - connect: - account_connector: packagist.user_provider - registration_form_handler: packagist.oauth.registration_form_handler - registration_form: packagist.oauth.registration_form - fosub: - username_iterations: 30 - properties: - github: githubId - resource_owners: - github: - type: github - client_id: '%github.client_id%' - client_secret: '%github.client_secret%' - options: - csrf: true - -nelmio_cors: - defaults: - allow_origin: ['*'] - allow_headers: ['*'] - max_age: 3600 - paths: - '^/packages/list\.json$': - allow_methods: ['GET'] - forced_allow_origin_value: '*' - '^/search\.json$': - allow_methods: ['GET'] - '^/packages/[^/]+/[^/]+\.json$': - allow_methods: ['GET'] - forced_allow_origin_value: '*' + type: Packagist\WebBundle\Form\Type\ProfileFormType packagist_web: archive: true diff --git a/app/config/config_dev.yml b/app/config/config_dev.yml index 28aa7c6d..47855aa0 100644 --- a/app/config/config_dev.yml +++ b/app/config/config_dev.yml @@ -42,9 +42,5 @@ monolog: VERBOSITY_DEBUG: DEBUG channels: ["doctrine"] -hwi_oauth: - http_client: - verify_peer: false - #assetic: # use_controller: true diff --git a/app/config/config_prod.yml b/app/config/config_prod.yml index aea91841..b219ca72 100644 --- a/app/config/config_prod.yml +++ b/app/config/config_prod.yml @@ -64,51 +64,3 @@ framework: cookie_secure: '%force_ssl%' validation: cache: '%validation_cache_backend%' - -nelmio_security: - clickjacking: - paths: - '^/.*': DENY - forced_ssl: - enabled: '%force_ssl%' - hsts_max_age: 31104000 # 1y - csp: - enabled: true - report_logger_service: logger - hosts: [] - content_types: [] - enforce: - browser_adaptive: - enabled: false - default-src: - - 'self' - script-src: - - 'self' - - 'unsafe-inline' - - 'unsafe-eval' - - 'https://cdn.jsdelivr.net/' - - 'https://ssl.google-analytics.com/' - connect-src: - - 'self' - - '*.algolia.net' - - '*.algolianet.com' - img-src: - - 'self' - - 'https://www.gravatar.com/' - - 'https://camo.githubusercontent.com/' - - 'https://user-images.githubusercontent.com/' - - 'https://raw.githubusercontent.com/' - - 'https://raw.github.com/' - - 'https://github.com/' - - 'https://gitlab.com/' - - 'https://ssl.google-analytics.com/' - - 'http://www.google-analytics.com/' - style-src: - - 'self' - - 'unsafe-inline' - - 'https://cdn.jsdelivr.net/' - - 'https://fonts.googleapis.com/' - font-src: - - 'self' - - 'https://fonts.gstatic.com/' - block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist index 22a159cd..e256ed51 100644 --- a/app/config/parameters.yml.dist +++ b/app/config/parameters.yml.dist @@ -1,9 +1,10 @@ parameters: - database_driver: pdo_mysql + database_driver: pdo_pgsql database_host: localhost database_name: packagist - database_user: root - database_password: + database_user: postgres + database_password: ~ + database_port: ~ database_name_test: packagist_test mailer_transport: @@ -13,12 +14,9 @@ parameters: mailer_from_email: admin@example.org mailer_from_name: Admin Team mailer_encryption: tls + mailer_port: ~ mailer_auth_mode: login - # packagist_host: example.org - # router.request_context.host: '%packagist_host%' - # router.request_context.scheme: https - redis_dsn: redis://localhost/1 redis_dsn_test: redis://127.0.0.1/14 redis_session_dsn: redis://localhost/2 @@ -28,10 +26,6 @@ parameters: google_analytics: ga_key: - # set those to values obtained by creating an application at https://github.com/settings/applications - github.client_id: CHANGE_ME_IN_PROD - github.client_secret: CHANGE_ME_IN_PROD - # -- performance features -- # set both to apc to optimize things if it is available validation_cache_backend: ~ @@ -48,8 +42,5 @@ parameters: # e.g. ['.*\.?packagist\.org$'] to allow packagist.org and all subdomains as valid hosts trusted_hosts: ~ - # -- Algolia credentials -- - algolia.app_id: CHANGE_ME - algolia.admin_key: CHANGE_ME - algolia.search_key: CHANGE_ME - algolia.index_name: 'packagist' + # Host for download zip + packagist_dist_host: ~ diff --git a/app/config/routing.yml b/app/config/routing.yml index cc18a330..c73d7ca6 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -18,25 +18,5 @@ fos_user_resetting: fos_user_change_password: resource: '@FOSUserBundle/Resources/config/routing/change_password.xml' - -hwi_oauth_connect: - resource: '@HWIOAuthBundle/Resources/config/routing/connect.xml' - prefix: /connect - -# overrides the fosub /login page -hwi_oauth_login: - resource: '@HWIOAuthBundle/Resources/config/routing/login.xml' - prefix: /login - -hwi_oauth_redirect: - resource: '@HWIOAuthBundle/Resources/config/routing/redirect.xml' - prefix: /login - -github_check: - path: /login/check-github - -logout: - path: /logout - -login_check: - path: /login_check +fos_user: + resource: "@FOSUserBundle/Resources/config/routing/security.xml" diff --git a/app/config/security.yml b/app/config/security.yml index 67398fb8..9e94b275 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -11,14 +11,8 @@ security: firewalls: packages: - pattern: (^(/packages.json$|/p/|/zipball/|/downloads/))+ + pattern: (^(/packages.json$|/p/|/zipball/|/downloads/|/api/))+ api_basic: true - remember_me: - secret: '%remember_me.secret%' - user_providers: packagist - name: pauth - always_remember_me: true - lifetime: 31104000 # 1y main: pattern: .* @@ -36,13 +30,6 @@ security: lifetime: 31104000 # 1y logout: true anonymous: true - oauth: - resource_owners: - github: '/login/check-github' - login_path: /login - failure_path: /login - oauth_user_provider: - service: packagist.user_provider switch_user: provider: packagist @@ -56,10 +43,12 @@ security: # URL of FOSUserBundle which need to be available to anonymous users - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/login/, role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/resetting/, role: IS_AUTHENTICATED_ANONYMOUSLY } # Packagist - - { path: (^(/change-password|/profile/))+, role: ROLE_USER } + - { path: (^(/change-password|/profile/|/search|/logout|/packages/|/versions/))+, role: ROLE_USER } - { path: (^(/packages.json$|/p/|/zipball/|/downloads/))+, role: ROLE_USER } + - { path: ^/$, role: ROLE_USER } # Secured part of the site # This config requires being logged for the whole site and having the admin role for the admin part. diff --git a/app/console b/bin/console similarity index 60% rename from app/console rename to bin/console index ed6d4ad1..0629023a 100755 --- a/app/console +++ b/bin/console @@ -1,25 +1,22 @@ #!/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 00000000..a7bf65a1 --- /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 2dad07f1..ca5fc6f9 100644 --- a/composer.json +++ b/composer.json @@ -31,8 +31,8 @@ }, "require": { "php": ">=7.0", - "symfony/symfony": "^2.8", - "doctrine/orm": "^2.4", + "symfony/symfony": "^3.4", + "doctrine/orm": "^2.6", "doctrine/doctrine-bundle": "^1.2", "doctrine/doctrine-cache-bundle": "^1.3", "twig/extensions": "^1.0", @@ -44,9 +44,8 @@ "jms/security-extra-bundle": "^1.5", "jms/di-extra-bundle": "^1.4", "oro/doctrine-extensions": "^1.2", - "composer/composer": "^1.3@dev", - "friendsofsymfony/user-bundle": "^2.0@dev", - "nelmio/security-bundle": "^2.4", + "composer/composer": "^1.6", + "friendsofsymfony/user-bundle": "^2.1", "predis/predis": "^1.0", "snc/redis-bundle": "^2.0", "white-october/pagerfanta-bundle": "^1.0", @@ -56,30 +55,32 @@ "pagerfanta/pagerfanta": "^1.0", "knplabs/knp-menu-bundle": "^2.1", "ezyang/htmlpurifier": "^4.6", - "nelmio/cors-bundle": "^1.4", "cebe/markdown": "^1.1", - "algolia/algoliasearch-client-php": "^1.18", "seld/signal-handler": "^1.1" }, - "_comment": ["fos user bundle 2.0.0 tag needed"], "require-dev": { "symfony/phpunit-bridge": "^2.7 || ^3.0", "phpunit/phpunit": "^6.5" }, "scripts": { - "post-install-cmd": [ + "symfony-scripts": [ "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache", - "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets" + "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets", + "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile", + "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget" + ], + "post-install-cmd": [ + "@symfony-scripts" ], "post-update-cmd": [ - "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", - "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache", - "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets" + "@symfony-scripts" ] }, "extra": { "symfony-app-dir": "app", + "symfony-bin-dir": "bin", + "symfony-var-dir": "var", "symfony-web-dir": "web", "symfony-assets-install": "symlink" } diff --git a/composer.lock b/composer.lock index 2597220e..66ac9357 100644 --- a/composer.lock +++ b/composer.lock @@ -4,71 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "42db6730d583728ee1aef7f053b4a196", + "content-hash": "05de88095f996480c00ec77c2893fb7b", "packages": [ - { - "name": "algolia/algoliasearch-client-php", - "version": "1.20.0", - "source": { - "type": "git", - "url": "https://github.com/algolia/algoliasearch-client-php.git", - "reference": "3daee8d55c1d84eff227fd99054e78ddc196f309" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/algolia/algoliasearch-client-php/zipball/3daee8d55c1d84eff227fd99054e78ddc196f309", - "reference": "3daee8d55c1d84eff227fd99054e78ddc196f309", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0", - "satooshi/php-coveralls": "0.6.*" - }, - "type": "library", - "autoload": { - "psr-0": { - "AlgoliaSearch": "src/", - "AlgoliaSearch\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Algolia Team", - "email": "contact@algolia.com" - }, - { - "name": "Ryan T. Catlin", - "email": "ryan.catlin@gmail.com" - }, - { - "name": "Jonathan H. Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Algolia Search API Client for PHP", - "homepage": "https://github.com/algolia/algoliasearch-client-php", - "time": "2017-08-30T08:28:40+00:00" - }, { "name": "cebe/markdown", - "version": "1.1.1", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/cebe/markdown.git", - "reference": "c30eb5e01fe021cc5bba2f9ee0eeef96d4931166" + "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cebe/markdown/zipball/c30eb5e01fe021cc5bba2f9ee0eeef96d4931166", - "reference": "c30eb5e01fe021cc5bba2f9ee0eeef96d4931166", + "url": "https://api.github.com/repos/cebe/markdown/zipball/9bac5e971dd391e2802dca5400bbeacbaea9eb86", + "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86", "shasum": "" }, "require": { @@ -86,7 +35,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -115,7 +64,7 @@ "markdown", "markdown-extra" ], - "time": "2016-09-14T20:40:20+00:00" + "time": "2018-03-26T11:24:36+00:00" }, { "name": "composer/ca-bundle", @@ -175,23 +124,22 @@ }, { "name": "composer/composer", - "version": "dev-master", + "version": "1.6.5", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "22025f2e29dbcae962efaec49e3c8677edde8a6f" + "reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/22025f2e29dbcae962efaec49e3c8677edde8a6f", - "reference": "22025f2e29dbcae962efaec49e3c8677edde8a6f", + "url": "https://api.github.com/repos/composer/composer/zipball/b184a92419cc9a9c4c6a09db555a94d441cb11c9", + "reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0", "composer/semver": "^1.0", "composer/spdx-licenses": "^1.2", - "composer/xdebug-handler": "^1.1", "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", "php": "^5.3.2 || ^7.0", "psr/log": "^1.0", @@ -221,7 +169,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -252,7 +200,7 @@ "dependency", "package" ], - "time": "2018-05-04T09:47:45+00:00" + "time": "2018-05-04T09:44:59+00:00" }, { "name": "composer/semver", @@ -377,64 +325,23 @@ ], "time": "2018-04-30T10:33:04+00:00" }, - { - "name": "composer/xdebug-handler", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/c919dc6c62e221fc6406f861ea13433c0aa24f08", - "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0", - "psr/log": "^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "time": "2018-04-11T15:42:36+00:00" - }, { "name": "container-interop/container-interop", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/container-interop/container-interop.git", - "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", - "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", "shasum": "" }, + "require": { + "psr/container": "^1.0" + }, "type": "library", "autoload": { "psr-4": { @@ -446,34 +353,35 @@ "MIT" ], "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "time": "2014-12-30T15:22:37+00:00" + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14T19:40:03+00:00" }, { "name": "doctrine/annotations", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", "shasum": "" }, "require": { "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -514,37 +422,41 @@ "docblock", "parser" ], - "time": "2017-02-24T16:22:25+00:00" + "time": "2017-12-06T07:11:42+00:00" }, { "name": "doctrine/cache", - "version": "v1.6.2", + "version": "v1.7.1", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" + "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", + "url": "https://api.github.com/repos/doctrine/cache/zipball/b3217d58609e9c8e661cd41357a54d926c4a2a1a", + "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a", "shasum": "" }, "require": { - "php": "~5.5|~7.0" + "php": "~7.1" }, "conflict": { "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" + "alcaeus/mongo-php-adapter": "^1.1", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^5.7", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -584,24 +496,24 @@ "cache", "caching" ], - "time": "2017-07-22T12:49:21+00:00" + "time": "2017-08-25T07:02:50+00:00" }, { "name": "doctrine/collections", - "version": "v1.4.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba" + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/1a4fb7e902202c33cce8c55989b945612943c2ba", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/coding-standard": "~0.1@dev", @@ -651,37 +563,43 @@ "collections", "iterator" ], - "time": "2017-01-03T10:49:41+00:00" + "time": "2017-07-22T10:37:32+00:00" }, { "name": "doctrine/common", - "version": "v2.7.3", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "4acb8f89626baafede6ee5475bc5844096eba8a9" + "reference": "a210246d286c77d2b89040f8691ba7b3a713d2c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/4acb8f89626baafede6ee5475bc5844096eba8a9", - "reference": "4acb8f89626baafede6ee5475bc5844096eba8a9", + "url": "https://api.github.com/repos/doctrine/common/zipball/a210246d286c77d2b89040f8691ba7b3a713d2c1", + "reference": "a210246d286c77d2b89040f8691ba7b3a713d2c1", "shasum": "" }, "require": { - "doctrine/annotations": "1.*", - "doctrine/cache": "1.*", - "doctrine/collections": "1.*", - "doctrine/inflector": "1.*", - "doctrine/lexer": "1.*", - "php": "~5.6|~7.0" + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^5.4.6" + "doctrine/coding-standard": "^1.0", + "phpunit/phpunit": "^6.3", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7.x-dev" + "dev-master": "2.9.x-dev" } }, "autoload": { @@ -713,10 +631,14 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], "description": "Common Library for Doctrine projects", - "homepage": "http://www.doctrine-project.org", + "homepage": "https://www.doctrine-project.org", "keywords": [ "annotations", "collections", @@ -724,29 +646,36 @@ "persistence", "spl" ], - "time": "2017-07-22T08:35:12+00:00" + "time": "2018-07-12T21:16:12+00:00" }, { "name": "doctrine/dbal", - "version": "v2.5.13", + "version": "v2.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "729340d8d1eec8f01bff708e12e449a3415af873" + "reference": "5140a64c08b4b607b9bedaae0cedd26f04a0e621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/729340d8d1eec8f01bff708e12e449a3415af873", - "reference": "729340d8d1eec8f01bff708e12e449a3415af873", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/5140a64c08b4b607b9bedaae0cedd26f04a0e621", + "reference": "5140a64c08b4b607b9bedaae0cedd26f04a0e621", "shasum": "" }, "require": { - "doctrine/common": ">=2.4,<2.8-dev", - "php": ">=5.3.2" + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "4.*", - "symfony/console": "2.*||^3.0" + "doctrine/coding-standard": "^4.0", + "jetbrains/phpstorm-stubs": "^2018.1.2", + "phpstan/phpstan": "^0.10.1", + "phpunit/phpunit": "^7.1.2", + "phpunit/phpunit-mock-objects": "!=3.2.4,!=3.2.5", + "symfony/console": "^2.0.5|^3.0|^4.0", + "symfony/phpunit-bridge": "^3.4.5|^4.0.5" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -757,7 +686,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5.x-dev" + "dev-master": "2.8.x-dev", + "dev-develop": "3.0.x-dev" } }, "autoload": { @@ -795,20 +725,20 @@ "persistence", "queryobject" ], - "time": "2017-07-22T20:44:48+00:00" + "time": "2018-07-13T03:16:35+00:00" }, { "name": "doctrine/doctrine-bundle", - "version": "1.8.1", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "eb6e4fb904a459be28872765ab6e2d246aac7c87" + "reference": "703fad32e4c8cbe609caf45a71a1d4266c830f0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/eb6e4fb904a459be28872765ab6e2d246aac7c87", - "reference": "eb6e4fb904a459be28872765ab6e2d246aac7c87", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/703fad32e4c8cbe609caf45a71a1d4266c830f0f", + "reference": "703fad32e4c8cbe609caf45a71a1d4266c830f0f", "shasum": "" }, "require": { @@ -819,13 +749,13 @@ "symfony/console": "~2.7|~3.0|~4.0", "symfony/dependency-injection": "~2.7|~3.0|~4.0", "symfony/doctrine-bridge": "~2.7|~3.0|~4.0", - "symfony/framework-bundle": "~2.7|~3.0|~4.0" + "symfony/framework-bundle": "^2.7.22|~3.0|~4.0" }, "conflict": { "symfony/http-foundation": "<2.6" }, "require-dev": { - "doctrine/orm": "~2.3", + "doctrine/orm": "~2.4", "phpunit/phpunit": "^4.8.36|^5.7|^6.4", "satooshi/php-coveralls": "^1.0", "symfony/phpunit-bridge": "~2.7|~3.0|~4.0", @@ -880,43 +810,43 @@ "orm", "persistence" ], - "time": "2017-11-24T13:09:19+00:00" + "time": "2018-04-19T14:07:39+00:00" }, { "name": "doctrine/doctrine-cache-bundle", - "version": "1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineCacheBundle.git", - "reference": "9baecbd6bfdd1123b0cf8c1b88fee0170a84ddd1" + "reference": "4c8e363f96427924e7e519c5b5119b4f54512697" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineCacheBundle/zipball/9baecbd6bfdd1123b0cf8c1b88fee0170a84ddd1", - "reference": "9baecbd6bfdd1123b0cf8c1b88fee0170a84ddd1", + "url": "https://api.github.com/repos/doctrine/DoctrineCacheBundle/zipball/4c8e363f96427924e7e519c5b5119b4f54512697", + "reference": "4c8e363f96427924e7e519c5b5119b4f54512697", "shasum": "" }, "require": { "doctrine/cache": "^1.4.2", "doctrine/inflector": "~1.0", "php": ">=5.3.2", - "symfony/doctrine-bridge": "~2.2|~3.0|~4.0" + "symfony/doctrine-bridge": "~2.7|~3.3|~4.0" }, "require-dev": { "instaclick/coding-standard": "~1.1", "instaclick/object-calisthenics-sniffs": "dev-master", "instaclick/symfony2-coding-standard": "dev-remaster", - "phpunit/phpunit": "~4", + "phpunit/phpunit": "~4|~5", "predis/predis": "~0.8", "satooshi/php-coveralls": "^1.0", "squizlabs/php_codesniffer": "~1.5", - "symfony/console": "~2.2|~3.0|~4.0", - "symfony/finder": "~2.2|~3.0|~4.0", - "symfony/framework-bundle": "~2.2|~3.0|~4.0", - "symfony/phpunit-bridge": "~2.7|~3.0|~4.0", - "symfony/security-acl": "~2.3|~3.0", - "symfony/validator": "~2.2|~3.0|~4.0", - "symfony/yaml": "~2.2|~3.0|~4.0" + "symfony/console": "~2.7|~3.3|~4.0", + "symfony/finder": "~2.7|~3.3|~4.0", + "symfony/framework-bundle": "~2.7|~3.3|~4.0", + "symfony/phpunit-bridge": "~2.7|~3.3|~4.0", + "symfony/security-acl": "~2.7|~3.3", + "symfony/validator": "~2.7|~3.3|~4.0", + "symfony/yaml": "~2.7|~3.3|~4.0" }, "suggest": { "symfony/security-acl": "For using this bundle to cache ACLs" @@ -968,24 +898,98 @@ "cache", "caching" ], - "time": "2017-10-12T17:23:29+00:00" + "time": "2018-03-27T09:22:12+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" }, { "name": "doctrine/inflector", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462" + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462", - "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.1" }, "require-dev": { "phpunit/phpunit": "^6.2" @@ -993,7 +997,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -1035,36 +1039,36 @@ "singularize", "string" ], - "time": "2017-07-22T12:18:28+00:00" + "time": "2018-01-09T20:05:19+00:00" }, { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -1089,7 +1093,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "doctrine/lexer", @@ -1147,38 +1151,40 @@ }, { "name": "doctrine/orm", - "version": "v2.5.14", + "version": "v2.6.2", "source": { "type": "git", "url": "https://github.com/doctrine/doctrine2.git", - "reference": "810a7baf81462a5ddf10e8baa8cb94b6eec02754" + "reference": "d2b4dd71d2a276edd65d0c170375b445f8a4a4a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/810a7baf81462a5ddf10e8baa8cb94b6eec02754", - "reference": "810a7baf81462a5ddf10e8baa8cb94b6eec02754", + "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/d2b4dd71d2a276edd65d0c170375b445f8a4a4a8", + "reference": "d2b4dd71d2a276edd65d0c170375b445f8a4a4a8", "shasum": "" }, "require": { - "doctrine/cache": "~1.4", - "doctrine/collections": "~1.2", - "doctrine/common": ">=2.5-dev,<2.9-dev", - "doctrine/dbal": ">=2.5-dev,<2.7-dev", - "doctrine/instantiator": "^1.0.1", + "doctrine/annotations": "~1.5", + "doctrine/cache": "~1.6", + "doctrine/collections": "^1.4", + "doctrine/common": "^2.7.1", + "doctrine/dbal": "^2.6", + "doctrine/instantiator": "~1.1", "ext-pdo": "*", - "php": ">=5.4", - "symfony/console": "~2.5|~3.0|~4.0" + "php": "^7.1", + "symfony/console": "~3.0|~4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0", - "symfony/yaml": "~2.3|~3.0|~4.0" + "doctrine/coding-standard": "^1.0", + "phpunit/phpunit": "^6.5", + "squizlabs/php_codesniffer": "^3.2", + "symfony/yaml": "~3.4|~4.0" }, "suggest": { "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" }, "bin": [ - "bin/doctrine", - "bin/doctrine.php" + "bin/doctrine" ], "type": "library", "extra": { @@ -1187,8 +1193,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\ORM\\": "lib/" + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" } }, "notification-url": "https://packagist.org/downloads/", @@ -1211,6 +1217,10 @@ { "name": "Jonathan Wage", "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], "description": "Object-Relational-Mapper for PHP", @@ -1219,100 +1229,122 @@ "database", "orm" ], - "time": "2017-12-17T02:57:51+00:00" + "time": "2018-07-12T20:47:13+00:00" }, { - "name": "ezyang/htmlpurifier", - "version": "v4.10.0", + "name": "doctrine/persistence", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "d85d39da4576a6934b72480be6978fb10c860021" + "url": "https://github.com/doctrine/persistence.git", + "reference": "17896f6d56a2794a1619e019596ae627aabd8fd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021", - "reference": "d85d39da4576a6934b72480be6978fb10c860021", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/17896f6d56a2794a1619e019596ae627aabd8fd5", + "reference": "17896f6d56a2794a1619e019596ae627aabd8fd5", "shasum": "" }, "require": { - "php": ">=5.2" + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" }, "require-dev": { - "simpletest/simpletest": "^1.1" + "doctrine/coding-standard": "^4.0", + "phpstan/phpstan": "^0.8", + "phpunit/phpunit": "^7.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-0": { - "HTMLPurifier": "library/" - }, - "files": [ - "library/HTMLPurifier.composer.php" - ] + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL" + "MIT" ], "authors": [ { - "name": "Edward Z. Yang", - "email": "admin@htmlpurifier.org", - "homepage": "http://ezyang.com" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], - "description": "Standards compliant HTML filter written in PHP", - "homepage": "http://htmlpurifier.org/", + "description": "Doctrine Persistence abstractions.", + "homepage": "https://doctrine-project.org/projects/persistence.html", "keywords": [ - "html" + "persistence" ], - "time": "2018-02-23T01:58:20+00:00" + "time": "2018-06-14T18:57:48+00:00" }, { - "name": "friendsofsymfony/user-bundle", - "version": "dev-master", + "name": "doctrine/reflection", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/FriendsOfSymfony/FOSUserBundle.git", - "reference": "528f0a93aebb641a0bc6471cc24562fbd01432cb" + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSUserBundle/zipball/528f0a93aebb641a0bc6471cc24562fbd01432cb", - "reference": "528f0a93aebb641a0bc6471cc24562fbd01432cb", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", "shasum": "" }, "require": { - "php": ">=5.3.9", - "symfony/form": "~2.3|~3.0", - "symfony/framework-bundle": "~2.3|~3.0", - "symfony/security-bundle": "~2.3|~3.0", - "symfony/twig-bundle": "~2.3|~3.0" - }, - "conflict": { - "symfony/doctrine-bridge": "<2.3" + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" }, "require-dev": { - "doctrine/doctrine-bundle": "~1.3", - "swiftmailer/swiftmailer": "~4.3|~5", - "symfony/console": "~2.3|~3.0", - "symfony/phpunit-bridge": "~2.7|~3.0", - "symfony/validator": "~2.3|~3.0", - "symfony/yaml": "~2.3|~3.0", - "willdurand/propel-typehintable-behavior": "~1.0" - }, - "suggest": { - "willdurand/propel-typehintable-behavior": "Needed when using the propel implementation" + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" }, - "type": "symfony-bundle", + "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "FOS\\UserBundle\\": "" + "Doctrine\\Common\\": "lib/Doctrine/Common" } }, "notification-url": "https://packagist.org/downloads/", @@ -1321,75 +1353,115 @@ ], "authors": [ { - "name": "Christophe Coevoet", - "email": "stof@notk.org" + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, { - "name": "FriendsOfSymfony Community", - "homepage": "https://github.com/friendsofsymfony/FOSUserBundle/contributors" - }, + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { - "name": "Thibault Duplessis", - "email": "thibault.duplessis@gmail.com" + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" } ], - "description": "Symfony FOSUserBundle", - "homepage": "http://friendsofsymfony.github.com", + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", "keywords": [ - "User management" + "reflection" ], - "time": "2016-09-09T10:00:40+00:00" + "time": "2018-06-14T14:45:07+00:00" }, { - "name": "hwi/oauth-bundle", - "version": "0.4.2", + "name": "ezyang/htmlpurifier", + "version": "v4.10.0", "source": { "type": "git", - "url": "https://github.com/hwi/HWIOAuthBundle.git", - "reference": "2554f2b2947d1614d9e8b04800967b175b0afd8a" + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "d85d39da4576a6934b72480be6978fb10c860021" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hwi/HWIOAuthBundle/zipball/2554f2b2947d1614d9e8b04800967b175b0afd8a", - "reference": "2554f2b2947d1614d9e8b04800967b175b0afd8a", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021", + "reference": "d85d39da4576a6934b72480be6978fb10c860021", "shasum": "" }, "require": { - "kriswallsmith/buzz": "~0.13", - "php": ">=5.3.3", - "symfony/form": "~2.3", - "symfony/framework-bundle": "~2.3", - "symfony/options-resolver": "~2.3", - "symfony/security-bundle": "~2.3", - "symfony/yaml": "~2.3" - }, - "conflict": { - "twig/twig": "<1.12" + "php": ">=5.2" }, "require-dev": { - "doctrine/orm": "~2.3", - "friendsofsymfony/user-bundle": "~1.3|~2.0", - "phpunit/phpunit": "~4.8|~5.0", - "symfony/phpunit-bridge": "~2.7", - "symfony/property-access": "~2.3", - "symfony/twig-bundle": "~2.3", - "symfony/validator": "~2.3" + "simpletest/simpletest": "^1.1" }, - "suggest": { - "doctrine/doctrine-bundle": "to use Doctrine user provider", - "friendsofsymfony/user-bundle": "to connect FOSUB with this bundle", - "symfony/property-access": "to use FOSUB integration with this bundle", - "symfony/twig-bundle": "to use the Twig hwi_oauth_* functions" + "type": "library", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ] }, - "type": "symfony-bundle", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "time": "2018-02-23T01:58:20+00:00" + }, + { + "name": "fig/link-util", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link-util.git", + "reference": "1a07821801a148be4add11ab0603e4af55a72fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link-util/zipball/1a07821801a148be4add11ab0603e4af55a72fac", + "reference": "1a07821801a148be4add11ab0603e4af55a72fac", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "psr/link": "~1.0@dev" + }, + "require-dev": { + "phpunit/phpunit": "^5.1", + "squizlabs/php_codesniffer": "^2.3.1" + }, + "type": "library", "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "HWI\\Bundle\\OAuthBundle\\": "" + "Fig\\Link\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1398,109 +1470,71 @@ ], "authors": [ { - "name": "Contributors", - "homepage": "https://github.com/hwi/HWIOAuthBundle/contributors" - }, - { - "name": "Joseph Bielawski", - "email": "stloyd@gmail.com" - }, - { - "name": "Alexander", - "email": "iam.asm89@gmail.com" - }, - { - "name": "Geoffrey Bachelet", - "email": "geoffrey.bachelet@gmail.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Support for authenticating users using both OAuth1.0a and OAuth2 in Symfony2.", - "homepage": "http://github.com/hwi/HWIOAuthBundle", + "description": "Common utility implementations for HTTP links", "keywords": [ - "37signals", - "Authentication", - "Deezer", - "EVE Online", - "amazon", - "auth0", - "azure", - "bitbucket", - "bitly", - "box", - "bufferapp", - "dailymotion", - "deviantart", - "discogs", - "disqus", - "dropbox", - "eventbrite", - "facebook", - "firewall", - "fiware", - "flickr", - "foursquare", - "github", - "google", - "hubic", - "instagram", - "jira", - "linkedin", - "mail.ru", - "oauth", - "oauth1", - "oauth2", - "odnoklassniki", - "paypal", - "qq", - "reddit", - "runkeeper", - "salesforce", - "security", - "sensio connect", - "sina weibo", - "slack", - "sound cloud", - "spotify", - "stack exchange", - "stereomood", - "strava", - "toshl", - "trakt", - "trello", - "twitch", - "twitter", - "vkontakte", - "wechat", - "windows live", - "wordpress", - "xing", - "yahoo", - "yandex", - "youtube" - ], - "time": "2016-07-27T14:43:30+00:00" + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "time": "2016-10-17T18:31:11+00:00" }, { - "name": "ircmaxell/password-compat", - "version": "v1.0.4", + "name": "friendsofsymfony/user-bundle", + "version": "v2.1.2", "source": { "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + "url": "https://github.com/FriendsOfSymfony/FOSUserBundle.git", + "reference": "1049935edd24ec305cc6cfde1875372fa9600446" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSUserBundle/zipball/1049935edd24ec305cc6cfde1875372fa9600446", + "reference": "1049935edd24ec305cc6cfde1875372fa9600446", "shasum": "" }, + "require": { + "paragonie/random_compat": "^1 || ^2", + "php": "^5.5.9 || ^7.0", + "symfony/form": "^2.8 || ^3.0 || ^4.0", + "symfony/framework-bundle": "^2.8 || ^3.0 || ^4.0", + "symfony/security-bundle": "^2.8 || ^3.0 || ^4.0", + "symfony/templating": "^2.8 || ^3.0 || ^4.0", + "symfony/twig-bundle": "^2.8 || ^3.0 || ^4.0", + "symfony/validator": "^2.8 || ^3.0 || ^4.0", + "twig/twig": "^1.28 || ^2.0" + }, + "conflict": { + "doctrine/doctrine-bundle": "<1.3", + "symfony/doctrine-bridge": "<2.7" + }, "require-dev": { - "phpunit/phpunit": "4.*" + "doctrine/doctrine-bundle": "^1.3", + "friendsofphp/php-cs-fixer": "^2.2", + "phpunit/phpunit": "^4.8.35|^5.7.11|^6.5", + "swiftmailer/swiftmailer": "^4.3 || ^5.0 || ^6.0", + "symfony/console": "^2.8 || ^3.0 || ^4.0", + "symfony/phpunit-bridge": "^2.8 || ^3.0 || ^4.0", + "symfony/yaml": "^2.8 || ^3.0 || ^4.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } }, - "type": "library", "autoload": { - "files": [ - "lib/password.php" + "psr-4": { + "FOS\\UserBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1509,18 +1543,23 @@ ], "authors": [ { - "name": "Anthony Ferrara", - "email": "ircmaxell@php.net", - "homepage": "http://blog.ircmaxell.com" + "name": "Christophe Coevoet", + "email": "stof@notk.org" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/friendsofsymfony/FOSUserBundle/contributors" + }, + { + "name": "Thibault Duplessis" } ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", + "description": "Symfony FOSUserBundle", + "homepage": "http://friendsofsymfony.github.com", "keywords": [ - "hashing", - "password" + "User management" ], - "time": "2014-11-20T16:49:30+00:00" + "time": "2018-03-08T08:59:27+00:00" }, { "name": "jdorn/sql-formatter", @@ -1574,25 +1613,26 @@ }, { "name": "jms/aop-bundle", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/JMSAopBundle.git", - "reference": "78000d007e74283cc564a58e184d7f62548ad394" + "reference": "4ee2089a81b54ce94a8c94e95b48d5bb353dd8d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/JMSAopBundle/zipball/78000d007e74283cc564a58e184d7f62548ad394", - "reference": "78000d007e74283cc564a58e184d7f62548ad394", + "url": "https://api.github.com/repos/schmittjoh/JMSAopBundle/zipball/4ee2089a81b54ce94a8c94e95b48d5bb353dd8d0", + "reference": "4ee2089a81b54ce94a8c94e95b48d5bb353dd8d0", "shasum": "" }, "require": { "jms/cg": "^1.1", "php": ">=5.3.9", - "symfony/framework-bundle": "^2.3|^3.0" + "symfony/framework-bundle": "^2.3 || ^3.0 || ^4.0" }, "require-dev": { - "symfony/phpunit-bridge": "^2.7" + "phpunit/phpunit": "^4.8.36 | ^5.0", + "symfony/phpunit-bridge": "^2.7 || ^4.0" }, "type": "symfony-bundle", "extra": { @@ -1620,7 +1660,7 @@ "annotations", "aop" ], - "time": "2015-12-09T16:30:46+00:00" + "time": "2018-01-16T10:22:28+00:00" }, { "name": "jms/cg", @@ -1671,16 +1711,16 @@ }, { "name": "jms/di-extra-bundle", - "version": "1.8.0", + "version": "1.9.2", "source": { "type": "git", "url": "https://github.com/schmittjoh/JMSDiExtraBundle.git", - "reference": "7c8e23ffd65eb05f7b76869aa8ef1949e90789c7" + "reference": "fa82a4e6c9dc84df8015805028575217c0be4a54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/JMSDiExtraBundle/zipball/7c8e23ffd65eb05f7b76869aa8ef1949e90789c7", - "reference": "7c8e23ffd65eb05f7b76869aa8ef1949e90789c7", + "url": "https://api.github.com/repos/schmittjoh/JMSDiExtraBundle/zipball/fa82a4e6c9dc84df8015805028575217c0be4a54", + "reference": "fa82a4e6c9dc84df8015805028575217c0be4a54", "shasum": "" }, "require": { @@ -1699,13 +1739,16 @@ "doctrine/orm": "~2.3", "jms/security-extra-bundle": "~1.0", "phpcollection/phpcollection": ">=0.2,<0.3-dev", + "phpunit/phpunit": "^4.8.35|^5.4.4|^6.0.0", "sensio/framework-extra-bundle": "~2.0|~3.0", + "symfony/asset": "~2.3|^3.3", "symfony/browser-kit": "~2.3|~3.0", "symfony/class-loader": "~2.3|~3.0", "symfony/expression-language": "~2.6|~3.0", "symfony/form": "~2.3|~3.0", - "symfony/phpunit-bridge": "~2.7", - "symfony/security-bundle": "~2.3", + "symfony/phpunit-bridge": "~3.3", + "symfony/security-bundle": "~2.3|^3.0", + "symfony/templating": "~2.3|^3.3", "symfony/twig-bundle": "~2.3|~3.0", "symfony/validator": "~2.3|~3.0", "symfony/yaml": "~2.3|~3.0" @@ -1713,7 +1756,7 @@ "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -1737,27 +1780,28 @@ "annotations", "dependency injection" ], - "time": "2016-09-09T12:35:58+00:00" + "time": "2018-01-12T19:04:30+00:00" }, { "name": "jms/metadata", - "version": "1.5.1", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/metadata.git", - "reference": "22b72455559a25777cfd28c4ffda81ff7639f353" + "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/22b72455559a25777cfd28c4ffda81ff7639f353", - "reference": "22b72455559a25777cfd28c4ffda81ff7639f353", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/6a06970a10e0a532fb52d3959547123b84a3b3ab", + "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "doctrine/cache": "~1.0" + "doctrine/cache": "~1.0", + "symfony/cache": "~3.1" }, "type": "library", "extra": { @@ -1772,14 +1816,12 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache" + "Apache-2.0" ], "authors": [ { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", - "role": "Developer of wrapped JMSSerializerBundle" + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" } ], "description": "Class/method/property metadata management in PHP", @@ -1789,7 +1831,7 @@ "xml", "yaml" ], - "time": "2014-07-12T07:13:19+00:00" + "time": "2016-12-05T10:18:33+00:00" }, { "name": "jms/parser-lib", @@ -1828,16 +1870,16 @@ }, { "name": "jms/security-extra-bundle", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/schmittjoh/JMSSecurityExtraBundle.git", - "reference": "d70399b25f41afd8277335cedc3c9b3acdc3759d" + "reference": "8d3b81d62601dcbafafc5e0c2d20f3383e475525" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/JMSSecurityExtraBundle/zipball/d70399b25f41afd8277335cedc3c9b3acdc3759d", - "reference": "d70399b25f41afd8277335cedc3c9b3acdc3759d", + "url": "https://api.github.com/repos/schmittjoh/JMSSecurityExtraBundle/zipball/8d3b81d62601dcbafafc5e0c2d20f3383e475525", + "reference": "8d3b81d62601dcbafafc5e0c2d20f3383e475525", "shasum": "" }, "require": { @@ -1900,29 +1942,29 @@ "secure", "security" ], - "time": "2016-02-03T15:29:16+00:00" + "time": "2016-08-04T14:40:55+00:00" }, { "name": "justinrainbow/json-schema", - "version": "5.1.0", + "version": "5.2.7", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "48817e5f95c9d29e11513f12e43cc0223fa5eb6c" + "reference": "8560d4314577199ba51bf2032f02cd1315587c23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/48817e5f95c9d29e11513f12e43cc0223fa5eb6c", - "reference": "48817e5f95c9d29e11513f12e43cc0223fa5eb6c", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", + "reference": "8560d4314577199ba51bf2032f02cd1315587c23", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^2.1", "json-schema/json-schema-test-suite": "1.2.0", - "phpdocumentor/phpdocumentor": "~2", - "phpunit/phpunit": "^4.8.22" + "phpunit/phpunit": "^4.8.35" }, "bin": [ "bin/validate-json" @@ -1966,41 +2008,39 @@ "json", "schema" ], - "time": "2017-02-22T03:28:16+00:00" + "time": "2018-02-14T22:26:30+00:00" }, { "name": "knplabs/knp-menu", - "version": "v2.1.1", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/KnpLabs/KnpMenu.git", - "reference": "9917b999a3c3d3901386d60c4888b07679291031" + "reference": "655630a1db0b72108262d1a844de3b1ba0885be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/KnpMenu/zipball/9917b999a3c3d3901386d60c4888b07679291031", - "reference": "9917b999a3c3d3901386d60c4888b07679291031", + "url": "https://api.github.com/repos/KnpLabs/KnpMenu/zipball/655630a1db0b72108262d1a844de3b1ba0885be5", + "reference": "655630a1db0b72108262d1a844de3b1ba0885be5", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.6.0" }, "require-dev": { - "pimple/pimple": "~1.0", - "silex/silex": "~1.0", - "symfony/phpunit-bridge": "~2.7|~3.0", - "symfony/routing": "~2.3|~3.0", + "psr/container": "^1.0", + "symfony/http-foundation": "~2.4|~3.0|^4.0", + "symfony/phpunit-bridge": "~3.3|^4.0", + "symfony/routing": "~2.3|~3.0|^4.0", "twig/twig": "~1.16|~2.0" }, "suggest": { - "pimple/pimple": "for the built-in implementations of the menu provider and renderer provider", - "silex/silex": "for the integration with your silex application", "twig/twig": "for the TwigRenderer and the integration with your templates" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.3-dev" } }, "autoload": { @@ -2017,54 +2057,56 @@ "name": "Christophe Coevoet", "email": "stof@notk.org" }, - { - "name": "KnpLabs", - "homepage": "http://knplabs.com" - }, { "name": "Symfony Community", "homepage": "https://github.com/KnpLabs/KnpMenu/contributors" + }, + { + "name": "KnpLabs", + "homepage": "https://knplabs.com" } ], "description": "An object oriented menu library", - "homepage": "http://knplabs.com", + "homepage": "https://knplabs.com", "keywords": [ "menu", "tree" ], - "time": "2016-01-08T15:42:54+00:00" + "time": "2017-11-18T20:49:26+00:00" }, { "name": "knplabs/knp-menu-bundle", - "version": "2.1.2", + "version": "v2.2.1", "source": { "type": "git", "url": "https://github.com/KnpLabs/KnpMenuBundle.git", - "reference": "42ff1953c3a79d0b31aba2ece8c03fbd70e7f1ca" + "reference": "6bea43eb84fc67c43ab2b43709194efffa8a8ac0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/KnpMenuBundle/zipball/42ff1953c3a79d0b31aba2ece8c03fbd70e7f1ca", - "reference": "42ff1953c3a79d0b31aba2ece8c03fbd70e7f1ca", + "url": "https://api.github.com/repos/KnpLabs/KnpMenuBundle/zipball/6bea43eb84fc67c43ab2b43709194efffa8a8ac0", + "reference": "6bea43eb84fc67c43ab2b43709194efffa8a8ac0", "shasum": "" }, "require": { - "knplabs/knp-menu": "~2.1", - "symfony/framework-bundle": "~2.3|~3.0" + "knplabs/knp-menu": "~2.3", + "php": "^5.6 || ^7", + "symfony/framework-bundle": "~2.7|~3.0 | ^4.0" }, "require-dev": { - "symfony/expression-language": "~2.4|~3.0", - "symfony/phpunit-bridge": "~2.7|~3.0" + "symfony/expression-language": "~2.7|~3.0 | ^4.0", + "symfony/phpunit-bridge": "^3.3 | ^4.0", + "symfony/templating": "~2.7|~3.0 | ^4.0" }, "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { "psr-4": { - "Knp\\Bundle\\MenuBundle\\": "" + "Knp\\Bundle\\MenuBundle\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2089,55 +2131,7 @@ "keywords": [ "menu" ], - "time": "2016-06-21T06:53:03+00:00" - }, - { - "name": "kriswallsmith/buzz", - "version": "v0.15", - "source": { - "type": "git", - "url": "https://github.com/kriswallsmith/Buzz.git", - "reference": "d4041666c3ffb379af02a92dabe81c904b35fab8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kriswallsmith/Buzz/zipball/d4041666c3ffb379af02a92dabe81c904b35fab8", - "reference": "d4041666c3ffb379af02a92dabe81c904b35fab8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*" - }, - "suggest": { - "ext-curl": "*" - }, - "type": "library", - "autoload": { - "psr-0": { - "Buzz": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kris Wallsmith", - "email": "kris.wallsmith@gmail.com", - "homepage": "http://kriswallsmith.net/" - } - ], - "description": "Lightweight HTTP client", - "homepage": "https://github.com/kriswallsmith/Buzz", - "keywords": [ - "curl", - "http client" - ], - "time": "2015-06-25T17:26:56+00:00" + "time": "2017-12-24T16:32:39+00:00" }, { "name": "monolog/monolog", @@ -2217,124 +2211,6 @@ ], "time": "2017-06-19T01:22:40+00:00" }, - { - "name": "nelmio/cors-bundle", - "version": "1.5.3", - "source": { - "type": "git", - "url": "https://github.com/nelmio/NelmioCorsBundle.git", - "reference": "ac6576a599d7db9c2c6022602c188a5594216056" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/ac6576a599d7db9c2c6022602c188a5594216056", - "reference": "ac6576a599d7db9c2c6022602c188a5594216056", - "shasum": "" - }, - "require": { - "symfony/framework-bundle": "^2.7 || ^3.0" - }, - "require-dev": { - "matthiasnoback/symfony-dependency-injection-test": "^0.7.6", - "mockery/mockery": "0.9.*" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - } - }, - "autoload": { - "psr-4": { - "Nelmio\\CorsBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nelmio", - "homepage": "http://nelm.io" - }, - { - "name": "Symfony Community", - "homepage": "https://github.com/nelmio/NelmioCorsBundle/contributors" - } - ], - "description": "Adds CORS (Cross-Origin Resource Sharing) headers support in your Symfony2 application", - "keywords": [ - "api", - "cors", - "crossdomain" - ], - "time": "2017-04-24T09:12:42+00:00" - }, - { - "name": "nelmio/security-bundle", - "version": "2.4.0", - "source": { - "type": "git", - "url": "https://github.com/nelmio/NelmioSecurityBundle.git", - "reference": "d0d7b151eda5f0ebe80562528f78b56954c1aec7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioSecurityBundle/zipball/d0d7b151eda5f0ebe80562528f78b56954c1aec7", - "reference": "d0d7b151eda5f0ebe80562528f78b56954c1aec7", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "~1.0|~2.0", - "symfony/framework-bundle": "~2.3|~3.0", - "symfony/security": "~2.3|~3.0", - "ua-parser/uap-php": "^3.4.4" - }, - "require-dev": { - "doctrine/cache": "^1.0", - "psr/cache": "^1.0", - "symfony/phpunit-bridge": "^3.2", - "symfony/yaml": "~2.3|~3.0", - "twig/twig": "^1.24" - }, - "suggest": { - "ua-parser/uap-php": "To allow adapt CSP directives given the user-agent" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "2.4.x-dev" - } - }, - "autoload": { - "psr-4": { - "Nelmio\\SecurityBundle\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nelmio", - "homepage": "http://nelm.io" - }, - { - "name": "Symfony Community", - "homepage": "https://github.com/nelmio/NelmioSecurityBundle/contributors" - } - ], - "description": "Extra security-related features for Symfony: signed/encrypted cookies, HTTPS/SSL/HSTS handling, cookie session storage, ...", - "keywords": [ - "security" - ], - "time": "2017-06-22T08:11:46+00:00" - }, { "name": "oro/doctrine-extensions", "version": "1.2.0", @@ -2392,16 +2268,16 @@ }, { "name": "pagerfanta/pagerfanta", - "version": "v1.0.3", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/whiteoctober/Pagerfanta.git", - "reference": "a874d3612d954dcbbb49e5ffe178890918fb76fb" + "reference": "8400ab498e500018cff9a099ac22555e7949aa9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/whiteoctober/Pagerfanta/zipball/a874d3612d954dcbbb49e5ffe178890918fb76fb", - "reference": "a874d3612d954dcbbb49e5ffe178890918fb76fb", + "url": "https://api.github.com/repos/whiteoctober/Pagerfanta/zipball/8400ab498e500018cff9a099ac22555e7949aa9a", + "reference": "8400ab498e500018cff9a099ac22555e7949aa9a", "shasum": "" }, "require": { @@ -2414,7 +2290,8 @@ "jmikola/geojson": "~1.0", "mandango/mandango": "~1.0@dev", "mandango/mondator": "~1.0@dev", - "phpunit/phpunit": "~4", + "phpunit/phpunit": "^4.8.35 | ^5.7", + "propel/propel": "~2.0@dev", "propel/propel1": "~1.6", "ruflin/elastica": "~1.3", "solarium/solarium": "~3.1" @@ -2424,6 +2301,7 @@ "doctrine/orm": "To use the DoctrineORMAdapter.", "doctrine/phpcr-odm": "To use the DoctrineODMPhpcrAdapter. >= 1.1.0", "mandango/mandango": "To use the MandangoAdapter.", + "propel/propel": "To use the Propel2Adapter", "propel/propel1": "To use the PropelAdapter", "solarium/solarium": "To use the SolariumAdapter." }, @@ -2455,20 +2333,20 @@ "paginator", "paging" ], - "time": "2014-10-06T10:57:25+00:00" + "time": "2018-05-01T10:49:10+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.12", + "version": "v2.0.17", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", "shasum": "" }, "require": { @@ -2500,89 +2378,282 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2018-04-04T21:24:14+00:00" + "time": "2018-07-04T16:31:37+00:00" }, { "name": "phpoption/phpoption", "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed" + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-0": { + "PhpOption\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "time": "2015-07-25T16:39:46+00:00" + }, + { + "name": "predis/predis", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/nrk/predis.git", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net" + } + ], + "description": "Flexible and feature-complete Redis client for PHP and HHVM", + "homepage": "http://github.com/nrk/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "time": "2016-06-16T16:22:20+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/link", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed", - "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "url": "https://api.github.com/repos/php-fig/link/zipball/eea8e8662d5cd3ae4517c9b864493f59fca95562", + "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "require-dev": { - "phpunit/phpunit": "4.7.*" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "PhpOption\\": "src/" + "psr-4": { + "Psr\\Link\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache2" + "MIT" ], "authors": [ { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Option Type for PHP", + "description": "Common interfaces for HTTP links", "keywords": [ - "language", - "option", - "php", - "type" + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" ], - "time": "2015-07-25T16:39:46+00:00" + "time": "2016-10-28T16:06:13+00:00" }, { - "name": "predis/predis", - "version": "v1.1.1", + "name": "psr/log", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/nrk/predis.git", - "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", - "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "suggest": { - "ext-curl": "Allows access to Webdis when paired with phpiredis", - "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "Predis\\": "src/" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2591,32 +2662,31 @@ ], "authors": [ { - "name": "Daniele Alessandri", - "email": "suppakilla@gmail.com", - "homepage": "http://clorophilla.net" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Flexible and feature-complete Redis client for PHP and HHVM", - "homepage": "http://github.com/nrk/predis", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "nosql", - "predis", - "redis" + "log", + "psr", + "psr-3" ], - "time": "2016-06-16T16:22:20+00:00" + "time": "2016-10-10T12:19:37+00:00" }, { - "name": "psr/log", - "version": "1.0.2", + "name": "psr/simple-cache", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", "shasum": "" }, "require": { @@ -2630,7 +2700,7 @@ }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\SimpleCache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2643,14 +2713,15 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common interfaces for simple caching", "keywords": [ - "log", + "cache", + "caching", "psr", - "psr-3" + "psr-16", + "simple-cache" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2017-10-23T01:57:42+00:00" }, { "name": "seld/cli-prompt", @@ -2702,16 +2773,16 @@ }, { "name": "seld/jsonlint", - "version": "1.7.0", + "version": "1.7.1", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "9b355654ea99460397b89c132b5c1087b6bf4473" + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9b355654ea99460397b89c132b5c1087b6bf4473", - "reference": "9b355654ea99460397b89c132b5c1087b6bf4473", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", "shasum": "" }, "require": { @@ -2747,7 +2818,7 @@ "parser", "validator" ], - "time": "2018-01-03T12:13:57+00:00" + "time": "2018-01-24T12:46:19+00:00" }, { "name": "seld/phar-utils", @@ -2843,16 +2914,16 @@ }, { "name": "sensio/distribution-bundle", - "version": "v5.0.21", + "version": "v5.0.22", "source": { "type": "git", "url": "https://github.com/sensiolabs/SensioDistributionBundle.git", - "reference": "eb6266b3b472e4002538610b28a0a04bcf94891a" + "reference": "209b11f8cee5bf71986dd703e45e27d3ed7a6d15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/eb6266b3b472e4002538610b28a0a04bcf94891a", - "reference": "eb6266b3b472e4002538610b28a0a04bcf94891a", + "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/209b11f8cee5bf71986dd703e45e27d3ed7a6d15", + "reference": "209b11f8cee5bf71986dd703e45e27d3ed7a6d15", "shasum": "" }, "require": { @@ -2891,7 +2962,7 @@ "configuration", "distribution" ], - "time": "2017-08-25T16:55:44+00:00" + "time": "2018-06-07T06:22:12+00:00" }, { "name": "sensio/framework-extra-bundle", @@ -3064,29 +3135,29 @@ }, { "name": "snc/redis-bundle", - "version": "2.0.0", + "version": "2.1.4", "source": { "type": "git", "url": "https://github.com/snc/SncRedisBundle.git", - "reference": "b8aa1a966b32c4fba6b7dac4532d5eeb1d890afb" + "reference": "3f3c233ebbfba43d3abd2403be0bc34c11e6dc06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/snc/SncRedisBundle/zipball/b8aa1a966b32c4fba6b7dac4532d5eeb1d890afb", - "reference": "b8aa1a966b32c4fba6b7dac4532d5eeb1d890afb", + "url": "https://api.github.com/repos/snc/SncRedisBundle/zipball/3f3c233ebbfba43d3abd2403be0bc34c11e6dc06", + "reference": "3f3c233ebbfba43d3abd2403be0bc34c11e6dc06", "shasum": "" }, "require": { "php": ">=5.3.3", - "symfony/framework-bundle": "^2.7 || ^3.0", - "symfony/yaml": "^2.7 || ^3.0" + "symfony/framework-bundle": "^2.7 || ^3.0 || ^4.0", + "symfony/yaml": "^2.7 || ^3.0 || ^4.0" }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "4.8.*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", "predis/predis": "^1.0", - "symfony/console": "^2.7 || ^3.0", - "symfony/phpunit-bridge": "^2.7 || ^3.0" + "symfony/console": "^2.7 || ^3.0 || ^4.0", + "symfony/phpunit-bridge": "^2.7 || ^3.0 || ^4.0" }, "suggest": { "monolog/monolog": "If you want to use the monolog redis handler.", @@ -3125,7 +3196,7 @@ "redis", "symfony" ], - "time": "2016-06-17T11:50:26+00:00" + "time": "2018-06-25T15:31:46+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -3298,83 +3369,22 @@ "time": "2018-04-26T10:06:28+00:00" }, { - "name": "symfony/polyfill-intl-icu", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "80ee17ae83c10cd513e5144f91a73607a21edb4e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/80ee17ae83c10cd513e5144f91a73607a21edb4e", - "reference": "80ee17ae83c10cd513e5144f91a73607a21edb4e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "symfony/intl": "~2.3|~3.0|~4.0" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's ICU-related data and classes", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "icu", - "intl", - "polyfill", - "portable", - "shim" - ], - "time": "2018-04-25T14:53:50+00:00" - }, - { - "name": "symfony/polyfill-mbstring", + "name": "symfony/polyfill-ctype", "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "3296adf6a6454a050679cde90f95350ad604b171" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", - "reference": "3296adf6a6454a050679cde90f95350ad604b171", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "suggest": { - "ext-mbstring": "For best performance" - }, "type": "library", "extra": { "branch-alias": { @@ -3383,7 +3393,7 @@ }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Symfony\\Polyfill\\Ctype\\": "" }, "files": [ "bootstrap.php" @@ -3394,42 +3404,45 @@ "MIT" ], "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", + "ctype", "polyfill", - "portable", - "shim" + "portable" ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2018-04-30T19:57:29+00:00" }, { - "name": "symfony/polyfill-php54", + "name": "symfony/polyfill-intl-icu", "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php54.git", - "reference": "6c3a2b84c6025e4ea3f6a19feac35408c64b22e1" + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "80ee17ae83c10cd513e5144f91a73607a21edb4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/6c3a2b84c6025e4ea3f6a19feac35408c64b22e1", - "reference": "6c3a2b84c6025e4ea3f6a19feac35408c64b22e1", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/80ee17ae83c10cd513e5144f91a73607a21edb4e", + "reference": "80ee17ae83c10cd513e5144f91a73607a21edb4e", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.3", + "symfony/intl": "~2.3|~3.0|~4.0" + }, + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { @@ -3438,14 +3451,8 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php54\\": "" - }, "files": [ "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3462,34 +3469,38 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 5.4+ features to lower PHP versions", + "description": "Symfony polyfill for intl's ICU-related data and classes", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "icu", + "intl", "polyfill", "portable", "shim" ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2018-04-25T14:53:50+00:00" }, { - "name": "symfony/polyfill-php55", + "name": "symfony/polyfill-mbstring", "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php55.git", - "reference": "a39456128377a85f2c5707fcae458678560cba46" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/a39456128377a85f2c5707fcae458678560cba46", - "reference": "a39456128377a85f2c5707fcae458678560cba46", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { - "ircmaxell/password-compat": "~1.0", "php": ">=5.3.3" }, + "suggest": { + "ext-mbstring": "For best performance" + }, "type": "library", "extra": { "branch-alias": { @@ -3498,7 +3509,7 @@ }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php55\\": "" + "Symfony\\Polyfill\\Mbstring\\": "" }, "files": [ "bootstrap.php" @@ -3518,10 +3529,11 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 5.5+ features to lower PHP versions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "mbstring", "polyfill", "portable", "shim" @@ -3817,41 +3829,51 @@ }, { "name": "symfony/symfony", - "version": "v2.8.39", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/symfony.git", - "reference": "9b75ffe7b3adf2dad279e968787b71f829c1c404" + "reference": "c36f8cb21b5f1661a14fdb8cef9cc611d54a3494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/symfony/zipball/9b75ffe7b3adf2dad279e968787b71f829c1c404", - "reference": "9b75ffe7b3adf2dad279e968787b71f829c1c404", + "url": "https://api.github.com/repos/symfony/symfony/zipball/c36f8cb21b5f1661a14fdb8cef9cc611d54a3494", + "reference": "c36f8cb21b5f1661a14fdb8cef9cc611d54a3494", "shasum": "" }, "require": { - "doctrine/common": "~2.4", + "doctrine/common": "~2.4@stable", "ext-xml": "*", - "php": ">=5.3.9", + "fig/link-util": "^1.0", + "php": "^5.5.9|>=7.0.8", + "psr/cache": "~1.0", + "psr/container": "^1.0", + "psr/link": "^1.0", "psr/log": "~1.0", + "psr/simple-cache": "^1.0", "symfony/polyfill-apcu": "~1.1", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-icu": "~1.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php54": "~1.0", - "symfony/polyfill-php55": "~1.0", "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.0", - "symfony/polyfill-util": "~1.0", - "symfony/security-acl": "~2.7|~3.0.0", - "twig/twig": "~1.34|~2.4" + "symfony/polyfill-php70": "~1.6", + "twig/twig": "^1.35|^2.4.4" }, "conflict": { - "phpdocumentor/reflection": "<1.0.7", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", + "phpdocumentor/type-resolver": "<0.2.1", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/container-implementation": "1.0", + "psr/log-implementation": "1.0", + "psr/simple-cache-implementation": "1.0" + }, "replace": { "symfony/asset": "self.version", "symfony/browser-kit": "self.version", + "symfony/cache": "self.version", "symfony/class-loader": "self.version", "symfony/config": "self.version", "symfony/console": "self.version", @@ -3861,6 +3883,7 @@ "symfony/dependency-injection": "self.version", "symfony/doctrine-bridge": "self.version", "symfony/dom-crawler": "self.version", + "symfony/dotenv": "self.version", "symfony/event-dispatcher": "self.version", "symfony/expression-language": "self.version", "symfony/filesystem": "self.version", @@ -3869,9 +3892,10 @@ "symfony/framework-bundle": "self.version", "symfony/http-foundation": "self.version", "symfony/http-kernel": "self.version", + "symfony/inflector": "self.version", "symfony/intl": "self.version", "symfony/ldap": "self.version", - "symfony/locale": "self.version", + "symfony/lock": "self.version", "symfony/monolog-bridge": "self.version", "symfony/options-resolver": "self.version", "symfony/process": "self.version", @@ -3887,33 +3911,38 @@ "symfony/security-http": "self.version", "symfony/serializer": "self.version", "symfony/stopwatch": "self.version", - "symfony/swiftmailer-bridge": "self.version", "symfony/templating": "self.version", "symfony/translation": "self.version", "symfony/twig-bridge": "self.version", "symfony/twig-bundle": "self.version", "symfony/validator": "self.version", "symfony/var-dumper": "self.version", + "symfony/web-link": "self.version", "symfony/web-profiler-bundle": "self.version", + "symfony/web-server-bundle": "self.version", + "symfony/workflow": "self.version", "symfony/yaml": "self.version" }, "require-dev": { + "cache/integration-tests": "dev-master", "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.6", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.4", - "doctrine/doctrine-bundle": "~1.2", + "doctrine/doctrine-bundle": "~1.4", "doctrine/orm": "~2.4,>=2.4.5", - "egulias/email-validator": "~1.2,>=1.2.1", + "egulias/email-validator": "~1.2,>=1.2.8|~2.0", "monolog/monolog": "~1.11", "ocramius/proxy-manager": "~0.4|~1.0|~2.0", - "phpdocumentor/reflection": "^1.0.7", - "sensio/framework-extra-bundle": "^3.0.2", - "symfony/phpunit-bridge": "~3.4|~4.0" + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "predis/predis": "~1.0", + "symfony/phpunit-bridge": "~3.4|~4.0", + "symfony/security-acl": "~2.8|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -3921,7 +3950,6 @@ "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/", "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/", "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/", - "Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/", "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/", "Symfony\\Bundle\\": "src/Symfony/Bundle/", "Symfony\\Component\\": "src/Symfony/Component/" @@ -3952,27 +3980,28 @@ "keywords": [ "framework" ], - "time": "2018-04-30T05:53:09+00:00" + "time": "2018-06-25T12:29:33+00:00" }, { "name": "twig/extensions", - "version": "v1.3.0", + "version": "v1.5.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig-extensions.git", - "reference": "449e3c8a9ffad7c2479c7864557275a32b037499" + "reference": "d188c76168b853481cc75879ea045bf93d718e9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/449e3c8a9ffad7c2479c7864557275a32b037499", - "reference": "449e3c8a9ffad7c2479c7864557275a32b037499", + "url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/d188c76168b853481cc75879ea045bf93d718e9c", + "reference": "d188c76168b853481cc75879ea045bf93d718e9c", "shasum": "" }, "require": { - "twig/twig": "~1.20|~2.0" + "twig/twig": "~1.27|~2.0" }, "require-dev": { - "symfony/translation": "~2.3" + "symfony/phpunit-bridge": "~3.3@dev", + "symfony/translation": "~2.3|~3.0" }, "suggest": { "symfony/translation": "Allow the time_diff output to be translated" @@ -3980,12 +4009,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.5-dev" } }, "autoload": { "psr-0": { "Twig_Extensions_": "lib/" + }, + "psr-4": { + "Twig\\Extensions\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4004,24 +4036,25 @@ "i18n", "text" ], - "time": "2015-08-22T16:38:35+00:00" + "time": "2017-06-08T18:19:53+00:00" }, { "name": "twig/twig", - "version": "v2.4.8", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "7b604c89da162034bdf4bb66310f358d313dd16d" + "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/7b604c89da162034bdf4bb66310f358d313dd16d", - "reference": "7b604c89da162034bdf4bb66310f358d313dd16d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/6a5f676b77a90823c2d4eaf76137b771adf31323", + "reference": "6a5f676b77a90823c2d4eaf76137b771adf31323", "shasum": "" }, "require": { "php": "^7.0", + "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -4032,7 +4065,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -4061,90 +4094,41 @@ }, { "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", + "homepage": "https://twig.symfony.com/contributors", "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", + "homepage": "https://twig.symfony.com", "keywords": [ "templating" ], - "time": "2018-04-02T09:24:19+00:00" - }, - { - "name": "ua-parser/uap-php", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/ua-parser/uap-php.git", - "reference": "c8b31e5b8215a0c6dab4dd304050526a1907b17c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ua-parser/uap-php/zipball/c8b31e5b8215a0c6dab4dd304050526a1907b17c", - "reference": "c8b31e5b8215a0c6dab4dd304050526a1907b17c", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "symfony/console": "^2.0 || ^3.0 || ^4.0", - "symfony/filesystem": "^2.0 || ^3.0 || ^4.0", - "symfony/finder": "^2.0 || ^3.0 || ^4.0", - "symfony/yaml": "^2.0 || ^3.0 || ^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0" - }, - "bin": [ - "bin/uaparser" - ], - "type": "library", - "autoload": { - "psr-4": { - "UAParser\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Lars Strojny", - "email": "lars@strojny.net" - }, - { - "name": "Dave Olsen", - "email": "dmolsen@gmail.com" - } - ], - "description": "A multi-language port of Browserscope's user agent parser.", - "time": "2017-12-13T11:03:50+00:00" + "time": "2018-07-13T07:18:09+00:00" }, { "name": "white-october/pagerfanta-bundle", - "version": "v1.0.7", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/whiteoctober/WhiteOctoberPagerfantaBundle.git", - "reference": "f7e0fdf94a763a21a7c4c36ec9d9b5bcf4e12521" + "reference": "3f97e71c9d3f75e7a6179aa82c863497bf298b2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/whiteoctober/WhiteOctoberPagerfantaBundle/zipball/f7e0fdf94a763a21a7c4c36ec9d9b5bcf4e12521", - "reference": "f7e0fdf94a763a21a7c4c36ec9d9b5bcf4e12521", + "url": "https://api.github.com/repos/whiteoctober/WhiteOctoberPagerfantaBundle/zipball/3f97e71c9d3f75e7a6179aa82c863497bf298b2d", + "reference": "3f97e71c9d3f75e7a6179aa82c863497bf298b2d", "shasum": "" }, "require": { - "pagerfanta/pagerfanta": "1.0.*", - "symfony/framework-bundle": "~2.3|~3.0", - "symfony/property-access": "~2.3|~3.0", - "symfony/twig-bundle": "~2.3|~3.0" + "pagerfanta/pagerfanta": "^1.1.0|^2.0.0", + "php": ">=5.3", + "symfony/framework-bundle": "~2.3|~3.0|~4.0", + "symfony/property-access": "~2.3|~3.0|~4.0", + "symfony/twig-bundle": "~2.3|~3.0|~4.0" }, "require-dev": { - "phpunit/phpunit": "~3.7", - "symfony/symfony": "~2.3|~3.0" + "phpunit/phpunit": "~3.7|~4.0|^5.0", + "symfony/symfony": "~2.3|~3.0|~4.0" }, "type": "symfony-bundle", "extra": { @@ -4153,8 +4137,14 @@ } }, "autoload": { + "classmap": [ + "WhiteOctoberPagerfantaBundle.php" + ], "psr-4": { - "WhiteOctober\\PagerfantaBundle\\": "" + "WhiteOctober\\PagerfantaBundle\\DependencyInjection\\": "DependencyInjection", + "WhiteOctober\\PagerfantaBundle\\EventListener\\": "EventListener", + "WhiteOctober\\PagerfantaBundle\\Twig\\": "Twig", + "WhiteOctober\\PagerfantaBundle\\View\\": "View" } }, "notification-url": "https://packagist.org/downloads/", @@ -4172,7 +4162,7 @@ "page", "paging" ], - "time": "2016-08-04T15:48:14+00:00" + "time": "2018-06-20T09:32:42+00:00" }, { "name": "zendframework/zend-escaper", @@ -4221,16 +4211,16 @@ }, { "name": "zendframework/zend-feed", - "version": "2.9.0", + "version": "2.10.2", "source": { "type": "git", "url": "https://github.com/zendframework/zend-feed.git", - "reference": "abe88686124d492e0a2a84656f15e5482bfbe030" + "reference": "5253f949f4ad999086ab9b408908b6c6776f24db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/abe88686124d492e0a2a84656f15e5482bfbe030", - "reference": "abe88686124d492e0a2a84656f15e5482bfbe030", + "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/5253f949f4ad999086ab9b408908b6c6776f24db", + "reference": "5253f949f4ad999086ab9b408908b6c6776f24db", "shasum": "" }, "require": { @@ -4259,8 +4249,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.9-dev", - "dev-develop": "2.10-dev" + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" } }, "autoload": { @@ -4278,20 +4268,20 @@ "feed", "zf" ], - "time": "2017-12-04T17:59:38+00:00" + "time": "2018-06-18T20:14:01+00:00" }, { "name": "zendframework/zend-servicemanager", - "version": "2.7.10", + "version": "2.7.11", "source": { "type": "git", "url": "https://github.com/zendframework/zend-servicemanager.git", - "reference": "ba7069c94c9af93122be9fa31cddd37f7707d5b4" + "reference": "99ec9ed5d0f15aed9876433c74c2709eb933d4c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/ba7069c94c9af93122be9fa31cddd37f7707d5b4", - "reference": "ba7069c94c9af93122be9fa31cddd37f7707d5b4", + "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/99ec9ed5d0f15aed9876433c74c2709eb933d4c7", + "reference": "99ec9ed5d0f15aed9876433c74c2709eb933d4c7", "shasum": "" }, "require": { @@ -4330,7 +4320,7 @@ "servicemanager", "zf2" ], - "time": "2017-12-05T16:27:36+00:00" + "time": "2018-06-22T14:49:54+00:00" }, { "name": "zendframework/zend-stdlib", @@ -4500,25 +4490,28 @@ "packages-dev": [ { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -4541,7 +4534,7 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "time": "2018-06-11T23:09:50+00:00" }, { "name": "phar-io/manifest", @@ -5111,16 +5104,16 @@ }, { "name": "phpunit/phpunit", - "version": "6.5.8", + "version": "6.5.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b" + "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4f21a3c6b97c42952fd5c2837bb354ec0199b97b", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/093ca5508174cd8ab8efe44fd1dde447adfdec8f", + "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f", "shasum": "" }, "require": { @@ -5191,20 +5184,20 @@ "testing", "xunit" ], - "time": "2018-04-10T11:38:34+00:00" + "time": "2018-07-03T06:40:40+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "5.0.6", + "version": "5.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" + "reference": "6f9a3c8bf34188a2b53ce2ae7a126089c53e0a9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/6f9a3c8bf34188a2b53ce2ae7a126089c53e0a9f", + "reference": "6f9a3c8bf34188a2b53ce2ae7a126089c53e0a9f", "shasum": "" }, "require": { @@ -5250,7 +5243,7 @@ "mock", "xunit" ], - "time": "2018-01-06T05:45:45+00:00" + "time": "2018-07-13T03:27:23+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5813,28 +5806,39 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v3.1.4", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "1f4e2059cf4ecae1053b9c3027b3fc548fd077b9" + "reference": "8a21eb6bedad38bf1f15d529c65eb9e17d0242fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/1f4e2059cf4ecae1053b9c3027b3fc548fd077b9", - "reference": "1f4e2059cf4ecae1053b9c3027b3fc548fd077b9", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/8a21eb6bedad38bf1f15d529c65eb9e17d0242fd", + "reference": "8a21eb6bedad38bf1f15d529c65eb9e17d0242fd", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, "suggest": { + "ext-zip": "Zip support is required when using bin/simple-phpunit", "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" }, + "bin": [ + "bin/simple-phpunit" + ], "type": "symfony-bridge", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.4-dev" + }, + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" } }, "autoload": { @@ -5864,7 +5868,7 @@ ], "description": "Symfony PHPUnit Bridge", "homepage": "https://symfony.com", - "time": "2016-08-19T06:48:39+00:00" + "time": "2018-06-10T07:25:02+00:00" }, { "name": "theseer/tokenizer", @@ -5959,17 +5963,11 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "composer/composer": 20, - "friendsofsymfony/user-bundle": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=7.0" }, - "platform-dev": [], - "platform-overrides": { - "php": "7.0.27" - } + "platform-dev": [] } diff --git a/src/Packagist/WebBundle/Command/DumpPackagesCommand.php b/src/Packagist/WebBundle/Command/DumpPackagesCommand.php deleted file mode 100644 index d9292fef..00000000 --- a/src/Packagist/WebBundle/Command/DumpPackagesCommand.php +++ /dev/null @@ -1,95 +0,0 @@ - - * Nils Adermann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Packagist\WebBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Filesystem\LockHandler; - -/** - * @author Jordi Boggiano - */ -class DumpPackagesCommand extends ContainerAwareCommand -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('packagist:dump') - ->setDefinition(array( - new InputOption('force', null, InputOption::VALUE_NONE, 'Force a dump of all packages'), - )) - ->setDescription('Dumps the packages into a packages.json + included files') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $force = (Boolean) $input->getOption('force'); - $verbose = (Boolean) $input->getOption('verbose'); - - $deployLock = $this->getContainer()->getParameter('kernel.cache_dir').'/deploy.globallock'; - if (file_exists($deployLock)) { - if ($verbose) { - $output->writeln('Aborting, '.$deployLock.' file present'); - } - return; - } - - // another dumper is still active - $lock = new LockHandler('packagist_package_dumper'); - if (!$lock->lock()) { - if ($verbose) { - $output->writeln('Aborting, another dumper is still active'); - } - return; - } - - $doctrine = $this->getContainer()->get('doctrine'); - - if ($force) { - $packages = $doctrine->getManager()->getConnection()->fetchAll('SELECT id FROM package ORDER BY id ASC'); - } else { - $packages = $doctrine->getRepository('PackagistWebBundle:Package')->getStalePackagesForDumping(); - } - - $ids = array(); - foreach ($packages as $package) { - $ids[] = $package['id']; - } - if (!$ids && !$force) { - if ($verbose) { - $output->writeln('Aborting, no packages to dump and not doing a forced run'); - } - return 0; - } - - ini_set('memory_limit', -1); - gc_enable(); - - try { - $result = $this->getContainer()->get('packagist.package_dumper')->dump($ids, $force, $verbose); - } finally { - $lock->release(); - } - - return $result ? 0 : 1; - } -} diff --git a/src/Packagist/WebBundle/Command/IndexPackagesCommand.php b/src/Packagist/WebBundle/Command/IndexPackagesCommand.php deleted file mode 100644 index 47bbc9ec..00000000 --- a/src/Packagist/WebBundle/Command/IndexPackagesCommand.php +++ /dev/null @@ -1,298 +0,0 @@ - - * Nils Adermann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Packagist\WebBundle\Command; - -use Packagist\WebBundle\Entity\Package; -use Packagist\WebBundle\Model\DownloadManager; -use Packagist\WebBundle\Model\FavoriteManager; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Filesystem\LockHandler; -use Doctrine\DBAL\Connection; - -class IndexPackagesCommand extends ContainerAwareCommand -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('packagist:index') - ->setDefinition(array( - new InputOption('force', null, InputOption::VALUE_NONE, 'Force a re-indexing of all packages'), - new InputOption('all', null, InputOption::VALUE_NONE, 'Index all packages without clearing the index first'), - new InputArgument('package', InputArgument::OPTIONAL, 'Package name to index'), - )) - ->setDescription('Indexes packages in Algolia') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $verbose = $input->getOption('verbose'); - $force = $input->getOption('force'); - $indexAll = $input->getOption('all'); - $package = $input->getArgument('package'); - $indexName = $this->getContainer()->getParameter('algolia.index_name'); - - $deployLock = $this->getContainer()->getParameter('kernel.cache_dir').'/deploy.globallock'; - if (file_exists($deployLock)) { - if ($verbose) { - $output->writeln('Aborting, '.$deployLock.' file present'); - } - return; - } - - $doctrine = $this->getContainer()->get('doctrine'); - $algolia = $this->getContainer()->get('packagist.algolia.client'); - $index = $algolia->initIndex($indexName); - - $redis = $this->getContainer()->get('snc_redis.default'); - $downloadManager = $this->getContainer()->get('packagist.download_manager'); - $favoriteManager = $this->getContainer()->get('packagist.favorite_manager'); - - $lock = new LockHandler('packagist_algolia_indexer'); - - // another dumper is still active - if (!$lock->lock()) { - if ($verbose) { - $output->writeln('Aborting, another indexer is still active'); - } - return; - } - - if ($package) { - $packages = array(array('id' => $doctrine->getRepository('PackagistWebBundle:Package')->findOneByName($package)->getId())); - } elseif ($force || $indexAll) { - $packages = $doctrine->getManager()->getConnection()->fetchAll('SELECT id FROM package ORDER BY id ASC'); - $doctrine->getManager()->getConnection()->executeQuery('UPDATE package SET indexedAt = NULL'); - } else { - $packages = $doctrine->getRepository('PackagistWebBundle:Package')->getStalePackagesForIndexing(); - } - - $ids = array(); - foreach ($packages as $row) { - $ids[] = $row['id']; - } - - // clear index before a full-update - if ($force && !$package) { - if ($verbose) { - $output->writeln('Deleting existing index'); - } - - $index->clearIndex(); - } - - $total = count($ids); - $current = 0; - - // update package index - while ($ids) { - $indexTime = new \DateTime; - $idsSlice = array_splice($ids, 0, 50); - $packages = $doctrine->getRepository('PackagistWebBundle:Package')->findById($idsSlice); - - $idsToUpdate = []; - $records = []; - - foreach ($packages as $package) { - $current++; - if ($verbose) { - $output->writeln('['.sprintf('%'.strlen($total).'d', $current).'/'.$total.'] Indexing '.$package->getName()); - } - - // delete spam packages from the search index - if ($package->isAbandoned() && $package->getReplacementPackage() === 'spam/spam') { - try { - $index->deleteObject($package->getName()); - $idsToUpdate[] = $package->getId(); - continue; - } catch (\AlgoliaSearch\AlgoliaException $e) { - } - } - - try { - $tags = $this->getTags($doctrine, $package); - - $records[] = $this->packageToSearchableArray($package, $tags, $redis, $downloadManager, $favoriteManager); - - $idsToUpdate[] = $package->getId(); - } catch (\Exception $e) { - $output->writeln('Exception: '.$e->getMessage().', skipping package '.$package->getName().'.'); - - continue; - } - - $providers = $this->getProviders($doctrine, $package); - foreach ($providers as $provided) { - $records[] = $this->createSearchableProvider($provided['packageName']); - } - } - - try { - $index->addObjects($records); - } catch (\Exception $e) { - $output->writeln(''.get_class($e).': '.$e->getMessage().', occurred while processing packages: '.implode(',', $idsSlice).''); - continue; - } - - $doctrine->getManager()->clear(); - unset($packages); - - if ($verbose) { - $output->writeln('Updating package indexedAt column'); - } - - $this->updateIndexedAt($idsToUpdate, $doctrine, $indexTime->format('Y-m-d H:i:s')); - } - - $lock->release(); - } - - private function packageToSearchableArray( - Package $package, - array $tags, - $redis, - DownloadManager $downloadManager, - FavoriteManager $favoriteManager - ) { - $faversCount = $favoriteManager->getFaverCount($package); - $downloads = $downloadManager->getDownloads($package); - $downloadsLog = $downloads['monthly'] > 0 ? log($downloads['monthly'], 10) : 0; - $starsLog = $package->getGitHubStars() > 0 ? log($package->getGitHubStars(), 10) : 0; - $popularity = round($downloadsLog + $starsLog); - $trendiness = $redis->zscore('downloads:trending', $package->getId()); - - $record = [ - 'id' => $package->getId(), - 'objectID' => $package->getName(), - 'name' => $package->getName(), - 'package_organisation' => $package->getVendor(), - 'package_name' => $package->getPackageName(), - 'description' => preg_replace('{[\x00-\x1f]+}u', '', strip_tags($package->getDescription())), - 'type' => $package->getType(), - 'repository' => $package->getRepository(), - 'language' => $package->getLanguage(), - # log10 of downloads over the last 7days - 'trendiness' => $trendiness > 0 ? log($trendiness, 10) : 0, - # log10 of downloads + gh stars - 'popularity' => $popularity, - 'meta' => [ - 'downloads' => $downloads['total'], - 'downloads_formatted' => number_format($downloads['total'], 0, ',', ' '), - 'favers' => $faversCount, - 'favers_formatted' => number_format($faversCount, 0, ',', ' '), - ], - ]; - - if ($package->isAbandoned()) { - $record['abandoned'] = 1; - $record['replacementPackage'] = $package->getReplacementPackage() ?: ''; - } else { - $record['abandoned'] = 0; - $record['replacementPackage'] = ''; - } - - $record['tags'] = $tags; - - return $record; - } - - private function createSearchableProvider(string $provided) - { - $record = [ - 'id' => $provided, - 'objectID' => 'virtual:'.$provided, - 'name' => $provided, - 'package_organisation' => preg_replace('{/.*$}', '', $provided), - 'package_name' => preg_replace('{^[^/]*/}', '', $provided), - 'description' => '', - 'type' => 'virtual-package', - 'repository' => '', - 'language' => '', - 'trendiness' => 100, - 'popularity' => 4, - 'abandoned' => 0, - 'replacementPackage' => '', - 'tags' => [], - ]; - - return $record; - } - - private function getProviders($doctrine, Package $package) - { - return $doctrine->getManager()->getConnection()->fetchAll( - 'SELECT lp.packageName - FROM package p - JOIN package_version pv ON p.id = pv.package_id - JOIN link_provide lp ON lp.version_id = pv.id - WHERE p.id = :id - AND pv.development = true - GROUP BY lp.packageName', - ['id' => $package->getId()] - ); - } - - private function getTags($doctrine, Package $package) - { - $tags = $doctrine->getManager()->getConnection()->fetchAll( - 'SELECT t.name FROM package p - JOIN package_version pv ON p.id = pv.package_id - JOIN version_tag vt ON vt.version_id = pv.id - JOIN tag t ON t.id = vt.tag_id - WHERE p.id = :id - GROUP BY t.id, t.name', - ['id' => $package->getId()] - ); - - foreach ($tags as $idx => $tag) { - $tags[$idx] = $tag['name']; - } - - return array_map(function ($tag) { - return mb_strtolower(preg_replace('{[\x00-\x1f]+}u', '', $tag), 'UTF-8'); - }, $tags); - } - - private function updateIndexedAt(array $idsToUpdate, $doctrine, string $time) - { - $retries = 5; - // retry loop in case of a lock timeout - while ($retries--) { - try { - $doctrine->getManager()->getConnection()->executeQuery( - 'UPDATE package SET indexedAt=:indexed WHERE id IN (:ids)', - [ - 'ids' => $idsToUpdate, - 'indexed' => $time, - ], - ['ids' => Connection::PARAM_INT_ARRAY] - ); - } catch (\Exception $e) { - if (!$retries) { - throw $e; - } - sleep(2); - } - } - } -} diff --git a/src/Packagist/WebBundle/Command/RunWorkersCommand.php b/src/Packagist/WebBundle/Command/RunWorkersCommand.php index c6f7c94e..ea9140b2 100644 --- a/src/Packagist/WebBundle/Command/RunWorkersCommand.php +++ b/src/Packagist/WebBundle/Command/RunWorkersCommand.php @@ -7,7 +7,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\LockHandler; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Seld\Signal\SignalHandler; class RunWorkersCommand extends ContainerAwareCommand { diff --git a/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php b/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php index 1c0b9152..8cb0bdcd 100644 --- a/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php +++ b/src/Packagist/WebBundle/Command/UpdatePackagesCommand.php @@ -12,14 +12,6 @@ namespace Packagist\WebBundle\Command; -use Composer\Factory; -use Composer\IO\BufferIO; -use Composer\IO\ConsoleIO; -use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Loader\ValidatingArrayLoader; -use Composer\Repository\InvalidRepositoryException; -use Composer\Repository\VcsRepository; -use Packagist\WebBundle\Package\Updater; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -58,7 +50,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $package = $input->getArgument('package'); $doctrine = $this->getContainer()->get('doctrine'); - $router = $this->getContainer()->get('router'); $deleteBefore = false; $updateEqualRefs = false; $randomTimes = true; @@ -113,5 +104,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $locker->unlockCommand($this->getName()); + + return 0; } } diff --git a/src/Packagist/WebBundle/Controller/ApiController.php b/src/Packagist/WebBundle/Controller/ApiController.php index 84e91747..c64ed96f 100644 --- a/src/Packagist/WebBundle/Controller/ApiController.php +++ b/src/Packagist/WebBundle/Controller/ApiController.php @@ -14,11 +14,9 @@ use Packagist\WebBundle\Entity\Package; use Packagist\WebBundle\Entity\User; -use Packagist\WebBundle\Entity\Version; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; -use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -43,7 +41,7 @@ public function createPackageAction(Request $request) $package = new Package; $package->setEntityRepository($this->getDoctrine()->getRepository('PackagistWebBundle:Package')); $package->setRouter($this->get('router')); - $user = $this->findUser($request); + $user = $this->getUser(); $package->addMaintainer($user); $package->setRepository($url); $errors = $this->get('validator')->validate($package); @@ -116,7 +114,7 @@ public function updatePackageAction(Request $request) */ public function editPackageAction(Request $request, Package $package) { - $user = $this->findUser($request); + $user = $this->getUser(); if (!$package->getMaintainers()->contains($user) && !$this->isGranted('ROLE_EDIT_PACKAGES')) { throw new AccessDeniedException; } @@ -254,14 +252,13 @@ protected function receivePost(Request $request, $url, $urlRegex) } // find the user - $user = $this->findUser($request); - + $user = $this->getUser(); if (!$user) { return new Response(json_encode(array('status' => 'error', 'message' => 'Invalid credentials')), 403); } - // try to find the user package - $packages = $this->findPackagesByUrl($user, $url, $urlRegex); + // try to find the all package + $packages = $this->findPackagesByUrl($url, $urlRegex); if (!$packages) { return new Response(json_encode(array('status' => 'error', 'message' => 'Could not find a package that matches this request (does user maintain the package?)')), 404); @@ -312,19 +309,19 @@ protected function findUser(Request $request) /** * Find a user package given by its full URL * - * @param User $user * @param string $url * @param string $urlRegex * @return array the packages found */ - protected function findPackagesByUrl(User $user, $url, $urlRegex) + protected function findPackagesByUrl($url, $urlRegex) { if (!preg_match($urlRegex, $url, $matched)) { - return array(); + return []; } - $packages = array(); - foreach ($user->getPackages() as $package) { + $packages = []; + $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Package'); + foreach ($repo->findAll() as $package) { if (preg_match($urlRegex, $package->getRepository(), $candidate) && strtolower($candidate['host']) === strtolower($matched['host']) && strtolower($candidate['path']) === strtolower($matched['path']) diff --git a/src/Packagist/WebBundle/Controller/GroupController.php b/src/Packagist/WebBundle/Controller/GroupController.php index e90c4b2a..6ecdebd4 100644 --- a/src/Packagist/WebBundle/Controller/GroupController.php +++ b/src/Packagist/WebBundle/Controller/GroupController.php @@ -93,8 +93,8 @@ protected function handleUpdate(Request $request, Group $group, $flashMessage) { $form = $this->createForm(GroupType::class, $group); if ($request->getMethod() === 'POST') { - $form->submit($request); - if ($form->isValid()) { + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { $group = $form->getData(); $em = $this->getDoctrine()->getManager(); $em->persist($group); diff --git a/src/Packagist/WebBundle/Controller/PackageController.php b/src/Packagist/WebBundle/Controller/PackageController.php index 39f03f25..c60d003a 100644 --- a/src/Packagist/WebBundle/Controller/PackageController.php +++ b/src/Packagist/WebBundle/Controller/PackageController.php @@ -25,6 +25,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -46,6 +47,10 @@ class PackageController extends Controller */ public function allAction(Request $req) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + return new RedirectResponse($this->generateUrl('browse'), Response::HTTP_MOVED_PERMANENTLY); } @@ -56,6 +61,10 @@ public function allAction(Request $req) */ public function listAction(Request $req) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + /** @var PackageRepository $repo */ $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Package'); $fields = (array) $req->query->get('fields', array()); @@ -88,7 +97,7 @@ public function listAction(Request $req) public function submitPackageAction(Request $req) { $user = $this->getUser(); - if (!$user->isEnabled()) { + if (!$user->isEnabled() || !$this->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); } @@ -126,10 +135,14 @@ public function submitPackageAction(Request $req) */ public function fetchInfoAction(Request $req) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $package = new Package; $package->setEntityRepository($this->getDoctrine()->getRepository('PackagistWebBundle:Package')); $package->setRouter($this->get('router')); - $form = $this->createForm(new PackageType, $package); + $form = $this->createForm(PackageType::class, $package); $user = $this->getUser(); $package->addMaintainer($user); @@ -183,6 +196,10 @@ public function fetchInfoAction(Request $req) */ public function viewVendorAction($vendor) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $packages = $this->getDoctrine() ->getRepository('PackagistWebBundle:Package') ->getFilteredQueryBuilder(['vendor' => $vendor.'/%'], true) @@ -201,37 +218,6 @@ public function viewVendorAction($vendor) ); } - /** - * @Route( - * "/p/{name}.{_format}", - * name="view_package_alias", - * requirements={"name"="[A-Za-z0-9_.-]+(/[A-Za-z0-9_.-]+?)?", "_format"="(json)"}, - * defaults={"_format"="html"} - * ) - * @Route( - * "/packages/{name}", - * name="view_package_alias2", - * requirements={"name"="[A-Za-z0-9_.-]+(/[A-Za-z0-9_.-]+?)?/"}, - * defaults={"_format"="html"} - * ) - * @Method({"GET"}) - */ - public function viewPackageAliasAction(Request $req, $name) - { - $format = $req->getRequestFormat(); - if ($format === 'html') { - $format = null; - } - if ($format === 'json' || (!$format && substr($name, -5) === '.json')) { - throw new NotFoundHttpException('Package not found'); - } - if (false === strpos(trim($name, '/'), '/')) { - return $this->redirect($this->generateUrl('view_vendor', array('vendor' => $name, '_format' => $format))); - } - - return $this->redirect($this->generateUrl('view_package', array('name' => trim($name, '/'), '_format' => $format))); - } - /** * @Route( * "/providers/{name}", @@ -243,6 +229,10 @@ public function viewPackageAliasAction(Request $req, $name) */ public function viewProvidersAction($name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + /** @var PackageRepository $repo */ $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Package'); $providers = $repo->findProviders($name); @@ -293,6 +283,9 @@ public function viewPackageAction(Request $req, $name) $req->getSession()->save(); if (preg_match('{^(?Pext-[a-z0-9_.-]+?)/(?Pdependents|suggesters)$}i', $name, $match)) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedHttpException; + } return $this->{$match['method'].'Action'}($req, $match['pkg']); } @@ -303,19 +296,11 @@ public function viewPackageAction(Request $req, $name) /** @var Package $package */ $package = $repo->getPartialPackageByNameWithVersions($name); } catch (NoResultException $e) { - if ('json' === $req->getRequestFormat()) { - return new JsonResponse(array('status' => 'error', 'message' => 'Package not found'), 404); - } - - if ($providers = $repo->findProviders($name)) { - return $this->redirect($this->generateUrl('view_providers', array('name' => $name))); - } - - return $this->redirect($this->generateUrl('search', array('q' => $name, 'reason' => 'package_not_found'))); + throw new NotFoundHttpException; } - if ($package->isAbandoned() && $package->getReplacementPackage() === 'spam/spam') { - throw new NotFoundHttpException('This is a spam package'); + if (!$this->isGranted('ROLE_ADMIN', $package)) { + throw new NotFoundHttpException; } if ('json' === $req->getRequestFormat()) { @@ -416,6 +401,10 @@ public function viewPackageAction(Request $req, $name) */ public function viewPackageDownloadsAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedHttpException; + } + /** @var PackageRepository $repo */ $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Package'); @@ -475,6 +464,9 @@ public function viewPackageVersionAction(Request $req, $versionId) /** @var VersionRepository $repo */ $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Version'); + if (!$this->isGranted('ROLE_ADMIN', $repo->find($versionId))) { + throw new AccessDeniedHttpException; + } $html = $this->renderView( 'PackagistWebBundle:Package:versionDetails.html.twig', @@ -494,6 +486,10 @@ public function viewPackageVersionAction(Request $req, $versionId) */ public function deletePackageVersionAction(Request $req, $versionId) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + /** @var VersionRepository $repo */ $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Version'); @@ -522,6 +518,10 @@ public function deletePackageVersionAction(Request $req, $versionId) */ public function updatePackageAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $doctrine = $this->getDoctrine(); try { @@ -581,6 +581,10 @@ public function updatePackageAction(Request $req, $name) */ public function deletePackageAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $doctrine = $this->getDoctrine(); try { @@ -613,6 +617,10 @@ public function deletePackageAction(Request $req, $name) */ public function createMaintainerAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + /** @var $package Package */ $package = $this->getDoctrine() ->getRepository('PackagistWebBundle:Package') @@ -670,6 +678,10 @@ public function createMaintainerAction(Request $req, $name) */ public function removeMaintainerAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + /** @var $package Package */ $package = $this->getDoctrine() ->getRepository('PackagistWebBundle:Package') @@ -831,6 +843,10 @@ public function unabandonAction(Package $package) */ public function statsAction(Request $req, Package $package) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $versions = $package->getVersions()->toArray(); usort($versions, Package::class.'::sortVersions'); $date = $this->guessStatsStartDate($package); @@ -874,6 +890,10 @@ public function statsAction(Request $req, Package $package) */ public function dependentsAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $page = $req->query->get('page', 1); /** @var PackageRepository $repo */ @@ -903,6 +923,10 @@ public function dependentsAction(Request $req, $name) */ public function suggestersAction(Request $req, $name) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $page = $req->query->get('page', 1); /** @var PackageRepository $repo */ @@ -933,6 +957,10 @@ public function suggestersAction(Request $req, $name) */ public function overallStatsAction(Request $req, Package $package, Version $version = null) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + if ($from = $req->query->get('from')) { $from = new DateTimeImmutable($from); } else { @@ -1008,6 +1036,10 @@ public function overallStatsAction(Request $req, Package $package, Version $vers */ public function versionStatsAction(Request $req, Package $package, $version) { + if (!$this->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException; + } + $normalizer = new VersionParser; $normVersion = $normalizer->normalize($version); diff --git a/src/Packagist/WebBundle/Controller/ProviderController.php b/src/Packagist/WebBundle/Controller/ProviderController.php index be607ae6..ef2c20b5 100644 --- a/src/Packagist/WebBundle/Controller/ProviderController.php +++ b/src/Packagist/WebBundle/Controller/ProviderController.php @@ -4,6 +4,7 @@ use Packagist\WebBundle\Entity\Package; use Packagist\WebBundle\Entity\Version; +use Packagist\WebBundle\Service\DistManager; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; @@ -22,7 +23,7 @@ public function packagesAction() $manager = $this->container->get('packagist.package_manager'); $rootPackages = $manager->getRootPackagesJson($this->getUser()); - return new JsonResponse($rootPackages); + return new Response(\json_encode($rootPackages), 200, ['Content-Type' => 'application/json']); } /** @@ -45,7 +46,7 @@ public function providersAction($hash) return $this->createNotFound(); } - return new JsonResponse($providers); + return new Response(\json_encode($providers), 200, ['Content-Type' => 'application/json']); } /** @@ -73,7 +74,7 @@ public function packageAction($package) return $this->createNotFound(); } - return new JsonResponse($package); + return new Response(\json_encode($package), 200, ['Content-Type' => 'application/json']); } /** @@ -92,6 +93,7 @@ public function packageAction($package) public function zipballAction(Package $package, $hash) { $config = $this->container->get('packagist.dist_config'); + $distManager = new DistManager($config); if (false === \preg_match('{[a-f0-9]{40}}i', $hash, $match)) { return new JsonResponse(['status' => 'error', 'message' => 'Not Found'], 404); } @@ -105,19 +107,35 @@ function (Version $version) use ($match) { } ); + // Try to download from cache + if ($versions->count() === 0) { + list($path, $versionName) = $distManager->lookupInCache($match[0], $package->getName()); + if (null !== $versionName) { + $version = $package->getVersions() + ->filter( + function (Version $version) use ($versionName) { + return $versionName === $version->getVersion(); + } + )->first(); + if ($version && $this->isGranted('ROLE_ADMIN', $version)) { + return new BinaryFileResponse($path); + } + } + } + /** @var Version $version */ foreach ($versions as $version) { - if (false === $this->isGranted('ROLE_USER', $version)) { + if (!$this->isGranted('ROLE_ADMIN', $version)) { continue; } - $dist = $version->getDist(); - if ($file = $config->generateDistFileName($version->getName(), $dist['reference']) and \file_exists($file)) { - return new BinaryFileResponse($file); + if ($path = $distManager->getDistPath($version)) { + return new BinaryFileResponse($path); } + break; } - return new JsonResponse(['status' => 'error', 'message' => 'Not Found'], 404); + return $this->createNotFound(); } protected function createNotFound() diff --git a/src/Packagist/WebBundle/Controller/UserController.php b/src/Packagist/WebBundle/Controller/UserController.php index c39790a4..260c4801 100644 --- a/src/Packagist/WebBundle/Controller/UserController.php +++ b/src/Packagist/WebBundle/Controller/UserController.php @@ -87,6 +87,7 @@ public function updateAction(Request $request, User $user) public function createAction(Request $request) { $user = new User(); + $user->generateApiToken(); return $this->handleUpdate($request, $user, 'User has been saved.'); } @@ -94,8 +95,8 @@ protected function handleUpdate(Request $request, User $user, $flashMessage) { $form = $this->createForm(CustomerUserType::class, $user); if ($request->getMethod() === 'POST') { - $form->submit($request); - if ($form->isValid()) { + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { $user = $form->getData(); $this->get('fos_user.user_manager')->updateUser($user); @@ -156,17 +157,39 @@ public function myProfileAction(Request $req) */ public function profileAction(Request $req, User $user) { + $deleteForm = $this->createFormBuilder([])->getForm(); $packages = $this->getUserPackages($req, $user); $data = [ 'packages' => $packages, 'meta' => $this->getPackagesMetadata($packages), 'user' => $user, + 'deleteForm' => $deleteForm->createView() ]; return $data; } + /** + * @Route("/users/{name}/delete", name="user_delete") + * @ParamConverter("user", options={"mapping": {"name": "username"}}) + */ + public function deleteAction(Request $request, User $user) + { + $form = $this->createFormBuilder([])->getForm(); + $form->submit($request->request->get('form')); + if ($form->isValid()) { + $request->getSession()->save(); + $em = $this->getDoctrine()->getManager(); + $em->remove($user); + $em->flush(); + + return new RedirectResponse('/'); + } + + return new Response('Invalid form input', 400); + } + /** * @Template() * @Route("/users/{name}/favorites/", name="user_favorites") diff --git a/src/Packagist/WebBundle/Controller/WebController.php b/src/Packagist/WebBundle/Controller/WebController.php index d8c6233a..94ec903a 100644 --- a/src/Packagist/WebBundle/Controller/WebController.php +++ b/src/Packagist/WebBundle/Controller/WebController.php @@ -12,18 +12,19 @@ namespace Packagist\WebBundle\Controller; +use Doctrine\ORM\QueryBuilder; +use Packagist\WebBundle\Entity\Package; use Packagist\WebBundle\Form\Model\SearchQuery; use Packagist\WebBundle\Form\Type\SearchQueryType; use Pagerfanta\Adapter\ArrayAdapter; +use Pagerfanta\Adapter\CallbackAdapter; use Pagerfanta\Pagerfanta; use Predis\Connection\ConnectionException; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; -use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** * @author Jordi Boggiano @@ -33,10 +34,20 @@ class WebController extends Controller /** * @Template() * @Route("/", name="home") + * + * @param Request $request + * @return array */ - public function indexAction() + public function indexAction(Request $request) { - return array('page' => 'home'); + $page = $request->query->get('page', 1); + $paginator = new Pagerfanta($this->createAdapter()); + $paginator->setMaxPerPage(10); + $paginator->setCurrentPage($page); + + return [ + 'packages' => $paginator + ]; } /** @@ -79,9 +90,14 @@ public function searchAction(Request $req) $perPage = max(0, min(100, $perPage)); } + $allowed = $this->isGranted('ROLE_ADMIN') ? null : + $this->getDoctrine() + ->getRepository('PackagistWebBundle:Group') + ->getAllowedPackagesForUser($this->getUser(), false); + $page = $req->query->get('page', 1) - 1; $packages = $this->getDoctrine()->getRepository('PackagistWebBundle:Package') - ->searchPackage($query, $perPage, $page); + ->searchPackage($query, $perPage, $page, $allowed); } $paginator = new Pagerfanta(new ArrayAdapter($packages)); @@ -328,4 +344,47 @@ private function computeSearchQuery(Request $req, array $filteredOrderBys) ); } } + + private function createAdapter() + { + /** @var QueryBuilder $qb */ + $qb = $this->get('doctrine')->getManager()->createQueryBuilder(); + $qb->from('PackagistWebBundle:Package', 'p'); + $repo = $this->get('doctrine')->getRepository('PackagistWebBundle:Package'); + if (!$this->isGranted('ROLE_ADMIN')) { + $packages = $this->get('doctrine')->getRepository('PackagistWebBundle:Group') + ->getAllowedPackagesForUser($this->getUser()); + $qb->andWhere('p.id IN (:ids)') + ->setParameter('ids', $packages); + } + + $adapter = new CallbackAdapter( + function () use ($qb) { + $qb = clone $qb; + $qb->select('COUNT(1)'); + return $qb->getQuery()->getSingleScalarResult(); + }, + function ($offset, $length) use ($qb, $repo) { + $qb = clone $qb; + $qb->select('p') + ->setMaxResults($length) + ->setFirstResult($offset) + ->orderBy('p.id', 'DESC'); + + $packages = array_map( + function (Package $package) use ($repo) { + return [ + 'package' => $package, + 'dependencies' => $repo->getDependents($package->getName()) + ]; + }, + $qb->getQuery()->getResult() + ); + + return $packages; + } + ); + + return $adapter; + } } diff --git a/src/Packagist/WebBundle/DependencyInjection/Security/ApiHttpBasicFactory.php b/src/Packagist/WebBundle/DependencyInjection/Security/ApiHttpBasicFactory.php index 319a5d2b..a3c2806b 100644 --- a/src/Packagist/WebBundle/DependencyInjection/Security/ApiHttpBasicFactory.php +++ b/src/Packagist/WebBundle/DependencyInjection/Security/ApiHttpBasicFactory.php @@ -4,8 +4,8 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; use Symfony\Component\Config\Definition\Builder\NodeDefinition; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Reference; class ApiHttpBasicFactory implements SecurityFactoryInterface @@ -15,35 +15,23 @@ class ApiHttpBasicFactory implements SecurityFactoryInterface */ public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) { - $provider = 'packagist.security.authentication.provider.'.$id; + $provider = 'packagist.security.authentication.provider.' . $id; $container - ->setDefinition($provider, new DefinitionDecorator('packagist.security.authentication.provider')); + ->setDefinition($provider, new ChildDefinition('packagist.security.authentication.provider')) + ->replaceArgument(1, new Reference('security.user_checker.'.$id)); // entry point $entryPointId = $this->createEntryPoint($container, $id, $config, $defaultEntryPoint); // listener $listenerId = 'packagist.security.authentication.listener.'.$id; - $listener = $container->setDefinition($listenerId, new DefinitionDecorator('packagist.security.authentication.listener')); + $listener = $container->setDefinition($listenerId, new ChildDefinition('packagist.security.authentication.listener')); $listener->replaceArgument(2, $id) ->replaceArgument(3, new Reference($entryPointId)); return [$provider, $listenerId, $entryPointId]; } - protected function createEntryPoint(ContainerBuilder $container, $id, $config, $defaultEntryPoint) - { - if (null !== $defaultEntryPoint) { - return $defaultEntryPoint; - } - - $entryPointId = 'packagist.authentication.entry_point.'.$id; - $container - ->setDefinition($entryPointId, new DefinitionDecorator('packagist.authentication.entry_point')); - - return $entryPointId; - } - /** * {@inheritdoc} */ @@ -63,4 +51,17 @@ public function getKey() public function addConfiguration(NodeDefinition $builder) { } + + protected function createEntryPoint(ContainerBuilder $container, $id, $config, $defaultEntryPoint) + { + if (null !== $defaultEntryPoint) { + return $defaultEntryPoint; + } + + $entryPointId = 'packagist.authentication.entry_point.'.$id; + $container + ->setDefinition($entryPointId, new ChildDefinition('packagist.authentication.entry_point')); + + return $entryPointId; + } } diff --git a/src/Packagist/WebBundle/Entity/GroupRepository.php b/src/Packagist/WebBundle/Entity/GroupRepository.php index cf9af88c..d9a9b927 100644 --- a/src/Packagist/WebBundle/Entity/GroupRepository.php +++ b/src/Packagist/WebBundle/Entity/GroupRepository.php @@ -39,10 +39,11 @@ public function getAllowedVersionByPackage(User $user, Package $package) /** * @param User $user + * @param bool $hydration * * @return Package[] */ - public function getAllowedPackagesForUser(User $user) + public function getAllowedPackagesForUser(User $user, $hydration = true) { $qb = $this->_em->createQueryBuilder(); $qb @@ -55,7 +56,7 @@ public function getAllowedPackagesForUser(User $user) ->where($qb->expr()->eq('u.id', $user->getId())); $result = $qb->getQuery()->getResult(); - if ($result) { + if ($hydration && $result) { $qb = $this->_em->createQueryBuilder(); $qb->select('p') ->from('PackagistWebBundle:Package', 'p') @@ -65,6 +66,6 @@ public function getAllowedPackagesForUser(User $user) return $qb->getQuery()->getResult(); } - return []; + return $result ? array_column($result, 'id') : []; } } diff --git a/src/Packagist/WebBundle/Entity/Package.php b/src/Packagist/WebBundle/Entity/Package.php index 2de8e0d1..d4ea4a5f 100644 --- a/src/Packagist/WebBundle/Entity/Package.php +++ b/src/Packagist/WebBundle/Entity/Package.php @@ -33,7 +33,6 @@ * } * ) * @Assert\Callback(callback="isPackageUnique") - * @Assert\Callback(callback="isVendorWritable") * @Assert\Callback(callback="isRepositoryValid", groups={"Update", "Default"}) * @author Jordi Boggiano */ @@ -609,9 +608,6 @@ public function setRepository($repoUrl) if (null === $this->getName()) { $this->setName($information['name']); } - if ($driver instanceof GitHubDriver) { - $this->repository = $driver->getRepositoryUrl(); - } } catch (\Exception $e) { $this->vcsDriverError = '['.get_class($e).'] '.$e->getMessage(); } @@ -674,6 +670,14 @@ public function getVersion($normalizedVersion) } } + /** + * @return Version|null + */ + public function getHighest() + { + return $this->getVersion('9999999-dev'); + } + /** * Set updatedAt * diff --git a/src/Packagist/WebBundle/Entity/PackageRepository.php b/src/Packagist/WebBundle/Entity/PackageRepository.php index 64d1d15d..15d0b758 100644 --- a/src/Packagist/WebBundle/Entity/PackageRepository.php +++ b/src/Packagist/WebBundle/Entity/PackageRepository.php @@ -12,6 +12,7 @@ namespace Packagist\WebBundle\Entity; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Platforms\PostgreSqlPlatform; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; @@ -131,19 +132,15 @@ public function getStalePackages() WHERE p.abandoned = false AND ( p.crawledAt IS NULL - OR (p.autoUpdated = false AND p.crawledAt < :recent AND p.createdAt >= :yesterday) OR (p.autoUpdated = false AND p.crawledAt < :crawled) OR (p.crawledAt < :autocrawled) ) ORDER BY p.id ASC', array( - // crawl new packages once an hour for the first day so that dummy packages get deleted ASAP - 'recent' => date('Y-m-d H:i:s', strtotime('-1hour')), - 'yesterday' => date('Y-m-d H:i:s', strtotime('-1day')), // crawl packages without auto-update once a week - 'crawled' => date('Y-m-d H:i:s', strtotime('-1week')), - // crawl auto-updated packages once a month just in case - 'autocrawled' => date('Y-m-d H:i:s', strtotime('-1month')), + 'crawled' => date('Y-m-d H:i:s', strtotime('-4hour')), + // crawl auto-updated packages once a week just in case + 'autocrawled' => date('Y-m-d H:i:s', strtotime('-7day')), ) ); } @@ -429,33 +426,38 @@ public function getPackagesStatisticsByMonthAndYear() return $qb->getQuery()->getResult(); } - public function searchPackage(string $search, int $limit = 10, int $page = 0) + public function searchPackage(string $search, int $limit = 10, int $page = 0, array $allowed = null) { $conn = $this->getEntityManager()->getConnection(); if ($conn->getDatabasePlatform() instanceof PostgreSqlPlatform && $this->checkExtension('fuzzystrmatch')) { - $packages = []; - $sql = 'SELECT levenshtein(name, :search)/(1.0 + length(name)) AS idx, id - FROM package - ORDER BY idx LIMIT :limit OFFSET :ofs'; - $packagesId = $conn - ->executeQuery( - $sql, - ['search' => $search, 'limit' => $limit, 'ofs' => $page * $limit] - )->fetchAll(); - - if ($packagesId) { - foreach (array_column($packagesId, 'id') as $id) { - $packages[] = $this->find($id); - } + $params = ['search' => $search, 'limit' => $limit, 'ofs' => $page * $limit]; + $sql = 'SELECT levenshtein(name, :search)/(1.0 + length(name)) AS idx, id' + . ' FROM package '; + + if (null !== $allowed) { + $sql .= ' WHERE id IN (:ids) '; + $params['ids'] = $allowed; } - return $packages; + $sql .= 'ORDER BY idx LIMIT :limit OFFSET :ofs'; + + return array_map( + function ($item) { + return $this->find($item['id']); + }, + $conn->executeQuery($sql, $params, ['ids' => Connection::PARAM_INT_ARRAY])->fetchAll() + ); } $qb = $this->createQueryBuilder('p'); + if (null !== $allowed) { + $qb->andWhere('p.id IN (:ids)') + ->setParameter('ids', $allowed); + } - return $qb->where( + return $qb->andWhere( $qb->expr()->like('p.name', ':name') - )->setParameter('name', $search) + ) + ->setParameter('name', '%' . $search . '%') ->setMaxResults($limit) ->setFirstResult($limit * $page) ->getQuery()->getResult(); diff --git a/src/Packagist/WebBundle/Entity/User.php b/src/Packagist/WebBundle/Entity/User.php index 201d8a34..47f9d4b2 100644 --- a/src/Packagist/WebBundle/Entity/User.php +++ b/src/Packagist/WebBundle/Entity/User.php @@ -115,6 +115,12 @@ class User extends BaseUser */ private $failureNotifications = true; + /** + * @ORM\Column(name="expires_at", type="date", nullable=true) + * @var \DateTime + */ + private $expiresAt; + public function __construct() { $this->packages = new ArrayCollection(); @@ -324,6 +330,35 @@ public function getExpiresAt() return $this->expiresAt; } + /** + * @param \DateTime $expiresAt + * @return $this + */ + public function setExpiresAt($expiresAt) + { + $this->expiresAt = $expiresAt; + return $this; + } + + public function generateApiToken() + { + $this->apiToken = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='); + $this->apiToken = substr($this->apiToken, 0, 20); + return $this->apiToken; + } + + /** + * {@inheritdoc} + */ + public function isAccountNonExpired() + { + if (null === $this->expiresAt) { + return true; + } + + return new \DateTime('now') < $this->expiresAt; + } + /** * @return bool */ diff --git a/src/Packagist/WebBundle/Entity/Version.php b/src/Packagist/WebBundle/Entity/Version.php index 1dc3355f..646f3948 100644 --- a/src/Packagist/WebBundle/Entity/Version.php +++ b/src/Packagist/WebBundle/Entity/Version.php @@ -211,7 +211,7 @@ public function __construct() $this->updatedAt = new \DateTime; } - public function toArray(array $versionData) + public function toArray(array $versionData = []) { $tags = array(); foreach ($this->getTags() as $tag) { diff --git a/src/Packagist/WebBundle/Form/Handler/OAuthRegistrationFormHandler.php b/src/Packagist/WebBundle/Form/Handler/OAuthRegistrationFormHandler.php deleted file mode 100644 index 9f42b80e..00000000 --- a/src/Packagist/WebBundle/Form/Handler/OAuthRegistrationFormHandler.php +++ /dev/null @@ -1,99 +0,0 @@ - - * Nils Adermann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Packagist\WebBundle\Form\Handler; - -use FOS\UserBundle\Model\UserManagerInterface; -use FOS\UserBundle\Util\TokenGeneratorInterface; -use HWI\Bundle\OAuthBundle\Form\RegistrationFormHandlerInterface; -use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface; -use Symfony\Component\Form\Form; -use Symfony\Component\HttpFoundation\Request; - -/** - * OAuthRegistrationFormHandler - * - * @author Alexander - */ -class OAuthRegistrationFormHandler implements RegistrationFormHandlerInterface -{ - private $userManager; - private $tokenGenerator; - - /** - * Constructor. - * - * @param UserManagerInterface $userManager - * @param TokenGeneratorInterface $tokenGenerator - */ - public function __construct(UserManagerInterface $userManager, TokenGeneratorInterface $tokenGenerator) - { - $this->tokenGenerator = $tokenGenerator; - $this->userManager = $userManager; - } - - /** - * {@inheritDoc} - */ - public function process(Request $request, Form $form, UserResponseInterface $userInformation) - { - $user = $this->userManager->createUser(); - - // Try to get some properties for the initial form when coming from github - if ('GET' === $request->getMethod()) { - $user->setUsername($this->getUniqueUsername($userInformation->getNickname())); - $user->setEmail($userInformation->getEmail()); - } - - $form->setData($user); - - if ('POST' === $request->getMethod()) { - $form->handleRequest($request); - - if ($form->isValid()) { - if (!$user->getPassword() && !$user->getPlainPassword()) { - $randomPassword = $this->tokenGenerator->generateToken(); - $user->setPlainPassword($randomPassword); - } - $user->setEnabled(true); - - $apiToken = substr($this->tokenGenerator->generateToken(), 0, 20); - $user->setApiToken($apiToken); - - return true; - } - } - - return false; - } - - /** - * Attempts to get a unique username for the user. - * - * @param string $name - * - * @return string Name, or empty string if it failed after 10 times - * - * @see HWI\Bundle\OAuthBundle\Form\FOSUBRegistrationHandler - */ - protected function getUniqueUserName($name) - { - $i = 0; - $testName = $name; - - do { - $user = $this->userManager->findUserByUsername($testName); - } while ($user !== null && $i < 10 && $testName = $name.++$i); - - return $user !== null ? '' : $testName; - } -} diff --git a/src/Packagist/WebBundle/Form/Type/PackagePermissionType.php b/src/Packagist/WebBundle/Form/Type/PackagePermissionType.php index 2b683c23..27ae2a52 100644 --- a/src/Packagist/WebBundle/Form/Type/PackagePermissionType.php +++ b/src/Packagist/WebBundle/Form/Type/PackagePermissionType.php @@ -28,7 +28,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'label' => 'Version', 'required' => false, 'attr' => [ - 'placeholder' => 'Version (example ^1.0|^2.0)' + 'placeholder' => '^1.0|^2.0' ], 'constraints' => [new Callback($this->versionValidator())] ] diff --git a/src/Packagist/WebBundle/Form/Type/PackageType.php b/src/Packagist/WebBundle/Form/Type/PackageType.php index 04c7fba7..ebcc78b2 100644 --- a/src/Packagist/WebBundle/Form/Type/PackageType.php +++ b/src/Packagist/WebBundle/Form/Type/PackageType.php @@ -32,7 +32,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'label' => 'SSH Credentials (optional)', 'required' => false, 'class' => SshCredentials::class, - 'property' => 'name' + 'choice_label' => 'name' ]) ->add('repository', TextType::class, [ 'label' => 'Repository URL (Git/Svn/Hg)', diff --git a/src/Packagist/WebBundle/Menu/MenuBuilder.php b/src/Packagist/WebBundle/Menu/MenuBuilder.php index b9f7f84a..360eb3e5 100644 --- a/src/Packagist/WebBundle/Menu/MenuBuilder.php +++ b/src/Packagist/WebBundle/Menu/MenuBuilder.php @@ -43,7 +43,7 @@ public function createUserMenu() $this->addProfileMenu($menu); $menu->addChild('hr', ['label' => '
', 'labelAttributes' => ['class' => 'normal'], 'extras' => ['safe_label' => true]]); - $menu->addChild($this->translator->trans('menu.logout'), ['label' => '' . $this->translator->trans('menu.logout'), 'route' => 'logout', 'extras' => ['safe_label' => true]]); + $menu->addChild($this->translator->trans('menu.logout'), ['label' => '' . $this->translator->trans('menu.logout'), 'route' => 'fos_user_security_logout', 'extras' => ['safe_label' => true]]); return $menu; } diff --git a/src/Packagist/WebBundle/Model/ValidatingArrayLoader.php b/src/Packagist/WebBundle/Model/ValidatingArrayLoader.php new file mode 100644 index 00000000..faebab37 --- /dev/null +++ b/src/Packagist/WebBundle/Model/ValidatingArrayLoader.php @@ -0,0 +1,32 @@ + $license) { + if ('proprietary' === $license || !$licenseValidator->validate($license)) { + unset($licenses[$key]); + }; + } + + if (!$licenses) { + unset($config['license']); + } else { + $config['license'] = \count($licenses) === 1 ? \reset($licenses) : $licenses; + } + } + + return parent::load($config, $class); + } +} diff --git a/src/Packagist/WebBundle/Package/ArchiveManager.php b/src/Packagist/WebBundle/Package/ArchiveManager.php deleted file mode 100644 index 511d8dce..00000000 --- a/src/Packagist/WebBundle/Package/ArchiveManager.php +++ /dev/null @@ -1,26 +0,0 @@ -getSourceReference())) { - return $package->getSourceReference(); - } - - return parent::getPackageFilename($package); - } -} diff --git a/src/Packagist/WebBundle/Package/InMemoryDumper.php b/src/Packagist/WebBundle/Package/InMemoryDumper.php index b8746f03..d88bcf58 100644 --- a/src/Packagist/WebBundle/Package/InMemoryDumper.php +++ b/src/Packagist/WebBundle/Package/InMemoryDumper.php @@ -38,7 +38,7 @@ private function dumpRootPackages(User $user = null) $userHash = \hash('sha256', \json_encode($providers)); $rootFile['provider-includes'] = [ - '/p/providers$%hash%.json' => [ + 'p/providers$%hash%.json' => [ 'sha256' => $userHash ] ]; @@ -71,7 +71,10 @@ private function dumpUserPackages(User $user = null) $versionData = $versionRepo->getVersionData(\array_keys($versionIds)); foreach ($versionIds as $version) { - $packageData[$version->getVersion()] = $version->toArray($versionData); + $packageData[$version->getVersion()] = \array_merge( + $version->toArray($versionData), + ['uid' => $version->getId()] + ); } $packageData = [ diff --git a/src/Packagist/WebBundle/Package/SymlinkDumper.php b/src/Packagist/WebBundle/Package/SymlinkDumper.php deleted file mode 100644 index 34d3dc35..00000000 --- a/src/Packagist/WebBundle/Package/SymlinkDumper.php +++ /dev/null @@ -1,726 +0,0 @@ - - * Nils Adermann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Packagist\WebBundle\Package; - -use Symfony\Component\Filesystem\Filesystem; -use Composer\Util\Filesystem as ComposerFilesystem; -use Symfony\Bridge\Doctrine\RegistryInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Finder\Finder; -use Packagist\WebBundle\Entity\Version; -use Doctrine\DBAL\Connection; - -/** - * @author Jordi Boggiano - */ -class SymlinkDumper -{ - /** - * Doctrine - * @var RegistryInterface - */ - protected $doctrine; - - /** - * @var Filesystem - */ - protected $fs; - - /** - * @var ComposerFilesystem - */ - protected $cfs; - - /** - * @var string - */ - protected $webDir; - - /** - * @var string - */ - protected $buildDir; - - /** - * @var UrlGeneratorInterface - */ - protected $router; - - /** - * Data cache - * @var array - */ - private $rootFile; - - /** - * Data cache - * @var array - */ - private $listings = array(); - - /** - * Data cache - * @var array - */ - private $individualFiles = array(); - - /** - * Modified times of individual files - * @var array - */ - private $individualFilesMtime = array(); - - /** - * Stores all the disk writes to be replicated in the second build dir after the symlink has been swapped - * @var array - */ - private $writeLog = array(); - - /** - * Generate compressed files. - * @var int 0 disabled, 9 maximum. - */ - private $compress; - - /** - * Constructor - * - * @param RegistryInterface $doctrine - * @param Filesystem $filesystem - * @param UrlGeneratorInterface $router - * @param string $webDir web root - * @param string $targetDir - * @param int $compress - */ - public function __construct(RegistryInterface $doctrine, Filesystem $filesystem, UrlGeneratorInterface $router, $webDir, $targetDir, $compress) - { - $this->doctrine = $doctrine; - $this->fs = $filesystem; - $this->cfs = new ComposerFilesystem; - $this->router = $router; - $this->webDir = realpath($webDir); - $this->buildDir = $targetDir; - $this->compress = $compress; - } - - /** - * Dump a set of packages to the web root - * - * @param array $packageIds - * @param Boolean $force - * @param Boolean $verbose - */ - public function dump(array $packageIds, $force = false, $verbose = false) - { - $cleanUpOldFiles = date('i') == 0; - - // prepare build dir - $webDir = $this->webDir; - - $buildDirA = $this->buildDir.'/a'; - $buildDirB = $this->buildDir.'/b'; - - // initialize - $initialRun = false; - if (!is_dir($buildDirA) || !is_dir($buildDirB)) { - $initialRun = true; - if (!$this->removeDirectory($buildDirA) || !$this->removeDirectory($buildDirB)) { - throw new \RuntimeException('Failed to delete '.$buildDirA.' or '.$buildDirB); - } - $this->fs->mkdir($buildDirA); - $this->fs->mkdir($buildDirB); - } - - // set build dir to the not-active one - if (realpath($webDir.'/p') === realpath($buildDirA)) { - $buildDir = realpath($buildDirB); - $oldBuildDir = realpath($buildDirA); - } else { - $buildDir = realpath($buildDirA); - $oldBuildDir = realpath($buildDirB); - } - - // copy existing stuff for smooth BC transition - if ($initialRun && !$force) { - if (!file_exists($webDir.'/p') || is_link($webDir.'/p')) { - @rmdir($buildDir); - @rmdir($oldBuildDir); - throw new \RuntimeException('Run this again with --force the first time around to make sure it dumps all packages'); - } - if ($verbose) { - echo 'Copying existing files'.PHP_EOL; - } - - foreach (array($buildDir, $oldBuildDir) as $dir) { - $this->cloneDir($webDir.'/p', $dir); - } - } - - if ($verbose) { - echo 'Web dir is '.$webDir.'/p ('.realpath($webDir.'/p').')'.PHP_EOL; - echo 'Build dir is '.$buildDir.PHP_EOL; - } - - // clean the build dir to start over if we are re-dumping everything - if ($force) { - // disable the write log since we copy everything at the end in forced mode - $this->writeLog = false; - - if ($verbose) { - echo 'Cleaning up existing files'.PHP_EOL; - } - if (!$this->clearDirectory($buildDir)) { - return false; - } - } - - $dumpTimeUpdates = []; - - $versionRepo = $this->doctrine->getRepository('PackagistWebBundle:Version'); - - try { - $modifiedIndividualFiles = array(); - - $total = count($packageIds); - $current = 0; - $step = 50; - while ($packageIds) { - $dumpTime = new \DateTime; - $packages = $this->doctrine->getRepository('PackagistWebBundle:Package')->getPackagesWithVersions(array_splice($packageIds, 0, $step)); - - if ($verbose) { - echo '['.sprintf('%'.strlen($total).'d', $current).'/'.$total.'] Processing '.$step.' packages'.PHP_EOL; - } - - $current += $step; - - // prepare packages in memory - foreach ($packages as $package) { - // skip spam packages in the dumper in case we do a forced full dump and prevent them from being dumped for a little while - if ($package->isAbandoned() && $package->getReplacementPackage() === 'spam/spam') { - $dumpTimeUpdates['2100-01-01 00:00:00'][] = $package->getId(); - continue; - } - - $affectedFiles = array(); - $name = strtolower($package->getName()); - - // clean up versions in individual files - if (file_exists($buildDir.'/'.$name.'.files')) { - $files = json_decode(file_get_contents($buildDir.'/'.$name.'.files')); - - foreach ($files as $file) { - if (substr_count($file, '/') > 1) { // handle old .files with p/*/*.json paths - $file = preg_replace('{^p/}', '', $file); - } - $this->loadIndividualFile($buildDir.'/'.$file, $file); - if (isset($this->individualFiles[$file]['packages'][$name])) { - unset($this->individualFiles[$file]['packages'][$name]); - $modifiedIndividualFiles[$file] = true; - } - } - } - - // (re)write versions in individual files - $versionIds = []; - foreach ($package->getVersions() as $version) { - $versionIds[] = $version->getId(); - } - $versionData = $versionRepo->getVersionData($versionIds); - foreach ($package->getVersions() as $version) { - foreach (array_slice($version->getNames(), 0, 150) as $versionName) { - if (!preg_match('{^[A-Za-z0-9_-][A-Za-z0-9_.-]*/[A-Za-z0-9_-][A-Za-z0-9_.-]*$}', $versionName) || strpos($versionName, '..')) { - continue; - } - - $file = $buildDir.'/'.$versionName.'.json'; - $key = $versionName.'.json'; - $this->dumpVersionToIndividualFile($version, $file, $key, $versionData); - $modifiedIndividualFiles[$key] = true; - $affectedFiles[$key] = true; - } - } - - // store affected files to clean up properly in the next update - $this->fs->mkdir(dirname($buildDir.'/'.$name)); - $this->writeFile($buildDir.'/'.$name.'.files', json_encode(array_keys($affectedFiles))); - - $dumpTimeUpdates[$dumpTime->format('Y-m-d H:i:s')][] = $package->getId(); - } - - unset($packages, $package, $version); - $this->doctrine->getManager()->clear(); - - if ($current % 250 === 0 || !$packageIds) { - if ($verbose) { - echo 'Dumping individual files'.PHP_EOL; - } - $this->dumpIndividualFiles($buildDir); - } - } - - // prepare individual files listings - if ($verbose) { - echo 'Preparing individual files listings'.PHP_EOL; - } - $safeFiles = array(); - $individualHashedListings = array(); - $finder = Finder::create()->files()->ignoreVCS(true)->name('*.json')->in($buildDir)->depth('1'); - - foreach ($finder as $file) { - // skip hashed files - if (strpos($file, '$')) { - continue; - } - - $key = basename(dirname($file)).'/'.basename($file); - if ($force && !isset($modifiedIndividualFiles[$key])) { - continue; - } - - // add hashed provider to listing - $listing = $this->getTargetListing($file); - $hash = hash_file('sha256', $file); - $key = substr($key, 0, -5); - $safeFiles[] = $key.'$'.$hash.'.json'; - $this->listings[$listing]['providers'][$key] = array('sha256' => $hash); - $individualHashedListings[$listing] = true; - } - - // prepare root file - $rootFile = $buildDir.'/packages.json'; - $this->rootFile = array('packages' => array()); - $url = $this->router->generate('track_download', array('name' => 'VND/PKG')); - $this->rootFile['notify'] = str_replace('VND/PKG', '%package%', $url); - $this->rootFile['notify-batch'] = $this->router->generate('track_download_batch'); - $this->rootFile['providers-url'] = $this->router->generate('home') . 'p/%package%$%hash%.json'; - $this->rootFile['search'] = $this->router->generate('search', array('_format' => 'json')) . '?q=%query%&type=%type%'; - - if ($verbose) { - echo 'Dumping individual listings'.PHP_EOL; - } - - // dump listings to build dir - foreach ($individualHashedListings as $listing => $dummy) { - list($listingPath, $hash) = $this->dumpListing($buildDir.'/'.$listing); - $hashedListing = basename($listingPath); - $this->rootFile['provider-includes']['p/'.str_replace($hash, '%hash%', $hashedListing)] = array('sha256' => $hash); - $safeFiles[] = $hashedListing; - } - - if ($verbose) { - echo 'Dumping root'.PHP_EOL; - } - $this->dumpRootFile($rootFile); - } catch (\Exception $e) { - // restore files as they were before we started - $this->cloneDir($oldBuildDir, $buildDir); - throw $e; - } - - try { - if ($verbose) { - echo 'Putting new files in production'.PHP_EOL; - } - - // move away old files for BC update - if ($initialRun && file_exists($webDir.'/p') && !is_link($webDir.'/p')) { - rename($webDir.'/p', $webDir.'/p-old'); - } - - $this->switchActiveWebDir($webDir, $buildDir); - } catch (\Exception $e) { - @symlink($oldBuildDir, $webDir.'/p'); - throw $e; - } - - try { - if ($initialRun || !is_link($webDir.'/packages.json') || $force) { - if ($verbose) { - echo 'Writing/linking the packages.json'.PHP_EOL; - } - if (file_exists($webDir.'/packages.json')) { - unlink($webDir.'/packages.json'); - } - if (file_exists($webDir.'/packages.json.gz')) { - unlink($webDir.'/packages.json.gz'); - } - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $sourcePath = $buildDir.'/packages.json'; - if (!copy($sourcePath, $webDir.'/packages.json')) { - throw new \RuntimeException('Could not copy the packages.json file'); - } - } else { - $sourcePath = 'p/packages.json'; - if (!symlink($sourcePath, $webDir.'/packages.json')) { - throw new \RuntimeException('Could not symlink the packages.json file'); - } - if ($this->compress && !symlink($sourcePath.'.gz', $webDir.'/packages.json.gz')) { - throw new \RuntimeException('Could not symlink the packages.json.gz file'); - } - } - } - } catch (\Exception $e) { - $this->switchActiveWebDir($webDir, $oldBuildDir); - throw $e; - } - - // clean up old dir if present on BC update - if ($initialRun) { - $this->removeDirectory($webDir.'/p-old'); - } - - // clean the old build dir if we re-dumped everything - if ($force) { - if ($verbose) { - echo 'Cleaning up old build dir'.PHP_EOL; - } - if (!$this->clearDirectory($oldBuildDir)) { - throw new \RuntimeException('Unrecoverable inconsistent state (old build dir could not be cleared), run with --force again to retry'); - } - } - - // copy state to old active dir - if ($force) { - if ($verbose) { - echo 'Copying new contents to old build dir to sync up'.PHP_EOL; - } - $this->cloneDir($buildDir, $oldBuildDir); - } else { - if ($verbose) { - echo 'Replaying write log in old build dir'.PHP_EOL; - } - $this->copyWriteLog($buildDir, $oldBuildDir); - } - - // clean up old files once an hour - if (!$force && $cleanUpOldFiles) { - if ($verbose) { - echo 'Cleaning up old files'.PHP_EOL; - } - - $this->cleanOldFiles($buildDir, $oldBuildDir, $safeFiles); - } - - if ($verbose) { - echo 'Updating package dump times'.PHP_EOL; - } - foreach ($dumpTimeUpdates as $dt => $ids) { - $retries = 5; - // retry loop in case of a lock timeout - while ($retries--) { - try { - $this->doctrine->getManager()->getConnection()->executeQuery( - 'UPDATE package SET dumpedAt=:dumped WHERE id IN (:ids)', - [ - 'ids' => $ids, - 'dumped' => $dt, - ], - ['ids' => Connection::PARAM_INT_ARRAY] - ); - } catch (\Exception $e) { - if (!$retries) { - throw $e; - } - sleep(2); - } - } - } - - // TODO when a package is deleted, it should be removed from provider files, or marked for removal at least - return true; - } - - private function switchActiveWebDir($webDir, $buildDir) - { - $newLink = $webDir.'/p-new'; - $oldLink = $webDir.'/p'; - - if (file_exists($newLink)) { - unlink($newLink); - } - if (!symlink($buildDir, $newLink)) { - echo 'Warning: Could not symlink the build dir into the web dir'; - throw new \RuntimeException('Could not symlink the build dir into the web dir'); - } - if (!rename($newLink, $oldLink)) { - echo 'Warning: Could not replace the old symlink with the new one in the web dir'; - throw new \RuntimeException('Could not replace the old symlink with the new one in the web dir'); - } - } - - private function cloneDir($source, $target) - { - $this->removeDirectory($target); - exec('cp -rpf '.escapeshellarg($source).' '.escapeshellarg($target), $output, $exit); - if (0 !== $exit) { - echo 'Warning, cloning a directory using the php fallback does not keep filemtime, invalid behavior may occur'; - $this->fs->mirror($source, $target, null, array('override' => true)); - } - } - - private function cleanOldFiles($buildDir, $oldBuildDir, $safeFiles) - { - $finder = Finder::create()->directories()->ignoreVCS(true)->in($buildDir); - foreach ($finder as $vendorDir) { - $vendorFiles = Finder::create()->files()->ignoreVCS(true) - ->name('/\$[a-f0-9]+\.json$/') - ->date('until 10minutes ago') - ->in((string) $vendorDir); - - foreach ($vendorFiles as $file) { - $key = strtr(str_replace($buildDir.DIRECTORY_SEPARATOR, '', $file), '\\', '/'); - if (!in_array($key, $safeFiles, true)) { - unlink((string) $file); - if (file_exists($altDirFile = str_replace($buildDir, $oldBuildDir, (string) $file))) { - unlink($altDirFile); - } - } - } - } - - // clean up old provider listings - $finder = Finder::create()->depth(0)->files()->name('provider-*.json')->ignoreVCS(true)->in($buildDir)->date('until 10minutes ago'); - foreach ($finder as $provider) { - $key = strtr(str_replace($buildDir.DIRECTORY_SEPARATOR, '', $provider), '\\', '/'); - if (!in_array($key, $safeFiles, true)) { - $path = (string) $provider; - unlink($path); - if (file_exists($path.'.gz')) { - unlink($path.'.gz'); - } - if (file_exists($altDirFile = str_replace($buildDir, $oldBuildDir, $path))) { - unlink($altDirFile); - if (file_exists($altDirFile.'.gz')) { - unlink($altDirFile.'.gz'); - } - } - } - } - - // clean up old root listings - $finder = Finder::create()->depth(0)->files()->name('packages.json-*')->ignoreVCS(true)->in($buildDir)->date('until 10minutes ago'); - foreach ($finder as $rootFile) { - $path = (string) $rootFile; - unlink($path); - if (file_exists($path.'.gz')) { - unlink($path.'.gz'); - } - if (file_exists($altDirFile = str_replace($buildDir, $oldBuildDir, $path))) { - unlink($altDirFile); - if (file_exists($altDirFile.'.gz')) { - unlink($altDirFile.'.gz'); - } - } - } - } - - private function dumpRootFile($file) - { - // sort all versions and packages to make sha1 consistent - ksort($this->rootFile['packages']); - ksort($this->rootFile['provider-includes']); - foreach ($this->rootFile['packages'] as $package => $versions) { - ksort($this->rootFile['packages'][$package]); - } - - if (file_exists($file)) { - $timedFile = $file.'-'.time(); - rename($file, $timedFile); - if (file_exists($file.'.gz')) { - rename($file.'.gz', $timedFile.'.gz'); - } - } - - $json = json_encode($this->rootFile); - $time = time(); - - $this->writeFile($file, $json, $time); - if ($this->compress) { - $this->writeFile($file . '.gz', gzencode($json, $this->compress), $time); - } - } - - private function dumpListing($path) - { - $key = basename($path); - - // sort files to make hash consistent - ksort($this->listings[$key]['providers']); - - $json = json_encode($this->listings[$key]); - $hash = hash('sha256', $json); - $path = substr($path, 0, -5) . '$' . $hash . '.json'; - $time = time(); - - if (!file_exists($path)) { - $this->writeFile($path, $json, $time); - if ($this->compress) { - $this->writeFile($path . '.gz', gzencode($json, $this->compress), $time); - } - } - - return array($path, $hash); - } - - private function loadIndividualFile($path, $key) - { - if (isset($this->individualFiles[$key])) { - return; - } - - if (file_exists($path)) { - $this->individualFiles[$key] = json_decode(file_get_contents($path), true); - $this->individualFilesMtime[$key] = filemtime($path); - } else { - $this->individualFiles[$key] = array(); - $this->individualFilesMtime[$key] = 0; - } - } - - private function dumpIndividualFiles($buildDir) - { - // dump individual files to build dir - foreach ($this->individualFiles as $file => $dummy) { - $this->dumpIndividualFile($buildDir.'/'.$file, $file); - } - - $this->individualFiles = array(); - $this->individualFilesMtime = array(); - } - - private function dumpIndividualFile($path, $key) - { - // sort all versions and packages to make sha1 consistent - ksort($this->individualFiles[$key]['packages']); - foreach ($this->individualFiles[$key]['packages'] as $package => $versions) { - ksort($this->individualFiles[$key]['packages'][$package]); - } - - $this->fs->mkdir(dirname($path)); - - $json = json_encode($this->individualFiles[$key]); - $this->writeFile($path, $json, $this->individualFilesMtime[$key]); - - // write the hashed provider file - $hashedFile = substr($path, 0, -5) . '$' . hash('sha256', $json) . '.json'; - $this->writeFile($hashedFile, $json); - } - - private function dumpVersionToIndividualFile(Version $version, $file, $key, $versionData) - { - $this->loadIndividualFile($file, $key); - $data = $version->toArray($versionData); - $data['uid'] = $version->getId(); - $this->individualFiles[$key]['packages'][strtolower($version->getName())][$version->getVersion()] = $data; - $timestamp = $version->getReleasedAt() ? $version->getReleasedAt()->getTimestamp() : time(); - if (!isset($this->individualFilesMtime[$key]) || $this->individualFilesMtime[$key] < $timestamp) { - $this->individualFilesMtime[$key] = $timestamp; - } - } - - private function clearDirectory($path) - { - if (!$this->removeDirectory($path)) { - echo 'Could not remove the build dir entirely, aborting'; - - return false; - } - $this->fs->mkdir($path); - return true; - } - - private function removeDirectory($path) - { - $retries = 5; - do { - if (!$this->cfs->removeDirectory($path)) { - usleep(200); - } - clearstatcache(); - } while (is_dir($path) && $retries--); - - return !is_dir($path); - } - - private function getTargetListingBlocks($now) - { - $blocks = array(); - - // monday last week - $blocks['latest'] = strtotime('monday last week', $now); - - $month = date('n', $now); - $month = ceil($month / 3) * 3 - 2; // 1 for months 1-3, 10 for months 10-12 - $block = new \DateTime(date('Y', $now).'-'.$month.'-01'); // 1st day of current trimester - - // split last 12 months in 4 trimesters - for ($i=0; $i < 4; $i++) { - $blocks[$block->format('Y-m')] = $block->getTimestamp(); - $block->sub(new \DateInterval('P3M')); - } - - $year = (int) $block->format('Y'); - - while ($year >= 2013) { - $blocks[''.$year] = strtotime($year.'-01-01'); - $year--; - } - - return $blocks; - } - - private function getTargetListing($file) - { - static $blocks; - - if (!$blocks) { - $blocks = $this->getTargetListingBlocks(time()); - } - - $mtime = filemtime($file); - - foreach ($blocks as $label => $block) { - if ($mtime >= $block) { - return "provider-${label}.json"; - } - } - - return "provider-archived.json"; - } - - private function writeFile($path, $contents, $mtime = null) - { - file_put_contents($path, $contents); - if ($mtime !== null) { - touch($path, $mtime); - } - - if (is_array($this->writeLog)) { - $this->writeLog[$path] = array($contents, $mtime); - } - } - - private function copyWriteLog($from, $to) - { - foreach ($this->writeLog as $path => $op) { - $path = str_replace($from, $to, $path); - - $this->fs->mkdir(dirname($path)); - file_put_contents($path, $op[0]); - if ($op[1] !== null) { - touch($path, $op[1]); - } - } - } -} diff --git a/src/Packagist/WebBundle/Package/Updater.php b/src/Packagist/WebBundle/Package/Updater.php index e40b297b..b571094b 100644 --- a/src/Packagist/WebBundle/Package/Updater.php +++ b/src/Packagist/WebBundle/Package/Updater.php @@ -134,13 +134,9 @@ public function update(IOInterface $io, Config $config, Package $package, Reposi $apc = extension_loaded('apcu'); $rootIdentifier = null; - if ($this->archiveManager === null) { - $downloadManager = $this->factory->createDownloadManager($io, $config); - $archiveManager = $this->factory->createArchiveManager($config, $downloadManager); - $archiveManager->setOverwriteFiles(false); - } else { - $archiveManager = $this->archiveManager; - } + $downloadManager = $this->factory->createDownloadManager($io, $config); + $archiveManager = $this->factory->createArchiveManager($config, $downloadManager); + $archiveManager->setOverwriteFiles(false); if ($repository instanceof VcsRepository) { $cfg = $repository->getRepoConfig(); @@ -366,7 +362,7 @@ private function updateInformation( } $version->setHomepage($data->getHomepage()); - $version->setLicense($data->getLicense() ?: array()); + $version->setLicense($data->getLicense() ?: []); $version->setPackage($package); $version->setUpdatedAt(new \DateTime); @@ -568,17 +564,24 @@ private function updateArchive(ArchiveManager $archiveManager, PackageInterface return null; } - $path = $archiveManager->archive( - $data, - $this->distConfig->getArchiveFormat(), - $this->distConfig->generateTargetDir($data->getName()), - $data->getSourceReference() - ); + if (false === $this->distConfig->isLazy()) { + $fileName= $this->distConfig->getFileName( + $data->getSourceReference(), + $data->getVersion() + ); + + $path = $archiveManager->archive( + $data, + $this->distConfig->getArchiveFormat(), + $this->distConfig->generateTargetDir($data->getName()), + $fileName + ); + $dist['shasum'] = $this->distConfig->isIncludeArchiveChecksum() ? \hash_file('sha1', $path) : null; + } $dist['type'] = $this->distConfig->getArchiveFormat(); $dist['url'] = $this->distConfig->generateRoute($data->getName(), $data->getSourceReference()); $dist['reference'] = $data->getSourceReference(); - $dist['shasum'] = $this->distConfig->isIncludeArchiveChecksum() ? \hash_file('sha1', $path) : null; return $dist; } @@ -592,7 +595,11 @@ private function updateDist(array $dist, Version $version) $filesystem = new Filesystem(); $oldDist = $version->getDist(); if (isset($oldDist['reference']) && $dist['reference'] !== $oldDist['reference']) { - $targetDir = $this->distConfig->generateDistFileName($version->getName(), $oldDist['reference']); + $targetDir = $this->distConfig->generateDistFileName( + $version->getName(), + $oldDist['reference'], + $version->getVersion() + ); $filesystem->remove($targetDir); } diff --git a/src/Packagist/WebBundle/PackagistWebBundle.php b/src/Packagist/WebBundle/PackagistWebBundle.php index e90b5fad..bd53a79e 100644 --- a/src/Packagist/WebBundle/PackagistWebBundle.php +++ b/src/Packagist/WebBundle/PackagistWebBundle.php @@ -22,6 +22,9 @@ */ class PackagistWebBundle extends Bundle { + /** + * {@inheritdoc} + */ public function build(ContainerBuilder $container) { /** @var SecurityExtension $extension */ diff --git a/src/Packagist/WebBundle/Resources/config/security.yml b/src/Packagist/WebBundle/Resources/config/security.yml index 9046f4a7..582eb80c 100644 --- a/src/Packagist/WebBundle/Resources/config/security.yml +++ b/src/Packagist/WebBundle/Resources/config/security.yml @@ -19,9 +19,10 @@ services: packagist.security.authentication.provider: class: Packagist\WebBundle\Security\Api\ApiTokenProvider + public: false arguments: - '@packagist.user_provider' - public: false + - ~ packagist.security.authentication.listener: class: Packagist\WebBundle\Security\Api\ApiBasicAuthenticationListener diff --git a/src/Packagist/WebBundle/Resources/config/services.yml b/src/Packagist/WebBundle/Resources/config/services.yml index 675ef4b8..58fd0a4b 100644 --- a/src/Packagist/WebBundle/Resources/config/services.yml +++ b/src/Packagist/WebBundle/Resources/config/services.yml @@ -4,7 +4,7 @@ parameters: services: packagist.twig.extension: class: Packagist\WebBundle\Twig\PackagistExtension - arguments: [ '@packagist.provider_manager' ] + arguments: [ '@service_container' ] tags: - { name: twig.extension } @@ -32,10 +32,6 @@ services: tags: - { name: kernel.event_subscriber } - packagist.package_symlink_dumper: - class: Packagist\WebBundle\Package\SymlinkDumper - arguments: [ '@doctrine', '@filesystem', '@router', '%kernel.root_dir%/../web/', '%packagist_metadata_dir%', '%packagist_dumper_compress%' ] - packagist.user_repository: class: Packagist\WebBundle\Entity\UserRepository factory: ['@doctrine', getRepository] @@ -72,11 +68,7 @@ services: - '@fos_user.user_manager' - '@fos_user.util.token_generator' - '@event_dispatcher' - - '@service_container' - - packagist.oauth.registration_form_handler: - class: Packagist\WebBundle\Form\Handler\OAuthRegistrationFormHandler - arguments: ['@fos_user.user_manager', '@fos_user.util.token_generator'] + - '@request_stack' packagist.oauth.registration_form_type: class: Packagist\WebBundle\Form\Type\OAuthRegistrationFormType @@ -96,6 +88,7 @@ services: packagist.provider_manager: class: Packagist\WebBundle\Model\ProviderManager + public: true arguments: - '@snc_redis.default_client' - '@packagist.package_repository' @@ -123,7 +116,7 @@ services: class: Packagist\WebBundle\Form\Type\ProfileFormType arguments: ['%fos_user.model.user.class%'] tags: - - { name: form.type, alias: packagist_user_profile } + - { name: form.type } packagist.permission_collection.form.type: class: Packagist\WebBundle\Form\Type\GroupAclPermissionCollectionType @@ -153,10 +146,6 @@ services: tags: - { name: knp_menu.menu, alias: admin_menu } - packagist.algolia.client: - class: AlgoliaSearch\Client - arguments: ['%algolia.app_id%', '%algolia.admin_key%'] - packagist.queue_worker: class: Packagist\WebBundle\Service\QueueWorker arguments: @@ -185,5 +174,3 @@ services: packagist.console_stack_trace_line_formatter: class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter arguments: [] - calls: - - [includeStacktraces, [true]] diff --git a/src/Packagist/WebBundle/Resources/public/css/main.css b/src/Packagist/WebBundle/Resources/public/css/main.css index 0ce3ea6b..7868ff6a 100644 --- a/src/Packagist/WebBundle/Resources/public/css/main.css +++ b/src/Packagist/WebBundle/Resources/public/css/main.css @@ -55,7 +55,7 @@ body { position: absolute; width: 100px; left: -98px; - top: -43px; + top: -33px; } @media (min-width: 1200px) { .logo { @@ -305,6 +305,7 @@ strong { .nav-user .signin-box .signin-box-buttons { float: left; width: 100%; + padding: 10px; } .nav-user .signin-box .signin-box-register { @@ -594,7 +595,7 @@ input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:fo margin: 0 -4px 6px 0; border-right: 0; background: none; - color: #c6cacd; + color: #7e7d7b; font-size: 16px; } @@ -1663,4 +1664,23 @@ svg.chart { speak: none; } +.package-panel-info { + border-color: #f28d1a; +} +.package-panel-danger { + border-color: #cd3729; +} +.package-panel-info >.panel-heading { + background-image: linear-gradient(#f28d1a, #f59d3e); +} +.package-panel-danger >.panel-heading { + background-image: linear-gradient(#cd3729, #cd554c); +} +.panel-heading .anchor { + color: #FFF; +} +.package-permission input { + width: 100% !important; +} + .icon-mail:before { content: '\2709'; } /* '✉' */ diff --git a/src/Packagist/WebBundle/Resources/public/img/logo-small.png b/src/Packagist/WebBundle/Resources/public/img/logo-small.png index 76c0e62a20d7ca8f50ce24b1e5acb8b4af2b932f..4d967ebe0e86fed9faae216c47a15d44714b9a82 100644 GIT binary patch literal 15543 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 diff --git a/src/Packagist/WebBundle/Resources/public/img/logo.png b/src/Packagist/WebBundle/Resources/public/img/logo.png index 289548d51a7fd44e405c14a89cb0303dafeebd2a..562f032d469230f4c3b79801660e9a5a40d1e8e3 100644 GIT binary patch literal 126405 zcmXtg2Q*yW`}OEUgdtiGWlTgbQ6sw1hG@}y3xX)oYjmUcgy=*>kKjf061@Zw5xqt4 zy?@8=TmQ9U5zEZI&OK*8``LRxBGgpm?-NiHKp>F&iV8>#2m}KTJ}jZQ;5#8Lg5BT~ zzLSEU3k1T&boYVbSs>vKfiOT6ky4tT8CymkuA1W~v#Zn3n?4*3Ah6?SpQF~A6df@M z7CRz!CEp2d1>pQV)kMmM%FByjVxmamiAEW#L*hl!l(Xwkv#u|hTr4EjBzf2RYkwPk zO&rJ+v)(x$s_mZ)XMk(wV3L24^a^@kivd34u(f`;`=a%@m5M2vHx`EZD&;vNHa;U1 zq5utCyY0Up%^Qgh(ddIE@N}_2Al=RyUQ;I?7)4HlY)(&tc;)(GL%TPe7SZp!JLQp> zYSOW2Xh=M}|C6a>oxevONE{Na`B*HAXbse4fzpRX?Q+9s^Jn`@HJWTG@u{h)
i ztXy0>ZB5c~&O;QjwxeTmYOlADnF-!%h8>s?%2-f$ZHC%Wa{ z@E}GmpFxon1Co;*#DYSS;YhO<(8^1}kkC+RDx&aSBaa!kg@`9vo^RHE=DP4x$1rp| zIE33F6iK_CGx!~*>xiv~GR}3)&CPYmaBvvOUM&)0WByv&k56Ed_upR#rx*XE$)@+q zuO!t~CpQSq=F}}oCY!bDwcpR(LVL58ALsw*!2>2}P!8BsA(A{~m`NiLt0a=BsHS)w zH7HvFDIu;H7G&@8`q%1Vg7@*pqjv|rPfXS)D&{n@Rv%hK%OKCHpb@-sECrqm?V+98 zW%`ej5WPsKlzOrP5*@&R&e33%su<&i#B-T6ms0VVwvKYQT)hR`0~?|{sjGp*HhM~4 zCli21CL)L+3{Rds(Ykpk89{n*j`g$b<@4!!XB-E^dWc|!9`x4#^!^vEL#`ffmSs^o z?!s|f9xg5w5x)!9WA%JF&W&G1W2$x&<=aSTf^cjSLUD09`Zs-b3MOQ0rlB^Xf92`E zC^vqPLNx9pu8R$e48e19SHxrU+!8b@@sonGG8qN8@$~Mbb#|s4)GV5JC+_c_stkBy zInyMM@!Ag?p^*5rwDp|i_n)`$85ttrN83|0i=!G5a{0`?iV>E}U(76L4!oADhzrfj zK8}C=`W5XhYOGQ*VWF%X?YcML))kC+!r0*ZxE#bI;=9VhCx0 zEH4b&+9F3BP9)|XKawAw#JTytJvBk*>z^eIbu#k({r$zlY=04lo2&ESR~lD*T|3!9 z1n^?Xdg=0(eNWN9yDhiP+XjwJ$BP@|CE;Kv)|r1J#l$;#1d+rIVvt6VVq}*

RSv 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 LdQa6Z_t^gc0>PFJ literal 65810 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]/)) { - location.replace(location.pathname); -} - -var searchThrottle = null; -var search = instantsearch({ - appId: algoliaConfig.app_id, - apiKey: algoliaConfig.search_key, - indexName: algoliaConfig.index_name, - routing: { - stateMapping: { - stateToRoute: function (uiState) { - return { - query: uiState.query, - type: uiState.menu && uiState.menu.type, - tags: uiState.refinementList && uiState.refinementList.tags && uiState.refinementList.tags.join('~'), - page: uiState.page, - }; - }, - routeToState: function (routeState) { - if (routeState.q) { - routeState.query = routeState.q; - } - if (routeState.query === undefined || routeState.query === '') { - return {}; - } - - return { - query: routeState.query, - menu: { - type: routeState.type - }, - refinementList: { - tags: routeState.tags && routeState.tags.split('~'), - }, - page: routeState.page - }; - }, - }, - }, - searchFunction: function(helper) { - var searchResults = $('#search-container'); - - if (helper.state.query === '' - && helper.state.hierarchicalFacetsRefinements.type === undefined - && (helper.state.disjunctiveFacetsRefinements.tags === undefined || helper.state.disjunctiveFacetsRefinements.tags.length === 0) - ) { - searchResults.addClass('hidden'); - } else { - searchResults.removeClass('hidden'); - } - - if (searchThrottle) { - clearTimeout(searchThrottle); - } - - searchThrottle = setTimeout(function () { - helper.search(); - }, 300); - }, - searchParameters: searchParameters -}); - -var autofocus = false; -if (location.pathname == "/" || location.pathname == "/app_dev.php/") { - autofocus = true; -} -search.addWidget( - instantsearch.widgets.searchBox({ - container: '#search_query_query', - magnifier: false, - reset: false, - wrapInput: false, - autofocus: autofocus - }) -); - -search.addWidget( - instantsearch.widgets.hits({ - container: '.search-list', - transformData: function (hit) { - hit.url = '/packages/' + hit.name; - if (hit.type === 'virtual-package') { - hit.virtual = true; - hit.url = '/providers/' + hit.name; - } - - if (hit._highlightResult && hit._highlightResult.description.value && hit._highlightResult.description.value.length > 200) { - hit._highlightResult.description.value = hit._highlightResult.description.value.substring(0, 200).replace(/<[a-z ]+$/, ''); - } - - return hit; - }, - templates: { - empty: 'No packages found.', - item: ` -

-
-
-

{{ language }}

-

- {{{ _highlightResult.name.value }}} - {{#virtual}} - (Virtual Package) - {{/virtual}} -

- -

{{{ _highlightResult.description.value }}}

- - {{#abandoned}} -

- Abandoned! - {{#replacementPackage}} - See {{ replacementPackage }} - {{/replacementPackage}} -

- {{/abandoned}} -
- -
- {{#meta}} - - {{/meta}} -
-
-
-` - }, - cssClasses: { - root: 'packages', - item: 'row' - } - }) -); - -search.addWidget( - instantsearch.widgets.pagination({ - container: '.pagination', - maxPages: 200, - scrollTo: false, - showFirstLast: false, - }) -); - -search.addWidget( - instantsearch.widgets.currentRefinedValues({ - container: '.search-facets-active-filters', - clearAll: 'before', - clearsQuery: false, - cssClasses: { - clearAll: 'pull-right' - }, - templates: { - header: 'Active filters', - item: function (filter) { - if ('tags' == filter.attributeName) { - return 'tag: ' + filter.name - } else { - return filter.attributeName + ': ' + filter.name - } - } - }, - onlyListedAttributes: true, - }) -); - -search.addWidget( - instantsearch.widgets.menu({ - container: '.search-facets-type', - attributeName: 'type', - limit: 15, - showMore: true, - templates: { - header: 'Package type' - } - }) -); - -search.addWidget( - instantsearch.widgets.refinementList({ - container: '.search-facets-tags', - attributeName: 'tags', - limit: 15, - showMore: true, - templates: { - header: 'Tags' - }, - searchForFacetValues:true - }) -); - -search.start(); diff --git a/src/Packagist/WebBundle/Resources/translations/messages.en.yml b/src/Packagist/WebBundle/Resources/translations/messages.en.yml index 7acde9ef..b34ce6b6 100644 --- a/src/Packagist/WebBundle/Resources/translations/messages.en.yml +++ b/src/Packagist/WebBundle/Resources/translations/messages.en.yml @@ -50,7 +50,7 @@ explore: search: claim_html: | - Packagist is the main Composer repository. It aggregates public PHP packages installable with Composer. + Packagist is the main Composer repository. It aggregates PHP packages installable with Composer. packages: mine: My packages @@ -152,7 +152,7 @@ user: 'Search packages...': 'Search packages...' brandname: Packagist -navclaim: The PHP Package Repository +navclaim: The Private Composer Repository Sort: 'Sort' Order: 'Order' Username: 'Username' diff --git a/src/Packagist/WebBundle/Resources/views/About/about.html.twig b/src/Packagist/WebBundle/Resources/views/About/about.html.twig index 29fad7a9..e5101f6c 100644 --- a/src/Packagist/WebBundle/Resources/views/About/about.html.twig +++ b/src/Packagist/WebBundle/Resources/views/About/about.html.twig @@ -99,6 +99,7 @@ v2.0.4-p1

How to update packages?

+ {% set url = app.request.getScheme() ~ '://' ~ app.request.getHttpHost() %}

GitHub Service Hook

@@ -116,15 +117,15 @@ v2.0.4-p1

Bitbucket Webhooks

-

To enable the Bitbucket web hook, go to your BitBucket repository, open the settings and select "Webhooks" in the menu. Add a new hook. You have to enter the Packagist endpoint, containing both your username and API token. Enter https://packagist.org/api/bitbucket?username={{ app.user.username|default('USERNAME') }}&apiToken=API_TOKEN as URL. Save your changes and you're done.

+

To enable the Bitbucket web hook, go to your BitBucket repository, open the settings and select "Webhooks" in the menu. Add a new hook. You have to enter the Packagist endpoint, containing both your username and API token. Enter {{ url }}/api/bitbucket?token={{ app.user.username|default('USERNAME') ~ ':' ~ app.user.apiToken|default('token') }} as URL. Save your changes and you're done.

Manual hook setup

-

If you do not use Bitbucket or GitHub there is a generic endpoint you can call manually from a git post-receive hook or similar. You have to do a POST request to https://packagist.org/api/update-package?username={{ app.user.username|default('USERNAME') }}&apiToken=API_TOKEN with a request body looking like this: {"repository":{"url":"PACKAGIST_PACKAGE_URL"}}

+

If you do not use Bitbucket or GitHub there is a generic endpoint you can call manually from a git post-receive hook or similar. You have to do a POST request to {{ url }}/api/update-package?token={{ app.user.username|default('USERNAME') ~ ':' ~ app.user.apiToken|default('token') }} with a request body looking like this: {"repository":{"url":"PACKAGIST_PACKAGE_URL"}}

You can do this using curl for example:

-
curl -XPOST -H'content-type:application/json' 'https://packagist.org/api/update-package?username={{ app.user.username|default('USERNAME') }}&apiToken=API_TOKEN' -d'{"repository":{"url":"PACKAGIST_PACKAGE_URL"}}'
+
curl -XPOST -H'content-type:application/json' '{{ url }}/api/update-package?token={{ app.user.username|default('USERNAME') ~ ':' ~ app.user.apiToken|default('token') }}' -d'{"repository":{"url":"PACKAGIST_PACKAGE_URL"}}'
diff --git a/src/Packagist/WebBundle/Resources/views/Group/index.html.twig b/src/Packagist/WebBundle/Resources/views/Group/index.html.twig index b4ce8beb..053f716f 100644 --- a/src/Packagist/WebBundle/Resources/views/Group/index.html.twig +++ b/src/Packagist/WebBundle/Resources/views/Group/index.html.twig @@ -15,16 +15,18 @@

{{ group.name }}

-
- -
+
+ +
diff --git a/src/Packagist/WebBundle/Resources/views/Package/package.html.twig b/src/Packagist/WebBundle/Resources/views/Package/package.html.twig new file mode 100644 index 00000000..a8a30824 --- /dev/null +++ b/src/Packagist/WebBundle/Resources/views/Package/package.html.twig @@ -0,0 +1,108 @@ +
+
+

+ + {{ package.name }} + +

+ + {% if package.abandoned %} +

+ Abandoned! + Package is abandoned, you should avoid using it. + {% if package.replacementPackage %} + Use {{ package.replacementPackage }} instead. + {% else %} + No replacement was suggested. + {% endif %} +

+ {% endif %} + +
+ +
+ {% if package.description %} +

{{ package.description }}

+ {% endif %} + + {% if package.highest and package.highest.tags|length %} +
+
Keywords
+
{{ package.highest.tags|join(', ') }}
+
+ {% endif %} + + {% if package.highest and package.highest.homepage %} + + {% endif %} + + {% if package.highest and package.highest.license %} +
+
License
+
{{ package.highest.license|join(', ') }}
+
+ {% endif %} + + {% if package.highest and package.highest.authors|length %} +
+
Authors
+
+ {% for author in package.highest.authors %} + {%- if author.homepage -%} + {{ author.name }} + {%- else -%} + {{ author.name }} + {%- endif -%} + {%- if not loop.last -%}, {% endif -%} + {% endfor %} +
+
+ {% endif %} + + {% if package.highest and package.highest.support %} +
+
Support
+
+
    + {% for support_type, support_url in package.highest.support %} +
  • {{ support_type|capitalize }}: {{ support_url }}
  • + {% endfor %} +
+
+
+ {% endif %} + +
+
Releases
+
+ {% for version in package.versions %} + {%- if version.dist -%} + {% set url = '?token=' ~ app.user.username ~ ':' ~ app.user.apiToken %} + + {{ version.version }} + + {%- else -%} + {{ version.version }} + {%- endif -%} + {%- if not loop.last -%}, {% endif -%} + {% endfor %} +
+
+ + {% if dependencies is defined and dependencies|length %} +
+
Required by
+
+ +
+
+ {% endif %} +
+
diff --git a/src/Packagist/WebBundle/Resources/views/Package/viewPackage.html.twig b/src/Packagist/WebBundle/Resources/views/Package/viewPackage.html.twig index ed9ecf5b..b9e73a72 100644 --- a/src/Packagist/WebBundle/Resources/views/Package/viewPackage.html.twig +++ b/src/Packagist/WebBundle/Resources/views/Package/viewPackage.html.twig @@ -37,6 +37,7 @@ {% endif %} {{ package.vendor }}/{{ package.packageName }} +

Last updated: {{ package.crawledAt ? package.crawledAt|date('Y-m-d H:i:s') ~ ' UTC': 'N/A' }}

@@ -71,11 +72,6 @@ %}
This package is in a broken state and will not update anymore. Some branches contain invalid data and until you fix them the entire package is frozen. Click "Update" below to see details.
{% endif %} - - {% if expandedVersion and not expandedVersion.license %} -
There is no license information available for the latest version ({{ expandedVersion.version }}) of this package.
- {% endif %} -

{{ package.description|truncate(300) }}

{% if hasActions %} @@ -112,7 +108,8 @@
-
+ {% if is_granted('ROLE_ADMIN') %} +

{% for maintainer in package.maintainers -%} @@ -214,6 +211,7 @@ {% endif %}

+ {% endif %}
diff --git a/src/Packagist/WebBundle/Resources/views/User/profile.html.twig b/src/Packagist/WebBundle/Resources/views/User/profile.html.twig index 9428d71e..9b17586e 100644 --- a/src/Packagist/WebBundle/Resources/views/User/profile.html.twig +++ b/src/Packagist/WebBundle/Resources/views/User/profile.html.twig @@ -16,12 +16,23 @@
-
-

Your customer needs to authenticate to access their Composer repository:
- The simplest way to provide your credentials is providing your set of credentials - inline with the repository specification such as: -

-
+
+    {% if deleteForm is defined and is_granted('ROLE_ADMIN') and user.admin == false %}
+        
+
+ {{ form_widget(deleteForm._token) }} + +
+
+ {% endif %} + + {% if user.admin == false or isActualUser %} +
+

Your customer needs to authenticate to access their Composer repository:
+ The simplest way to provide your credentials is providing your set of credentials + inline with the repository specification such as: +

+
 {
     "repositories": [
         {
@@ -30,16 +41,17 @@
         }
     ]
 }
-        
-

- When you don't want to hard code your credentials into your composer.json. - There is a second way to provide these details and it is via interaction. - If you don't provide the authentication credentials composer will prompt you upon connection - to enter the username and password. -

-
+            
+

+ When you don't want to hard code your credentials into your composer.json. + There is a second way to provide these details and it is via interaction. + If you don't provide the authentication credentials composer will prompt you upon connection + to enter the username and password. +

+
 composer config --global --auth http-basic.{{ app.request.getHttpHost() }} {{ user.username }} {{ user.apiToken }}
-        
-
+
+
+ {% endif %}
{% endblock %} diff --git a/src/Packagist/WebBundle/Resources/views/Web/index.html.twig b/src/Packagist/WebBundle/Resources/views/Web/index.html.twig index 203d2c4f..83edb5c6 100644 --- a/src/Packagist/WebBundle/Resources/views/Web/index.html.twig +++ b/src/Packagist/WebBundle/Resources/views/Web/index.html.twig @@ -2,64 +2,14 @@ {% block content %}
-
-

Getting Started

-
-

Define Your Dependencies

-

Put a file named composer.json at the root of your project, containing your project dependencies:

-
{
-    "require": {
-        "vendor/package": "1.3.2",
-        "vendor/package2": "1.*",
-        "vendor/package3": "^2.0.3"
-    }
-}
- -

For more information about packages versions usage, see the composer documentation.

- -

Install Composer In Your Project

-

Run this in your command line:

-
curl -sS https://getcomposer.org/installer | php
-

Or download composer.phar into your project root.

-

See the Composer documentation for complete installation instructions on various platforms.

- -

Install Dependencies

-

Execute this in your project root.

-
php composer.phar install
- -

Autoload Dependencies

-

If your packages specify autoloading information, you can autoload all the dependencies by adding this to your code:

-
require 'vendor/autoload.php';
-

Browse the packages we have to find more great libraries you can use in your project.

-
-
- -
-

Publishing Packages

-
-

Define Your Package

-

Put a file named composer.json at the root of your package's repository, containing this information:

-
{
-    "name": "your-vendor-name/package-name",
-    "description": "A short description of what your package does",
-    "require": {
-        "php": "^5.3.3 || ^7.0",
-        "another-vendor/package": "1.*"
-    }
-}
-

This is the strictly minimal information you have to give.

-

For more details about package naming and the fields you can use to document your package better, see the about page.

- -

Commit The File

-

Add the composer.json to your git or other VCS repository and commit it.

- -

Publish It

-

Login on this site, then hit the submit button in the menu.

-

Once you entered your public repository URL in there, your package will be automatically crawled periodically. You just have to make sure you keep the composer.json file up to date.

- -

Sharing Private Code

-

Use Private Packagist if you want to share private code as a Composer package with colleagues or customers without publishing it for everyone on Packagist.org. Private Packagist allows you to manage your own private Composer repository with per-user authentication, team management and integration in version control systems.

-
-
+ {% for packageInfo in packages %} + {% set package = packageInfo.package %} + {% set dependencies = packageInfo.dependencies %} + {% include 'PackagistWebBundle:Package:package.html.twig' %} + {% endfor %} + + {% if packages.haveToPaginate() %} + {{ pagerfanta(packages, 'twitter_bootstrap', {'proximity': 2}) }} + {% endif %}
{% endblock %} diff --git a/src/Packagist/WebBundle/Resources/views/Web/search.html.twig b/src/Packagist/WebBundle/Resources/views/Web/search.html.twig index b0252c82..f74dc47f 100644 --- a/src/Packagist/WebBundle/Resources/views/Web/search.html.twig +++ b/src/Packagist/WebBundle/Resources/views/Web/search.html.twig @@ -1,2 +1,19 @@ -{% embed "PackagistWebBundle:Web:list.html.twig" %} -{% endembed %} +{% extends noLayout|default(false) ? "::base_nolayout.html.twig" : "PackagistWebBundle::layout.html.twig" %} + +{% block content %} + {% block content_title %}

{{ 'listing.title'|trans }}

{% endblock %} +
+ {% if packages|length %} + {% for package in packages %} + {% include 'PackagistWebBundle:Package:package.html.twig' %} + {% endfor %} + {% if packages.haveToPaginate() %} + {{ pagerfanta(packages, 'twitter_bootstrap', {'proximity': 2}) }} + {% endif %} + {% else %} +
+

{{ 'listing.nopackages'|trans }}

+
+ {% endif %} +
+{% endblock %} diff --git a/src/Packagist/WebBundle/Resources/views/forms.html.twig b/src/Packagist/WebBundle/Resources/views/forms.html.twig index 37c4f07f..9f6c0070 100644 --- a/src/Packagist/WebBundle/Resources/views/forms.html.twig +++ b/src/Packagist/WebBundle/Resources/views/forms.html.twig @@ -52,11 +52,11 @@ {%- block package_permission_widget -%}
-
{% if value is not empty %}{{ value.name }}{% endif %}
- {{ form_widget(form.version) }} +
{% if value is not empty %}{{ value.name }}{% endif %}
{{ form_widget(form.selected) }}
+
{{ form_widget(form.version) }}
{{ form_widget(form.name) }}
{{ form_errors(form.version) }} diff --git a/src/Packagist/WebBundle/Resources/views/layout.html.twig b/src/Packagist/WebBundle/Resources/views/layout.html.twig index e5aa3bde..9831fbeb 100644 --- a/src/Packagist/WebBundle/Resources/views/layout.html.twig +++ b/src/Packagist/WebBundle/Resources/views/layout.html.twig @@ -22,9 +22,6 @@ {% endblock %} - - - {% block head_additions %}{% endblock %} @@ -45,13 +42,13 @@
-

Packagist maintenance and hosting is supported by Private Packagist

+

Packagist maintenance and hosting is supported by Cuantic

diff --git a/src/Packagist/WebBundle/Security/Acl/PackagesAclVoter.php b/src/Packagist/WebBundle/Security/Acl/PackagesAclVoter.php index 8e3198be..98983d6d 100644 --- a/src/Packagist/WebBundle/Security/Acl/PackagesAclVoter.php +++ b/src/Packagist/WebBundle/Security/Acl/PackagesAclVoter.php @@ -20,22 +20,6 @@ public function __construct(PackagesAclChecker $checker) $this->checker = $checker; } - /** - * {@inheritdoc} - */ - public function supportsAttribute($attribute) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - return true; - } - /** * {@inheritdoc} */ @@ -56,6 +40,6 @@ public function vote(TokenInterface $token, $object, array $attributes) return self::ACCESS_DENIED; } - return self::ACCESS_ABSTAIN; + return self::ACCESS_GRANTED; } } diff --git a/src/Packagist/WebBundle/Security/Api/ApiTokenProvider.php b/src/Packagist/WebBundle/Security/Api/ApiTokenProvider.php index 7e077acb..79b8db88 100644 --- a/src/Packagist/WebBundle/Security/Api/ApiTokenProvider.php +++ b/src/Packagist/WebBundle/Security/Api/ApiTokenProvider.php @@ -1,5 +1,7 @@ userProvider = $provider; + $this->userChecker = $userChecker; } /** @@ -71,6 +76,7 @@ protected function retrieveUser(string $username, TokenInterface $token): User try { $user = $this->userProvider->loadUserByUsername($username); + $this->userChecker->checkPreAuth($user); } catch (UsernameNotFoundException $e) { throw new BadCredentialsException('Bad credentials.', 0, $e); } catch (\Exception $e) { diff --git a/src/Packagist/WebBundle/Security/Provider/UserProvider.php b/src/Packagist/WebBundle/Security/Provider/UserProvider.php index d00790a4..7b6d8b56 100644 --- a/src/Packagist/WebBundle/Security/Provider/UserProvider.php +++ b/src/Packagist/WebBundle/Security/Provider/UserProvider.php @@ -13,14 +13,10 @@ namespace Packagist\WebBundle\Security\Provider; use FOS\UserBundle\Model\UserManagerInterface; -use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface; -use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException; -use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface; -use Packagist\WebBundle\Entity\User; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; -class UserProvider implements OAuthAwareUserProviderInterface, UserProviderInterface +class UserProvider implements UserProviderInterface { /** * @var UserManagerInterface @@ -42,56 +38,6 @@ public function __construct(UserManagerInterface $userManager, UserProviderInter $this->userProvider = $userProvider; } - /** - * {@inheritDoc} - */ - public function connect($user, UserResponseInterface $response) - { - $username = $response->getUsername(); - - /** @var User $previousUser */ - $previousUser = $this->userManager->findUserBy(array('githubId' => $username)); - - /** @var User $user */ - $user->setGithubId($username); - $user->setGithubToken($response->getAccessToken()); - - // The account is already connected. Do nothing - if ($previousUser === $user) { - return; - } - - // 'disconnect' a previous account - if (null !== $previousUser) { - $previousUser->setGithubId(null); - $previousUser->setGithubToken(null); - $this->userManager->updateUser($previousUser); - } - - $this->userManager->updateUser($user); - } - - /** - * {@inheritDoc} - */ - public function loadUserByOAuthUserResponse(UserResponseInterface $response) - { - $username = $response->getUsername(); - /** @var User $user */ - $user = $this->userManager->findUserBy(array('githubId' => $username)); - - if (!$user) { - throw new AccountNotLinkedException(sprintf('No user with github username "%s" was found.', $username)); - } - - if ($user->getGithubToken() !== $response->getAccessToken()) { - $user->setGithubToken($response->getAccessToken()); - $this->userManager->updateUser($user); - } - - return $user; - } - /** * {@inheritDoc} */ diff --git a/src/Packagist/WebBundle/Service/DistConfig.php b/src/Packagist/WebBundle/Service/DistConfig.php index 2cd39d3f..20e8b901 100644 --- a/src/Packagist/WebBundle/Service/DistConfig.php +++ b/src/Packagist/WebBundle/Service/DistConfig.php @@ -1,4 +1,6 @@ -generateTargetDir($name); - return $targetDir . '/' . $reference . '.' . $this->getArchiveFormat(); + $fileName = $this->getFileName($reference, $version); + return $targetDir . '/' . $fileName . '.' . $this->getArchiveFormat(); + } + + /** + * @param string $reference + * @param string $version + * @return string + */ + public function getFileName(string $reference, string $version): string + { + $fileName = $version . '-' . $reference; + return str_replace('/', '-', $fileName); + } + + /** + * @param string $fileName + * @return string + */ + public function guessesVersion(string $fileName) + { + $fileName = explode('-', $fileName); + $pathCount = count($fileName); + if ($pathCount > 1) { + unset($fileName[$pathCount - 1]); + } + + $fileName = implode('-', $fileName); + $fileName = preg_replace('/(ticket|feature|fix)-/i', '$1/', $fileName); + return $fileName; } /** @@ -80,4 +112,12 @@ public function isEnable(): bool { return !empty($this->config); } + + /** + * @return bool + */ + public function isLazy(): bool + { + return $this->config['lazy'] ?? true; + } } diff --git a/src/Packagist/WebBundle/Service/DistManager.php b/src/Packagist/WebBundle/Service/DistManager.php new file mode 100644 index 00000000..cdaaf7be --- /dev/null +++ b/src/Packagist/WebBundle/Service/DistManager.php @@ -0,0 +1,92 @@ +config = $config; + $this->fileSystem = new Filesystem(); + } + + public function getDistPath(Version $version): ?string + { + $dist = $version->getDist(); + if (false === isset($dist['reference'])) { + return null; + } + + $path = $this->config->generateDistFileName($version->getName(), $dist['reference'], $version->getVersion()); + if ($this->fileSystem->exists($path)) { + return $path; + } + + return $this->download($version); + } + + public function lookupInCache(string $reference, string $packageName): ?array + { + $finder = new Finder(); + $files = $finder + ->in($this->config->generateTargetDir($packageName)) + ->name("/$reference/") + ->files(); + /** @var \SplFileObject $file */ + foreach ($files as $file) { + $fileName = $file->getFilename(); + if ($version = $this->config->guessesVersion($fileName)) { + return [$file->getRealPath(), $version]; + } + } + + return [null, null]; + } + + private function download(Version $version): ?string + { + $package = $version->getPackage(); + $package->loadCredentials(); + + $io = new BufferIO('', StreamOutput::VERBOSITY_VERBOSE); + $config = Factory::createConfig(); + $io->loadConfiguration($config); + $repository = new VcsRepository(['url' => $package->getRepository()], $io, $config); + + $factory = new Factory(); + $dm = $factory->createDownloadManager($io, $config); + $archiveManager = $factory->createArchiveManager($config, $dm); + $archiveManager->setOverwriteFiles(false); + + $versions = $repository->getPackages(); + $source = $version->getSource(); + foreach ($versions as $rootVersion) { + if ($rootVersion->getSourceReference() === $source['reference']) { + $fileName = $this->config->getFileName($source['reference'], $version->getVersion()); + $path = $archiveManager->archive( + $rootVersion, + $this->config->getArchiveFormat(), + $this->config->generateTargetDir($version->getName()), + $fileName + ); + + return $path; + } + } + + return null; + } +} diff --git a/src/Packagist/WebBundle/Service/UpdaterWorker.php b/src/Packagist/WebBundle/Service/UpdaterWorker.php index d3b9e056..754dd649 100644 --- a/src/Packagist/WebBundle/Service/UpdaterWorker.php +++ b/src/Packagist/WebBundle/Service/UpdaterWorker.php @@ -2,13 +2,9 @@ namespace Packagist\WebBundle\Service; -use Composer\IO\IOInterface; -use Composer\Package\Archiver\PharArchiver; -use Composer\Package\Archiver\ZipArchiver; -use Packagist\WebBundle\Package\ArchiveManager; +use Packagist\WebBundle\Model\ValidatingArrayLoader; use Psr\Log\LoggerInterface; use Composer\Package\Loader\ArrayLoader; -use Composer\Package\Loader\ValidatingArrayLoader; use Symfony\Bridge\Doctrine\RegistryInterface; use Composer\Console\HtmlOutputFormatter; use Composer\Repository\InvalidRepositoryException; @@ -23,7 +19,6 @@ use Seld\Signal\SignalHandler; use Composer\Factory; use Composer\Downloader\TransportException; -use Composer\Util\RemoteFilesystem; class UpdaterWorker { @@ -77,7 +72,6 @@ public function process(Job $job, SignalHandler $signal): array $config = Factory::createConfig(); $io = new BufferIO('', OutputInterface::VERBOSITY_VERY_VERBOSE, new HtmlOutputFormatter(Factory::createAdditionalStyles())); $io->loadConfiguration($config); - $archiveManager = $this->createArchiveManager($io); try { $flags = 0; @@ -97,15 +91,7 @@ public function process(Job $job, SignalHandler $signal): array $repository->setLoader($loader); // perform the actual update (fetch and re-scan the repository's source) - $this->updater->setArchiveManager($archiveManager); $package = $this->updater->update($io, $config, $package, $repository, $flags); - - // github update downgraded to a git clone, this should not happen, so check through API whether the package still exists - if (preg_match('{[@/]github.com[:/]([^/]+/[^/]+?)(\.git)?$}i', $package->getRepository(), $match) && 0 === strpos($repository->getDriver()->getUrl(), 'git@')) { - if ($result = $this->checkForDeadGitHubPackage($package, $match, $io, $io->getOutput())) { - return $result; - } - } } catch (\Throwable $e) { $output = $io->getOutput(); @@ -151,13 +137,6 @@ public function process(Job $job, SignalHandler $signal): array $found404 = true; } - // github 404'ed, check through API whether the package still exists and delete if not - if ($found404 && preg_match('{[@/]github.com[:/]([^/]+/[^/]+?)(\.git)?$}i', $package->getRepository(), $match)) { - if ($result = $this->checkForDeadGitHubPackage($package, $match, $io, $output)) { - return $result; - } - } - // detected a 404 so mark the package as gone and prevent updates for 1y if ($found404) { $package->setCrawledAt(new \DateTime('+1 year')); @@ -203,52 +182,4 @@ public function process(Job $job, SignalHandler $signal): array 'details' => '
'.$io->getOutput().'
' ]; } - - private function checkForDeadGitHubPackage(Package $package, $match, $io, $output) - { - $rfs = new RemoteFilesystem($io); - try { - $rfs->getContents('github.com', 'https://api.github.com/repos/'.$match[1], false, ['retry-auth-failure' => false]); - } catch (\Throwable $e) { - if ($e instanceof TransportException && $e->getStatusCode() === 404) { - try { - if ( - // check composer repo is visible to make sure it's not github or something else glitching - $rfs->getContents('github.com', 'https://api.github.com/repos/composer/composer', false, ['retry-auth-failure' => false]) - // remove packages with very low downloads and that are 404 - && $this->downloadManager->getTotalDownloads($package) <= 100 - ) { - $name = $package->getName(); - $this->packageManager->deletePackage($package); - - return [ - 'status' => Job::STATUS_PACKAGE_DELETED, - 'message' => 'Update of '.$package->getName().' failed, package appears to be 404/gone and has been deleted', - 'details' => '
'.$output.'
', - 'exception' => $e, - ]; - } - } catch (\Throwable $e) { - // ignore failures here, we/github must be offline - } - } - } - } - - /** - * @param IOInterface $io - * @return ArchiveManager - */ - private function createArchiveManager(IOInterface $io) - { - $composer = Factory::create($io); - $downloadManager = $composer->getDownloadManager(); - - $archiveManager = new ArchiveManager($downloadManager); - $archiveManager->setOverwriteFiles(false); - $archiveManager->addArchiver(new ZipArchiver()); - $archiveManager->addArchiver(new PharArchiver()); - - return $archiveManager; - } } diff --git a/src/Packagist/WebBundle/Twig/PackagistExtension.php b/src/Packagist/WebBundle/Twig/PackagistExtension.php index 85cc2c09..9b0b9481 100644 --- a/src/Packagist/WebBundle/Twig/PackagistExtension.php +++ b/src/Packagist/WebBundle/Twig/PackagistExtension.php @@ -2,18 +2,18 @@ namespace Packagist\WebBundle\Twig; -use Packagist\WebBundle\Model\ProviderManager; +use Symfony\Component\DependencyInjection\ContainerInterface; class PackagistExtension extends \Twig_Extension { /** - * @var ProviderManager + * @var ContainerInterface */ - private $providerManager; + private $container; - public function __construct(ProviderManager $providerManager) + public function __construct(ContainerInterface $container) { - $this->providerManager = $providerManager; + $this->container = $container; } public function getTests() @@ -49,12 +49,12 @@ public function packageExistsTest($package) return false; } - return $this->providerManager->packageExists($package); + return $this->getProviderManager()->packageExists($package); } public function providerExistsTest($package) { - return $this->providerManager->packageIsProvided($package); + return $this->getProviderManager()->packageIsProvided($package); } public function prettifySourceReference($sourceReference) @@ -70,4 +70,12 @@ public function generateGravatarHash($email) { return md5(strtolower($email)); } + + /** + * @return \Packagist\WebBundle\Model\ProviderManager + */ + private function getProviderManager() + { + return $this->container->get('packagist.provider_manager'); + } } diff --git a/src/Packagist/WebBundle/Util/UserManipulator.php b/src/Packagist/WebBundle/Util/UserManipulator.php index 813a4ba8..8166e772 100644 --- a/src/Packagist/WebBundle/Util/UserManipulator.php +++ b/src/Packagist/WebBundle/Util/UserManipulator.php @@ -15,8 +15,8 @@ use FOS\UserBundle\Model\UserManagerInterface; use FOS\UserBundle\Util\TokenGeneratorInterface; use FOS\UserBundle\Util\UserManipulator as BaseManipulator; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\RequestStack; class UserManipulator extends BaseManipulator { @@ -30,13 +30,13 @@ public function __construct( UserManagerInterface $userManager, TokenGeneratorInterface $tokenGenerator, EventDispatcherInterface $dispatcher, - ContainerInterface $container + RequestStack $requestStack ) { $this->userManager = $userManager; $this->tokenGenerator = $tokenGenerator; - parent::__construct($userManager, $dispatcher, $container); + parent::__construct($userManager, $dispatcher, $requestStack); } /** diff --git a/var/SymfonyRequirements.php b/var/SymfonyRequirements.php new file mode 100644 index 00000000..4a1fcc62 --- /dev/null +++ b/var/SymfonyRequirements.php @@ -0,0 +1,810 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/* + * Users of PHP 5.2 should be able to run the requirements checks. + * This is why the file and all classes must be compatible with PHP 5.2+ + * (e.g. not using namespaces and closures). + * + * ************** CAUTION ************** + * + * DO NOT EDIT THIS FILE as it will be overridden by Composer as part of + * the installation/update process. The original file resides in the + * SensioDistributionBundle. + * + * ************** CAUTION ************** + */ + +/** + * Represents a single PHP requirement, e.g. an installed extension. + * It can be a mandatory requirement or an optional recommendation. + * There is a special subclass, named PhpIniRequirement, to check a php.ini configuration. + * + * @author Tobias Schultze + */ +class Requirement +{ + private $fulfilled; + private $testMessage; + private $helpText; + private $helpHtml; + private $optional; + + /** + * Constructor that initializes the requirement. + * + * @param bool $fulfilled Whether the requirement is fulfilled + * @param string $testMessage The message for testing the requirement + * @param string $helpHtml The help text formatted in HTML for resolving the problem + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * @param bool $optional Whether this is only an optional recommendation not a mandatory requirement + */ + public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false) + { + $this->fulfilled = (bool) $fulfilled; + $this->testMessage = (string) $testMessage; + $this->helpHtml = (string) $helpHtml; + $this->helpText = null === $helpText ? strip_tags($this->helpHtml) : (string) $helpText; + $this->optional = (bool) $optional; + } + + /** + * Returns whether the requirement is fulfilled. + * + * @return bool true if fulfilled, otherwise false + */ + public function isFulfilled() + { + return $this->fulfilled; + } + + /** + * Returns the message for testing the requirement. + * + * @return string The test message + */ + public function getTestMessage() + { + return $this->testMessage; + } + + /** + * Returns the help text for resolving the problem. + * + * @return string The help text + */ + public function getHelpText() + { + return $this->helpText; + } + + /** + * Returns the help text formatted in HTML. + * + * @return string The HTML help + */ + public function getHelpHtml() + { + return $this->helpHtml; + } + + /** + * Returns whether this is only an optional recommendation and not a mandatory requirement. + * + * @return bool true if optional, false if mandatory + */ + public function isOptional() + { + return $this->optional; + } +} + +/** + * Represents a PHP requirement in form of a php.ini configuration. + * + * @author Tobias Schultze + */ +class PhpIniRequirement extends Requirement +{ + /** + * Constructor that initializes the requirement. + * + * @param string $cfgName The configuration name used for ini_get() + * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) + * @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * @param bool $optional Whether this is only an optional recommendation not a mandatory requirement + */ + public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false) + { + $cfgValue = ini_get($cfgName); + + if (is_callable($evaluation)) { + if (null === $testMessage || null === $helpHtml) { + throw new InvalidArgumentException('You must provide the parameters testMessage and helpHtml for a callback evaluation.'); + } + + $fulfilled = call_user_func($evaluation, $cfgValue); + } else { + if (null === $testMessage) { + $testMessage = sprintf('%s %s be %s in php.ini', + $cfgName, + $optional ? 'should' : 'must', + $evaluation ? 'enabled' : 'disabled' + ); + } + + if (null === $helpHtml) { + $helpHtml = sprintf('Set %s to %s in php.ini*.', + $cfgName, + $evaluation ? 'on' : 'off' + ); + } + + $fulfilled = $evaluation == $cfgValue; + } + + parent::__construct($fulfilled || ($approveCfgAbsence && false === $cfgValue), $testMessage, $helpHtml, $helpText, $optional); + } +} + +/** + * A RequirementCollection represents a set of Requirement instances. + * + * @author Tobias Schultze + */ +class RequirementCollection implements IteratorAggregate +{ + /** + * @var Requirement[] + */ + private $requirements = array(); + + /** + * Gets the current RequirementCollection as an Iterator. + * + * @return Traversable A Traversable interface + */ + public function getIterator() + { + return new ArrayIterator($this->requirements); + } + + /** + * Adds a Requirement. + * + * @param Requirement $requirement A Requirement instance + */ + public function add(Requirement $requirement) + { + $this->requirements[] = $requirement; + } + + /** + * Adds a mandatory requirement. + * + * @param bool $fulfilled Whether the requirement is fulfilled + * @param string $testMessage The message for testing the requirement + * @param string $helpHtml The help text formatted in HTML for resolving the problem + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null) + { + $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, false)); + } + + /** + * Adds an optional recommendation. + * + * @param bool $fulfilled Whether the recommendation is fulfilled + * @param string $testMessage The message for testing the recommendation + * @param string $helpHtml The help text formatted in HTML for resolving the problem + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null) + { + $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, true)); + } + + /** + * Adds a mandatory requirement in form of a php.ini configuration. + * + * @param string $cfgName The configuration name used for ini_get() + * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) + * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) + { + $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, false)); + } + + /** + * Adds an optional recommendation in form of a php.ini configuration. + * + * @param string $cfgName The configuration name used for ini_get() + * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) + * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) + { + $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, true)); + } + + /** + * Adds a requirement collection to the current set of requirements. + * + * @param RequirementCollection $collection A RequirementCollection instance + */ + public function addCollection(RequirementCollection $collection) + { + $this->requirements = array_merge($this->requirements, $collection->all()); + } + + /** + * Returns both requirements and recommendations. + * + * @return Requirement[] + */ + public function all() + { + return $this->requirements; + } + + /** + * Returns all mandatory requirements. + * + * @return Requirement[] + */ + public function getRequirements() + { + $array = array(); + foreach ($this->requirements as $req) { + if (!$req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns the mandatory requirements that were not met. + * + * @return Requirement[] + */ + public function getFailedRequirements() + { + $array = array(); + foreach ($this->requirements as $req) { + if (!$req->isFulfilled() && !$req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns all optional recommendations. + * + * @return Requirement[] + */ + public function getRecommendations() + { + $array = array(); + foreach ($this->requirements as $req) { + if ($req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns the recommendations that were not met. + * + * @return Requirement[] + */ + public function getFailedRecommendations() + { + $array = array(); + foreach ($this->requirements as $req) { + if (!$req->isFulfilled() && $req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns whether a php.ini configuration is not correct. + * + * @return bool php.ini configuration problem? + */ + public function hasPhpIniConfigIssue() + { + foreach ($this->requirements as $req) { + if (!$req->isFulfilled() && $req instanceof PhpIniRequirement) { + return true; + } + } + + return false; + } + + /** + * Returns the PHP configuration file (php.ini) path. + * + * @return string|false php.ini file path + */ + public function getPhpIniConfigPath() + { + return get_cfg_var('cfg_file_path'); + } +} + +/** + * This class specifies all requirements and optional recommendations that + * are necessary to run the Symfony Standard Edition. + * + * @author Tobias Schultze + * @author Fabien Potencier + */ +class SymfonyRequirements extends RequirementCollection +{ + const LEGACY_REQUIRED_PHP_VERSION = '5.3.3'; + const REQUIRED_PHP_VERSION = '5.5.9'; + + /** + * Constructor that initializes the requirements. + */ + public function __construct() + { + /* mandatory requirements follow */ + + $installedPhpVersion = PHP_VERSION; + $requiredPhpVersion = $this->getPhpRequiredVersion(); + + $this->addRecommendation( + $requiredPhpVersion, + 'Vendors should be installed in order to check all requirements.', + 'Run the composer install command.', + 'Run the "composer install" command.' + ); + + if (false !== $requiredPhpVersion) { + $this->addRequirement( + version_compare($installedPhpVersion, $requiredPhpVersion, '>='), + sprintf('PHP version must be at least %s (%s installed)', $requiredPhpVersion, $installedPhpVersion), + sprintf('You are running PHP version "%s", but Symfony needs at least PHP "%s" to run. + Before using Symfony, upgrade your PHP installation, preferably to the latest version.', + $installedPhpVersion, $requiredPhpVersion), + sprintf('Install PHP %s or newer (installed version is %s)', $requiredPhpVersion, $installedPhpVersion) + ); + } + + $this->addRequirement( + version_compare($installedPhpVersion, '5.3.16', '!='), + 'PHP version must not be 5.3.16 as Symfony won\'t work properly with it', + 'Install PHP 5.3.17 or newer (or downgrade to an earlier PHP version)' + ); + + $this->addRequirement( + is_dir(__DIR__.'/../vendor/composer'), + 'Vendor libraries must be installed', + 'Vendor libraries are missing. Install composer following instructions from http://getcomposer.org/. '. + 'Then run "php composer.phar install" to install them.' + ); + + $cacheDir = is_dir(__DIR__.'/../var/cache') ? __DIR__.'/../var/cache' : __DIR__.'/cache'; + + $this->addRequirement( + is_writable($cacheDir), + 'app/cache/ or var/cache/ directory must be writable', + 'Change the permissions of either "app/cache/" or "var/cache/" directory so that the web server can write into it.' + ); + + $logsDir = is_dir(__DIR__.'/../var/logs') ? __DIR__.'/../var/logs' : __DIR__.'/logs'; + + $this->addRequirement( + is_writable($logsDir), + 'app/logs/ or var/logs/ directory must be writable', + 'Change the permissions of either "app/logs/" or "var/logs/" directory so that the web server can write into it.' + ); + + if (version_compare($installedPhpVersion, '7.0.0', '<')) { + $this->addPhpIniRequirement( + 'date.timezone', true, false, + 'date.timezone setting must be set', + 'Set the "date.timezone" setting in php.ini* (like Europe/Paris).' + ); + } + + if (false !== $requiredPhpVersion && version_compare($installedPhpVersion, $requiredPhpVersion, '>=')) { + $this->addRequirement( + in_array(@date_default_timezone_get(), DateTimeZone::listIdentifiers(), true), + sprintf('Configured default timezone "%s" must be supported by your installation of PHP', @date_default_timezone_get()), + 'Your default timezone is not supported by PHP. Check for typos in your php.ini file and have a look at the list of deprecated timezones at http://php.net/manual/en/timezones.others.php.' + ); + } + + $this->addRequirement( + function_exists('iconv'), + 'iconv() must be available', + 'Install and enable the iconv extension.' + ); + + $this->addRequirement( + function_exists('json_encode'), + 'json_encode() must be available', + 'Install and enable the JSON extension.' + ); + + $this->addRequirement( + function_exists('session_start'), + 'session_start() must be available', + 'Install and enable the session extension.' + ); + + $this->addRequirement( + function_exists('ctype_alpha'), + 'ctype_alpha() must be available', + 'Install and enable the ctype extension.' + ); + + $this->addRequirement( + function_exists('token_get_all'), + 'token_get_all() must be available', + 'Install and enable the Tokenizer extension.' + ); + + $this->addRequirement( + function_exists('simplexml_import_dom'), + 'simplexml_import_dom() must be available', + 'Install and enable the SimpleXML extension.' + ); + + if (function_exists('apc_store') && ini_get('apc.enabled')) { + if (version_compare($installedPhpVersion, '5.4.0', '>=')) { + $this->addRequirement( + version_compare(phpversion('apc'), '3.1.13', '>='), + 'APC version must be at least 3.1.13 when using PHP 5.4', + 'Upgrade your APC extension (3.1.13+).' + ); + } else { + $this->addRequirement( + version_compare(phpversion('apc'), '3.0.17', '>='), + 'APC version must be at least 3.0.17', + 'Upgrade your APC extension (3.0.17+).' + ); + } + } + + $this->addPhpIniRequirement('detect_unicode', false); + + if (extension_loaded('suhosin')) { + $this->addPhpIniRequirement( + 'suhosin.executor.include.whitelist', + create_function('$cfgValue', 'return false !== stripos($cfgValue, "phar");'), + false, + 'suhosin.executor.include.whitelist must be configured correctly in php.ini', + 'Add "phar" to suhosin.executor.include.whitelist in php.ini*.' + ); + } + + if (extension_loaded('xdebug')) { + $this->addPhpIniRequirement( + 'xdebug.show_exception_trace', false, true + ); + + $this->addPhpIniRequirement( + 'xdebug.scream', false, true + ); + + $this->addPhpIniRecommendation( + 'xdebug.max_nesting_level', + create_function('$cfgValue', 'return $cfgValue > 100;'), + true, + 'xdebug.max_nesting_level should be above 100 in php.ini', + 'Set "xdebug.max_nesting_level" to e.g. "250" in php.ini* to stop Xdebug\'s infinite recursion protection erroneously throwing a fatal error in your project.' + ); + } + + $pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null; + + $this->addRequirement( + null !== $pcreVersion, + 'PCRE extension must be available', + 'Install the PCRE extension (version 8.0+).' + ); + + if (extension_loaded('mbstring')) { + $this->addPhpIniRequirement( + 'mbstring.func_overload', + create_function('$cfgValue', 'return (int) $cfgValue === 0;'), + true, + 'string functions should not be overloaded', + 'Set "mbstring.func_overload" to 0 in php.ini* to disable function overloading by the mbstring extension.' + ); + } + + /* optional recommendations follow */ + + if (file_exists(__DIR__.'/../vendor/composer')) { + require_once __DIR__.'/../vendor/autoload.php'; + + try { + $r = new ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle'); + + $contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php'); + } catch (ReflectionException $e) { + $contents = ''; + } + $this->addRecommendation( + file_get_contents(__FILE__) === $contents, + 'Requirements file should be up-to-date', + 'Your requirements file is outdated. Run composer install and re-check your configuration.' + ); + } + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.3.4', '>='), + 'You should use at least PHP 5.3.4 due to PHP bug #52083 in earlier versions', + 'Your project might malfunction randomly due to PHP bug #52083 ("Notice: Trying to get property of non-object"). Install PHP 5.3.4 or newer.' + ); + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.3.8', '>='), + 'When using annotations you should have at least PHP 5.3.8 due to PHP bug #55156', + 'Install PHP 5.3.8 or newer if your project uses annotations.' + ); + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.4.0', '!='), + 'You should not use PHP 5.4.0 due to the PHP bug #61453', + 'Your project might not work properly due to the PHP bug #61453 ("Cannot dump definitions which have method calls"). Install PHP 5.4.1 or newer.' + ); + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.4.11', '>='), + 'When using the logout handler from the Symfony Security Component, you should have at least PHP 5.4.11 due to PHP bug #63379 (as a workaround, you can also set invalidate_session to false in the security logout handler configuration)', + 'Install PHP 5.4.11 or newer if your project uses the logout handler from the Symfony Security Component.' + ); + + $this->addRecommendation( + (version_compare($installedPhpVersion, '5.3.18', '>=') && version_compare($installedPhpVersion, '5.4.0', '<')) + || + version_compare($installedPhpVersion, '5.4.8', '>='), + 'You should use PHP 5.3.18+ or PHP 5.4.8+ to always get nice error messages for fatal errors in the development environment due to PHP bug #61767/#60909', + 'Install PHP 5.3.18+ or PHP 5.4.8+ if you want nice error messages for all fatal errors in the development environment.' + ); + + if (null !== $pcreVersion) { + $this->addRecommendation( + $pcreVersion >= 8.0, + sprintf('PCRE extension should be at least version 8.0 (%s installed)', $pcreVersion), + 'PCRE 8.0+ is preconfigured in PHP since 5.3.2 but you are using an outdated version of it. Symfony probably works anyway but it is recommended to upgrade your PCRE extension.' + ); + } + + $this->addRecommendation( + class_exists('DomDocument'), + 'PHP-DOM and PHP-XML modules should be installed', + 'Install and enable the PHP-DOM and the PHP-XML modules.' + ); + + $this->addRecommendation( + function_exists('mb_strlen'), + 'mb_strlen() should be available', + 'Install and enable the mbstring extension.' + ); + + $this->addRecommendation( + function_exists('utf8_decode'), + 'utf8_decode() should be available', + 'Install and enable the XML extension.' + ); + + $this->addRecommendation( + function_exists('filter_var'), + 'filter_var() should be available', + 'Install and enable the filter extension.' + ); + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->addRecommendation( + function_exists('posix_isatty'), + 'posix_isatty() should be available', + 'Install and enable the php_posix extension (used to colorize the CLI output).' + ); + } + + $this->addRecommendation( + extension_loaded('intl'), + 'intl extension should be available', + 'Install and enable the intl extension (used for validators).' + ); + + if (extension_loaded('intl')) { + // in some WAMP server installations, new Collator() returns null + $this->addRecommendation( + null !== new Collator('fr_FR'), + 'intl extension should be correctly configured', + 'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.' + ); + + // check for compatible ICU versions (only done when you have the intl extension) + if (defined('INTL_ICU_VERSION')) { + $version = INTL_ICU_VERSION; + } else { + $reflector = new ReflectionExtension('intl'); + + ob_start(); + $reflector->info(); + $output = strip_tags(ob_get_clean()); + + preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches); + $version = $matches[1]; + } + + $this->addRecommendation( + version_compare($version, '4.0', '>='), + 'intl ICU version should be at least 4+', + 'Upgrade your intl extension with a newer ICU version (4+).' + ); + + if (class_exists('Symfony\Component\Intl\Intl')) { + $this->addRecommendation( + \Symfony\Component\Intl\Intl::getIcuDataVersion() <= \Symfony\Component\Intl\Intl::getIcuVersion(), + sprintf('intl ICU version installed on your system is outdated (%s) and does not match the ICU data bundled with Symfony (%s)', \Symfony\Component\Intl\Intl::getIcuVersion(), \Symfony\Component\Intl\Intl::getIcuDataVersion()), + 'To get the latest internationalization data upgrade the ICU system package and the intl PHP extension.' + ); + if (\Symfony\Component\Intl\Intl::getIcuDataVersion() <= \Symfony\Component\Intl\Intl::getIcuVersion()) { + $this->addRecommendation( + \Symfony\Component\Intl\Intl::getIcuDataVersion() === \Symfony\Component\Intl\Intl::getIcuVersion(), + sprintf('intl ICU version installed on your system (%s) does not match the ICU data bundled with Symfony (%s)', \Symfony\Component\Intl\Intl::getIcuVersion(), \Symfony\Component\Intl\Intl::getIcuDataVersion()), + 'To avoid internationalization data inconsistencies upgrade the symfony/intl component.' + ); + } + } + + $this->addPhpIniRecommendation( + 'intl.error_level', + create_function('$cfgValue', 'return (int) $cfgValue === 0;'), + true, + 'intl.error_level should be 0 in php.ini', + 'Set "intl.error_level" to "0" in php.ini* to inhibit the messages when an error occurs in ICU functions.' + ); + } + + $accelerator = + (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) + || + (extension_loaded('apc') && ini_get('apc.enabled')) + || + (extension_loaded('Zend Optimizer+') && ini_get('zend_optimizerplus.enable')) + || + (extension_loaded('Zend OPcache') && ini_get('opcache.enable')) + || + (extension_loaded('xcache') && ini_get('xcache.cacher')) + || + (extension_loaded('wincache') && ini_get('wincache.ocenabled')) + ; + + $this->addRecommendation( + $accelerator, + 'a PHP accelerator should be installed', + 'Install and/or enable a PHP accelerator (highly recommended).' + ); + + if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) { + $this->addRecommendation( + $this->getRealpathCacheSize() >= 5 * 1024 * 1024, + 'realpath_cache_size should be at least 5M in php.ini', + 'Setting "realpath_cache_size" to e.g. "5242880" or "5M" in php.ini* may improve performance on Windows significantly in some cases.' + ); + } + + $this->addPhpIniRecommendation('short_open_tag', false); + + $this->addPhpIniRecommendation('magic_quotes_gpc', false, true); + + $this->addPhpIniRecommendation('register_globals', false, true); + + $this->addPhpIniRecommendation('session.auto_start', false); + + $this->addRecommendation( + class_exists('PDO'), + 'PDO should be installed', + 'Install PDO (mandatory for Doctrine).' + ); + + if (class_exists('PDO')) { + $drivers = PDO::getAvailableDrivers(); + $this->addRecommendation( + count($drivers) > 0, + sprintf('PDO should have some drivers installed (currently available: %s)', count($drivers) ? implode(', ', $drivers) : 'none'), + 'Install PDO drivers (mandatory for Doctrine).' + ); + } + } + + /** + * Loads realpath_cache_size from php.ini and converts it to int. + * + * (e.g. 16k is converted to 16384 int) + * + * @return int + */ + protected function getRealpathCacheSize() + { + $size = ini_get('realpath_cache_size'); + $size = trim($size); + $unit = ''; + if (!ctype_digit($size)) { + $unit = strtolower(substr($size, -1, 1)); + $size = (int) substr($size, 0, -1); + } + switch ($unit) { + case 'g': + return $size * 1024 * 1024 * 1024; + case 'm': + return $size * 1024 * 1024; + case 'k': + return $size * 1024; + default: + return (int) $size; + } + } + + /** + * Defines PHP required version from Symfony version. + * + * @return string|false The PHP required version or false if it could not be guessed + */ + protected function getPhpRequiredVersion() + { + if (!file_exists($path = __DIR__.'/../composer.lock')) { + return false; + } + + $composerLock = json_decode(file_get_contents($path), true); + foreach ($composerLock['packages'] as $package) { + $name = $package['name']; + if ('symfony/symfony' !== $name && 'symfony/http-kernel' !== $name) { + continue; + } + + return (int) $package['version'][1] > 2 ? self::REQUIRED_PHP_VERSION : self::LEGACY_REQUIRED_PHP_VERSION; + } + + return false; + } +} diff --git a/web/app.php b/web/app.php index 3681a3fa..57c21828 100644 --- a/web/app.php +++ b/web/app.php @@ -2,25 +2,12 @@ use Symfony\Component\HttpFoundation\Request; -/** - * @var \Symfony\Component\ClassLoader\ClassLoader - */ -$loader = require __DIR__.'/../app/autoload.php'; -include_once __DIR__.'/../app/bootstrap.php.cache'; +require __DIR__.'/../vendor/autoload.php'; $kernel = new AppKernel('prod', false); -$kernel->loadClassCache(); - -if ($_SERVER['REMOTE_ADDR'] === '144.217.203.53') { - Request::setTrustedProxies([$_SERVER['REMOTE_ADDR']]); - // force all trusted header names - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, ''); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_REAL_IP'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, ''); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, ''); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, ''); -} +// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter +//Request::enableHttpMethodParameterOverride(); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); diff --git a/web/app_dev.php b/web/app_dev.php index 9a4676f3..57e1a433 100644 --- a/web/app_dev.php +++ b/web/app_dev.php @@ -1,33 +1,27 @@ loadClassCache(); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); diff --git a/web/apple-touch-icon-precomposed.png b/web/apple-touch-icon-precomposed.png deleted file mode 100644 index 8132e4ae7d939ecc7041810796982b453a8db92b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8307 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 diff --git a/web/apple-touch-icon.png b/web/apple-touch-icon.png deleted file mode 100644 index 8132e4ae7d939ecc7041810796982b453a8db92b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8307 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 diff --git a/web/favicon.ico b/web/favicon.ico index 4d9cd5eb82b31b1f0543b5657ba478775979f112..9a5742c0cb6e516e56d1a436e659c617bbd44d4d 100644 GIT binary patch literal 5430 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

}% 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

|D6D1|zYq$j+Y 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 - - Packagist - Packagist PHP Package Search - Use Packagist.org to search for PHP packages. - packagist composer php - contact@packagist.org - - en-us - UTF-8 - UTF-8 - https://packagist.org/apple-touch-icon.png - https://packagist.org/favicon.ico - diff --git a/web/touch-icon-192x192.png b/web/touch-icon-192x192.png deleted file mode 100644 index 58114b8f6ae1b1f905533657013a37dc51a60adc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8930 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 moZ