diff --git a/.gitignore b/.gitignore
index 933c555..022d1eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,16 @@
/.settings
/.project
/.buildpath
+/.composer
/satis.phar
/vendor
/satis.json
/web/packages.json
/web/include
+/web/dist
!/web/robots.txt
/config.yml
/cache/*
/logs/*
-/config/deploy.rb
+/satis/*
+/database.sqlite
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3879cba..0cb4648 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -3,7 +3,7 @@ Contributing Guidelines
This document outlines the recommended way to contribute to Packages.
-> More information can be found in the [project documentation](http://docs.terramarlabs.com/packages/3.1).
+> More information can be found in the [project documentation](http://docs.terramarlabs.com/packages/3.2).
Getting started
---------------
@@ -29,7 +29,7 @@ Other considerations
* The master branch contains active development.
* Create or a feature branch or don't-- whatever you prefer!
-* The project follows PSR-4 and, somewhat loosely, PSR-2.
+* The project follows PSR-1, -2, and -4.
* Consider writing unit tests for your change.
### And don't be afraid to ask for help!
diff --git a/README.md b/README.md
index 32cd47c..d3abc47 100644
--- a/README.md
+++ b/README.md
@@ -5,10 +5,130 @@ Packages
[![Build Status](https://img.shields.io/travis/terramar-labs/packages/master.svg?style=flat-square)](https://travis-ci.org/terramar-labs/packages)
-Packages is a PHP 5.6 and 7.x application providing an interface and tools for maintaining a private composer repository. Packages extends [Satis](https://github.com/composer/satis), adding a web frontend and useful management functionality like GitHub and GitLab integration.
+Packages is a PHP 5.6 and 7.x application providing an interface and tools for maintaining a private [Composer](https://getcomposer.org) repository. Packages extends [Satis](https://github.com/composer/satis), adding a web frontend and useful management functionality like GitHub and GitLab integration.
-Packages automatically registers GitLab and GitHub project web hooks to keep Satis up to date every time you push code. Packages also features a web management interface that allows for easy management of exposed packages and configured source control repositories.
+Packages automatically registers GitLab and GitHub project webhooks to keep Satis up to date every time you push code. Packages also features a web management interface that allows for easy management of exposed packages and configured source control repositories.
Packages version 3 works on a plugin based system based around source code repositories. Packages can trigger, with each code push, many automated tasks like documentation generation or code analysis. The simple event-based architecture allows easy creation of new automation tasks.
-[View the docs online](http://docs.terramarlabs.com/packages/3.1)
+[View the docs online](http://docs.terramarlabs.com/packages/3.2).
+
+Installation
+------------
+
+Pre-requisites:
+ * PHP 5.6 or later
+ * [Composer](https://getcomposer.org)
+ * Some database platform supported by [Doctrine 2](http://doctrine-project.org) (sqlite works great!)
+ * [Redis](https://redis.io/)
+
+Download the [latest release](https://github.com/terramar-labs/packages/releases/latest), or clone the repository.
+
+```bash
+git clone git@github.com:terramar-labs/packages.git
+```
+
+### Install dependencies
+
+Switch to the project root directory and run `composer install`.
+
+```bash
+cd packages
+composer install
+```
+
+### Edit configuration
+
+Copy `config.yml.dist` to `config.yml` and edit as appropriate.
+
+```bash
+cp config.yml.dist config.yml
+vi config.yml
+```
+
+### Generate the database schema
+
+Packages uses Doctrine ORM to auto-generate the database schema for your configured platform.
+
+```bash
+bin/console orm:schema-tool:create
+```
+
+Running the application
+-----------------------
+
+Start PHP's built-in webserver to run the Packages web application with minimal effort.
+
+```bash
+# Visit http://localhost:8080 to see the landing page.
+php -S localhost:8080 -t web
+```
+
+### Start a Resque worker
+
+For fully-automatic integration with GitHub, GitLab, and your Satis repository, you must always have at least one Resque worker running.
+
+```bash
+bin/console resque:worker:start
+```
+
+> For more information on Resque workers, check [the dedicated section](http://docs.terramarlabs.com/packages/3.2/managing-packages/resque).
+
+
+Using the application
+---------------------
+
+Read the [usage and design documentation](http://docs.terramarlabs.com/packages/3.2/getting-started/usage) for an overview of Packages functionality.
+
+
+### Development/debug mode
+
+Visit `index_dev.php` in your browser to view the site with the `dev` environment configuration. In this env, views and the service container are not cached, so changes made are immediately visible.
+
+### Customizing
+
+Check out the [Contributing Guide](CONTRIBUTING.md) for the recommended way to set up your development environment.
+
+Some tips:
+
+* Views are written using Twig and stored in `views/`.
+ * Views are cached in `prod` env; use `http://localhost:8080/index_dev.php` to develop.
+ * All pages inherit from `views/base.html.twig`, except for
+ * Public landing page views inherit from `views/Default/base.html.twig`.
+* [Composer Components](http://robloach.github.io/component-installer/) are used to manage front-end dependencies. The respective `web/images/`, `web/js/bootstrap.min.js`, and such are symlinks pointing to the real files installed by Composer in `vendor/`.
+* Check [the documentation](http://docs.terramarlabs.com/packages/3.2/getting-started/customizing) for additional information.
+
+
+Docker support
+--------------
+
+Packages comes with an example `docker-compose.yml` that starts an nginx container and a Redis container, ready to get up and running quickly.
+
+Visit [the documentation](http://docs.terramarlabs.com/packages/3.2/getting-started/docker) to get started.
+
+Troubleshooting
+---------------
+
+1. `index_dev.php` contains a non-localhost block, comment it out when using Docker.
+2. Manage Resque and Satis using the `bin/console` command-line utility.
+ * **Build the Satis `packages.json` file** with the `satis:build` command.
+ ```bash
+ bin/console satis:build
+ ```
+ * **View queued Resque jobs in Redis** with the `resque:queue:list` command.
+ ```bash
+ bin/console resque:queue:list
+ ```
+ * **View active Resque workers** with the `resque:worker:list` command.
+ ```bash
+ bin/console resque:worker:list
+ ```
+ * **Start a Resque worker** with `resque:worker:start`.
+ ```bash
+ bin/console resque:worker:start
+ ```
+3. Check the Resque logs to see if Resque is working properly.
+ ```bash
+ tail -f logs/resque.log
+ ```
+
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 810cb6d..6cfc843 100644
--- a/composer.json
+++ b/composer.json
@@ -22,20 +22,32 @@
"composer/composer": "1.4.3",
"sami/sami": "~1.4",
"m4tthumphrey/php-gitlab-api": "~7.13",
- "knplabs/github-api": "~1.4"
+ "knplabs/github-api": "~1.4",
+ "php-http/guzzle6-adapter": "^1.1",
+ "datatables/datatables": "^1.10",
+ "twbs/bootstrap": "3.3.7",
+ "fortawesome/font-awesome": "^4.7",
+ "components/jquery": "^3.2"
+ },
+ "config": {
+ "platform": {
+ "php": "5.6"
+ },
+ "component-dir": "vendor"
},
"require-dev": {
"phpunit/phpunit": "~3.7"
},
"autoload": {
"psr-4": {
- "Terramar\\Packages\\": "src/"
+ "Terramar\\Packages\\": "src/",
+ "Composer\\": "lib/Composer/"
}
},
"extra": {
"branch-alias": {
"dev-master": "3.1-dev",
- "dev-2-1-master": "2.1-dev"
+ "dev-3.2.x": "3.2-dev"
}
},
"minimum-stability": "beta",
diff --git a/composer.lock b/composer.lock
index 4a7dd66..2af682e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"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": "306db3a15935a295f81e3cbe5c7a5467",
+ "content-hash": "822b1fc1c79bb5a4de8ed34bc50eb42e",
"packages": [
{
"name": "chrisboulton/php-resque",
@@ -64,16 +64,16 @@
},
{
"name": "colinmollenhour/credis",
- "version": "1.9.0",
+ "version": "1.9.1",
"source": {
"type": "git",
"url": "https://github.com/colinmollenhour/credis.git",
- "reference": "e8e9b2081fb9b61097486dcaf8b6c11a7399da2d"
+ "reference": "049ccfb2c680e4dfa6adcfa97f2f29d086919abd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/colinmollenhour/credis/zipball/e8e9b2081fb9b61097486dcaf8b6c11a7399da2d",
- "reference": "e8e9b2081fb9b61097486dcaf8b6c11a7399da2d",
+ "url": "https://api.github.com/repos/colinmollenhour/credis/zipball/049ccfb2c680e4dfa6adcfa97f2f29d086919abd",
+ "reference": "049ccfb2c680e4dfa6adcfa97f2f29d086919abd",
"shasum": ""
},
"require": {
@@ -100,7 +100,49 @@
],
"description": "Credis is a lightweight interface to the Redis key-value store which wraps the phpredis library when available for better performance.",
"homepage": "https://github.com/colinmollenhour/credis",
- "time": "2017-09-26T05:03:25+00:00"
+ "time": "2017-10-05T20:28:58+00:00"
+ },
+ {
+ "name": "components/jquery",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/components/jquery.git",
+ "reference": "e5534d4ab8e80c159553d507e358ed20a806d3bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/components/jquery/zipball/e5534d4ab8e80c159553d507e358ed20a806d3bf",
+ "reference": "e5534d4ab8e80c159553d507e358ed20a806d3bf",
+ "shasum": ""
+ },
+ "type": "component",
+ "extra": {
+ "component": {
+ "scripts": [
+ "jquery.js"
+ ],
+ "files": [
+ "jquery.min.js",
+ "jquery.min.map",
+ "jquery.slim.js",
+ "jquery.slim.min.js",
+ "jquery.slim.min.map"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "JS Foundation and other contributors"
+ }
+ ],
+ "description": "jQuery JavaScript Library",
+ "homepage": "http://jquery.com",
+ "time": "2017-03-21T07:01:49+00:00"
},
{
"name": "composer/ca-bundle",
@@ -427,6 +469,29 @@
],
"time": "2017-04-03T19:08:52+00:00"
},
+ {
+ "name": "datatables/datatables",
+ "version": "1.10.16",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DataTables/DataTables.git",
+ "reference": "75a665f64f02982c0f4666b15a25c4670e5e6b18"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DataTables/DataTables/zipball/75a665f64f02982c0f4666b15a25c4670e5e6b18",
+ "reference": "75a665f64f02982c0f4666b15a25c4670e5e6b18",
+ "shasum": ""
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, based upon the foundations of progressive enhancement, which will add advanced interaction controls to any HTML table.",
+ "homepage": "http://www.datatables.net/",
+ "time": "2017-08-31T13:52:17+00:00"
+ },
{
"name": "doctrine/annotations",
"version": "v1.4.0",
@@ -1101,24 +1166,72 @@
],
"time": "2017-09-18T06:50:20+00:00"
},
+ {
+ "name": "fortawesome/font-awesome",
+ "version": "v4.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FortAwesome/Font-Awesome.git",
+ "reference": "a8386aae19e200ddb0f6845b5feeee5eb7013687"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FortAwesome/Font-Awesome/zipball/a8386aae19e200ddb0f6845b5feeee5eb7013687",
+ "reference": "a8386aae19e200ddb0f6845b5feeee5eb7013687",
+ "shasum": ""
+ },
+ "require-dev": {
+ "jekyll": "1.0.2",
+ "lessc": "1.4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.6.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "OFL-1.1",
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Dave Gandy",
+ "email": "dave@fontawesome.io",
+ "homepage": "http://twitter.com/davegandy",
+ "role": "Developer"
+ }
+ ],
+ "description": "The iconic font and CSS framework",
+ "homepage": "http://fontawesome.io/",
+ "keywords": [
+ "FontAwesome",
+ "awesome",
+ "bootstrap",
+ "font",
+ "icon"
+ ],
+ "time": "2016-10-24T15:52:54+00:00"
+ },
{
"name": "guzzle/guzzle",
- "version": "v3.9.3",
+ "version": "v3.8.1",
"source": {
"type": "git",
- "url": "https://github.com/guzzle/guzzle3.git",
- "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
- "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
+ "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.3",
- "symfony/event-dispatcher": "~2.1"
+ "symfony/event-dispatcher": ">=2.1"
},
"replace": {
"guzzle/batch": "self.version",
@@ -1145,21 +1258,18 @@
"guzzle/stream": "self.version"
},
"require-dev": {
- "doctrine/cache": "~1.3",
- "monolog/monolog": "~1.0",
+ "doctrine/cache": "*",
+ "monolog/monolog": "1.*",
"phpunit/phpunit": "3.7.*",
- "psr/log": "~1.0",
- "symfony/class-loader": "~2.1",
- "zendframework/zend-cache": "2.*,<2.3",
- "zendframework/zend-log": "2.*,<2.3"
- },
- "suggest": {
- "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
+ "psr/log": "1.0.*",
+ "symfony/class-loader": "*",
+ "zendframework/zend-cache": "<2.3",
+ "zendframework/zend-log": "<2.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.9-dev"
+ "dev-master": "3.8-dev"
}
},
"autoload": {
@@ -1183,7 +1293,7 @@
"homepage": "https://github.com/guzzle/guzzle/contributors"
}
],
- "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
+ "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
@@ -1195,7 +1305,188 @@
"web service"
],
"abandoned": "guzzlehttp/guzzle",
- "time": "2015-03-18T18:23:50+00:00"
+ "time": "2014-01-28T22:29:15+00:00"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699",
+ "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/promises": "^1.0",
+ "guzzlehttp/psr7": "^1.4",
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.0 || ^5.0",
+ "psr/log": "^1.0"
+ },
+ "suggest": {
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.2-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2017-06-22T18:50:49+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "v1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "time": "2016-12-20T10:07:11+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
+ "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Schultze",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "time": "2017-03-20T17:10:46+00:00"
},
{
"name": "ircmaxell/password-compat",
@@ -1241,16 +1532,16 @@
},
{
"name": "justinrainbow/json-schema",
- "version": "5.2.1",
+ "version": "5.2.4",
"source": {
"type": "git",
"url": "https://github.com/justinrainbow/json-schema.git",
- "reference": "429be236f296ca249d61c65649cdf2652f4a5e80"
+ "reference": "7ccb0e67ea8ace0f84c40900ca3c8a234467628c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/429be236f296ca249d61c65649cdf2652f4a5e80",
- "reference": "429be236f296ca249d61c65649cdf2652f4a5e80",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/7ccb0e67ea8ace0f84c40900ca3c8a234467628c",
+ "reference": "7ccb0e67ea8ace0f84c40900ca3c8a234467628c",
"shasum": ""
},
"require": {
@@ -1259,7 +1550,6 @@
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.1",
"json-schema/json-schema-test-suite": "1.2.0",
- "phpdocumentor/phpdocumentor": "^2.7",
"phpunit/phpunit": "^4.8.22"
},
"bin": [
@@ -1304,7 +1594,7 @@
"json",
"schema"
],
- "time": "2017-05-16T21:06:09+00:00"
+ "time": "2017-10-04T20:57:36+00:00"
},
{
"name": "knplabs/github-api",
@@ -1901,6 +2191,172 @@
],
"time": "2015-08-09T04:28:19+00:00"
},
+ {
+ "name": "php-http/guzzle6-adapter",
+ "version": "v1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-http/guzzle6-adapter.git",
+ "reference": "a56941f9dc6110409cfcddc91546ee97039277ab"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/a56941f9dc6110409cfcddc91546ee97039277ab",
+ "reference": "a56941f9dc6110409cfcddc91546ee97039277ab",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^6.0",
+ "php": ">=5.5.0",
+ "php-http/httplug": "^1.0"
+ },
+ "provide": {
+ "php-http/async-client-implementation": "1.0",
+ "php-http/client-implementation": "1.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "php-http/adapter-integration-tests": "^0.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Http\\Adapter\\Guzzle6\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com"
+ },
+ {
+ "name": "David de Boer",
+ "email": "david@ddeboer.nl"
+ }
+ ],
+ "description": "Guzzle 6 HTTP Adapter",
+ "homepage": "http://httplug.io",
+ "keywords": [
+ "Guzzle",
+ "http"
+ ],
+ "time": "2016-05-10T06:13:32+00:00"
+ },
+ {
+ "name": "php-http/httplug",
+ "version": "v1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-http/httplug.git",
+ "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-http/httplug/zipball/1c6381726c18579c4ca2ef1ec1498fdae8bdf018",
+ "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4",
+ "php-http/promise": "^1.0",
+ "psr/http-message": "^1.0"
+ },
+ "require-dev": {
+ "henrikbjorn/phpspec-code-coverage": "^1.0",
+ "phpspec/phpspec": "^2.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Eric GELOEN",
+ "email": "geloen.eric@gmail.com"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com"
+ }
+ ],
+ "description": "HTTPlug, the HTTP client abstraction for PHP",
+ "homepage": "http://httplug.io",
+ "keywords": [
+ "client",
+ "http"
+ ],
+ "time": "2016-08-31T08:30:17+00:00"
+ },
+ {
+ "name": "php-http/promise",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-http/promise.git",
+ "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-http/promise/zipball/dc494cdc9d7160b9a09bd5573272195242ce7980",
+ "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980",
+ "shasum": ""
+ },
+ "require-dev": {
+ "henrikbjorn/phpspec-code-coverage": "^1.0",
+ "phpspec/phpspec": "^2.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Http\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com"
+ },
+ {
+ "name": "Joel Wurtz",
+ "email": "joel.wurtz@gmail.com"
+ }
+ ],
+ "description": "Promise used for asynchronous HTTP requests",
+ "homepage": "http://httplug.io",
+ "keywords": [
+ "promise"
+ ],
+ "time": "2016-01-26T13:27:02+00:00"
+ },
{
"name": "pimple/pimple",
"version": "v1.0.2",
@@ -1947,6 +2403,56 @@
],
"time": "2013-03-08T08:21:40+00:00"
},
+ {
+ "name": "psr/http-message",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2016-08-06T14:39:51+00:00"
+ },
{
"name": "psr/log",
"version": "1.0.2",
@@ -2194,16 +2700,16 @@
},
{
"name": "symfony/config",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "0b8541d18507d10204a08384640ff6df3c739ebe"
+ "reference": "1dbeaa8e2db4b29159265867efff075ad961558c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/0b8541d18507d10204a08384640ff6df3c739ebe",
- "reference": "0b8541d18507d10204a08384640ff6df3c739ebe",
+ "url": "https://api.github.com/repos/symfony/config/zipball/1dbeaa8e2db4b29159265867efff075ad961558c",
+ "reference": "1dbeaa8e2db4b29159265867efff075ad961558c",
"shasum": ""
},
"require": {
@@ -2246,20 +2752,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2017-04-12T14:07:15+00:00"
+ "time": "2017-10-04T18:56:36+00:00"
},
{
"name": "symfony/console",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "c0807a2ca978e64d8945d373a9221a5c35d1a253"
+ "reference": "f81549d2c5fdee8d711c9ab3c7e7362353ea5853"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/c0807a2ca978e64d8945d373a9221a5c35d1a253",
- "reference": "c0807a2ca978e64d8945d373a9221a5c35d1a253",
+ "url": "https://api.github.com/repos/symfony/console/zipball/f81549d2c5fdee8d711c9ab3c7e7362353ea5853",
+ "reference": "f81549d2c5fdee8d711c9ab3c7e7362353ea5853",
"shasum": ""
},
"require": {
@@ -2307,20 +2813,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2017-08-27T14:29:03+00:00"
+ "time": "2017-10-01T21:00:16+00:00"
},
{
"name": "symfony/debug",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "efc9656dcb227e1459905d5aa51e43dfec76e752"
+ "reference": "eaaec993ca5e8067e204b2ee653cdd142961f33e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/efc9656dcb227e1459905d5aa51e43dfec76e752",
- "reference": "efc9656dcb227e1459905d5aa51e43dfec76e752",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/eaaec993ca5e8067e204b2ee653cdd142961f33e",
+ "reference": "eaaec993ca5e8067e204b2ee653cdd142961f33e",
"shasum": ""
},
"require": {
@@ -2364,20 +2870,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2017-08-27T14:29:03+00:00"
+ "time": "2017-10-01T21:00:16+00:00"
},
{
"name": "symfony/dependency-injection",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "fbeea992f0d30e3c400694c85f60c9bfd10454a3"
+ "reference": "2562562610dbdabbb98c6ceb60459a351811c734"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fbeea992f0d30e3c400694c85f60c9bfd10454a3",
- "reference": "fbeea992f0d30e3c400694c85f60c9bfd10454a3",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2562562610dbdabbb98c6ceb60459a351811c734",
+ "reference": "2562562610dbdabbb98c6ceb60459a351811c734",
"shasum": ""
},
"require": {
@@ -2427,31 +2933,31 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2017-08-10T14:42:21+00:00"
+ "time": "2017-10-02T07:17:52+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v2.8.27",
+ "version": "v3.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d"
+ "reference": "54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1377400fd641d7d1935981546aaef780ecd5bf6d",
- "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00",
+ "reference": "54da3ff63dec3c9c0e32ec3f95a7d94ef64baa00",
"shasum": ""
},
"require": {
- "php": ">=5.3.9"
+ "php": ">=5.5.9"
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/config": "^2.0.5|~3.0.0",
- "symfony/dependency-injection": "~2.6|~3.0.0",
- "symfony/expression-language": "~2.6|~3.0.0",
- "symfony/stopwatch": "~2.3|~3.0.0"
+ "symfony/config": "~2.8|~3.0",
+ "symfony/dependency-injection": "~2.8|~3.0",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0"
},
"suggest": {
"symfony/dependency-injection": "",
@@ -2460,7 +2966,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.8-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -2487,20 +2993,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2017-06-02T07:47:27+00:00"
+ "time": "2016-07-19T10:44:15+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "714b1036010c354ae2b25d7f9ca27e14e265e9f2"
+ "reference": "5e3af878f144089faddd4060a48cadae4fc44dee"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/714b1036010c354ae2b25d7f9ca27e14e265e9f2",
- "reference": "714b1036010c354ae2b25d7f9ca27e14e265e9f2",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/5e3af878f144089faddd4060a48cadae4fc44dee",
+ "reference": "5e3af878f144089faddd4060a48cadae4fc44dee",
"shasum": ""
},
"require": {
@@ -2536,20 +3042,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2017-07-11T07:12:11+00:00"
+ "time": "2017-10-02T08:46:46+00:00"
},
{
"name": "symfony/finder",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad"
+ "reference": "a945724b201f74d543e356f6059c930bb8d10c92"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/4f4e84811004e065a3bb5ceeb1d9aa592630f9ad",
- "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/a945724b201f74d543e356f6059c930bb8d10c92",
+ "reference": "a945724b201f74d543e356f6059c930bb8d10c92",
"shasum": ""
},
"require": {
@@ -2585,7 +3091,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01T20:52:29+00:00"
+ "time": "2017-10-01T21:00:16+00:00"
},
{
"name": "symfony/http-foundation",
@@ -2642,16 +3148,16 @@
},
{
"name": "symfony/http-kernel",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "b07102898dcba281d8e91d24ea43872f897d6203"
+ "reference": "d912b76d7db324f7650da9d1132be78c5f7ceb93"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b07102898dcba281d8e91d24ea43872f897d6203",
- "reference": "b07102898dcba281d8e91d24ea43872f897d6203",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d912b76d7db324f7650da9d1132be78c5f7ceb93",
+ "reference": "d912b76d7db324f7650da9d1132be78c5f7ceb93",
"shasum": ""
},
"require": {
@@ -2721,7 +3227,7 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
- "time": "2017-08-28T19:21:40+00:00"
+ "time": "2017-10-05T23:24:02+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@@ -2784,16 +3290,16 @@
},
{
"name": "symfony/process",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8"
+ "reference": "26c9fb02bf06bd6b90f661a5bd17e510810d0176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8",
- "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8",
+ "url": "https://api.github.com/repos/symfony/process/zipball/26c9fb02bf06bd6b90f661a5bd17e510810d0176",
+ "reference": "26c9fb02bf06bd6b90f661a5bd17e510810d0176",
"shasum": ""
},
"require": {
@@ -2829,20 +3335,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2017-07-03T08:04:30+00:00"
+ "time": "2017-10-01T21:00:16+00:00"
},
{
"name": "symfony/templating",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/templating.git",
- "reference": "3867ab005281fd8b32d68f47c0caaad017c26f52"
+ "reference": "ab3764461e860ce4ff16a509ecd93c44c1f5b0b1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/templating/zipball/3867ab005281fd8b32d68f47c0caaad017c26f52",
- "reference": "3867ab005281fd8b32d68f47c0caaad017c26f52",
+ "url": "https://api.github.com/repos/symfony/templating/zipball/ab3764461e860ce4ff16a509ecd93c44c1f5b0b1",
+ "reference": "ab3764461e860ce4ff16a509ecd93c44c1f5b0b1",
"shasum": ""
},
"require": {
@@ -2884,20 +3390,20 @@
],
"description": "Symfony Templating Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01T20:52:29+00:00"
+ "time": "2017-10-01T21:00:16+00:00"
},
{
"name": "symfony/yaml",
- "version": "v2.8.27",
+ "version": "v2.8.28",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5"
+ "reference": "842fb6df22180244b4c65935ce1a88d324e5ff9e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5",
- "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/842fb6df22180244b4c65935ce1a88d324e5ff9e",
+ "reference": "842fb6df22180244b4c65935ce1a88d324e5ff9e",
"shasum": ""
},
"require": {
@@ -2933,7 +3439,58 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01T20:52:29+00:00"
+ "time": "2017-10-05T14:38:30+00:00"
+ },
+ {
+ "name": "twbs/bootstrap",
+ "version": "v3.3.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twbs/bootstrap.git",
+ "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twbs/bootstrap/zipball/0b9c4a4007c44201dce9a6cc1a38407005c26c86",
+ "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86",
+ "shasum": ""
+ },
+ "replace": {
+ "twitter/bootstrap": "self.version"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jacob Thornton",
+ "email": "jacobthornton@gmail.com"
+ },
+ {
+ "name": "Mark Otto",
+ "email": "markdotto@gmail.com"
+ }
+ ],
+ "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
+ "homepage": "http://getbootstrap.com",
+ "keywords": [
+ "JS",
+ "css",
+ "framework",
+ "front-end",
+ "less",
+ "mobile-first",
+ "responsive",
+ "web"
+ ],
+ "time": "2016-07-25T15:51:55+00:00"
},
{
"name": "twig/twig",
@@ -3494,5 +4051,8 @@
"ext-pcntl": "*",
"ext-posix": "*"
},
- "platform-dev": []
+ "platform-dev": [],
+ "platform-overrides": {
+ "php": "5.6"
+ }
}
diff --git a/config.yml.dist b/config.yml.dist
index 22e26f0..7da6d02 100644
--- a/config.yml.dist
+++ b/config.yml.dist
@@ -12,22 +12,39 @@ doctrine:
database:
# Any Doctrine driver
driver: pdo_sqlite
-
+
# Options
path: %app.root_dir%/database.sqlite
# host: 127.0.0.1
# user: root
# password:
# dbname: packages
-
+
packages:
- site_name: 'Private Composer Repository'
- homepage: 'https://github.com/terramar-labs/packages'
+ # Defines the name used in the page titles and landing page.
+ name: 'Terramar Labs'
+
+ # If set, the homepage will be linked to from the landing page.
+ homepage: 'https://github.com/terramar-labs/packages'
+
+ # If set, the contact email is displayed on the landing page.
+ contact_email: 'contact@terramarlabs.com'
+
+ # Needs to be set to generate a dist archive
+ base_path: 'https://localhost'
+
+ # If set, will place a copy of every tagged package version in the web/dist folder
+ archive: true
+
+ # If set, username and password will be required when attempting to access
+ # Satis-generated files.
+ secure_satis: false
+
resque:
# Redis server host.
- host: 'unix:///tmp/redis.sock'
+ host: 'redis://redis-master'
# Format as either unix:///path/to/socket (note the 3 slashes) or redis://host
- #host: 'redis://127.0.0.1'
+ #host: 'unix:///var/run/redis.sock'
# If Redis is configured to require a password, you can pass it in the host:
#host: 'redis://ignored:password@host'
# Note that the username portion of the hostname is ignored and can be any value.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..deb3064
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,18 @@
+version: '2'
+services:
+ web:
+ image: webdevops/php-nginx:7.1
+ volumes:
+ - .:/app
+ - ./docker/nginx/vhost.common.d/vhost.common.conf:/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
+ links:
+ - redis
+ environment:
+ - WEB_DOCUMENT_ROOT=/app/web
+ ports:
+ - "127.0.0.1:80:80" # Access Packages in your browser at http://127.0.0.1:80
+ - "127.0.0.1:443:443" # Access Packages in your browser at https://127.0.0.1:443
+ redis:
+ image: redis:3.2
+ expose:
+ - "6379"
diff --git a/docker/nginx/vhost.common.d/vhost.common.conf b/docker/nginx/vhost.common.d/vhost.common.conf
new file mode 100644
index 0000000..1968c0b
--- /dev/null
+++ b/docker/nginx/vhost.common.d/vhost.common.conf
@@ -0,0 +1,3 @@
+location / {
+ try_files $uri $uri/ /index_dev.php$is_args$args;
+}
\ No newline at end of file
diff --git a/lib/Composer/LICENSE b/lib/Composer/LICENSE
new file mode 100644
index 0000000..f27399a
--- /dev/null
+++ b/lib/Composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/lib/Composer/NOTES.md b/lib/Composer/NOTES.md
new file mode 100644
index 0000000..20778e3
--- /dev/null
+++ b/lib/Composer/NOTES.md
@@ -0,0 +1,116 @@
+# Explain yourself!
+
+This "monkey patch" is necessary to allow Packages to use multiple different
+GitHub and GitLab auth tokens. Composer and Satis do not allow for this, and
+it is not yet clear on how or if it will be implemented upstream.
+
+> Yes, the warnings after `composer install` and `composer update` are expected.
+
+The changes to the GitHubDriver and GitLabDriver are very small, so
+maintaining these "forked" files shouldn't be that painful. The warning from
+composer sure is annoying though.
+
+
+# Details, please
+
+Packages 3.1 and earlier rely on `git` and having the user's environment
+configured. In practice, this means having a valid private SSH key on
+your server with access to every repository you need.
+
+With Packages 3.2, the github or gitlab auth token are loaded from their
+respective `RemoteConfiguration` and inserted into the repository options in
+the generated Satis configuration. This means that Packages no longer requires
+that the user running the Packages application to have a bunch of private keys
+different SSH keys configured, and adding a Remote no longer requires logging
+in to the server to add such a key.
+
+It boils down to adding handling for two new keys in a repository:
+`github-token` and `gitlab-token`.
+
+```json
+{
+ "repositories": [
+ {
+ "type": "vcs",
+ "url": "git@github.com:somereally/neatproject.git",
+ "github-token": "123abcdef456",
+ },
+ {
+ "type": "vcs",
+ "url": "git@gitlab.example.com:another/awesomeproject.git",
+ "gitlab-token": "xyz123",
+ }
+ ]
+}
+```
+
+If these values exist, the modified `GitHubDriver` or `GitLabDriver` sets the
+token on the Composer IO so the respective API can be used. And since this
+is done for every repository, multiple different users on the same GitLab
+instance can now easily share a Packages instance.
+
+Three lines in each file were all that were necessary to accomplish the task:
+
+```php
+repoConfig['github-token'])) {
+ $this->io->setAuthentication("github.com", $this->repoConfig['github-token']);
+ }
+
+ // ...
+ }
+
+ // ...
+}
+```
+
+```php
+repoConfig['gitlab-token'])) {
+ $this->io->setAuthentication($this->originUrl, $this->repoConfig['gitlab-token'], 'private-token');
+ }
+
+ // ...
+ }
+
+ // ...
+}
+```
+
+The final piece of the puzzle is setting up a new PSR-0 root in `composer.json`.
+
+```json
+ // ...
+ "autoload": {
+ // ...
+ "psr-0": {
+ "Composer\\": "lib/Composer/"
+ }
+ },
+ // ...
+}
+```
\ No newline at end of file
diff --git a/lib/Composer/Repository/Vcs/GitHubDriver.php b/lib/Composer/Repository/Vcs/GitHubDriver.php
new file mode 100644
index 0000000..88d1576
--- /dev/null
+++ b/lib/Composer/Repository/Vcs/GitHubDriver.php
@@ -0,0 +1,531 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Repository\Vcs;
+
+use Composer\Config;
+use Composer\Downloader\TransportException;
+use Composer\Json\JsonFile;
+use Composer\Cache;
+use Composer\IO\IOInterface;
+use Composer\Util\GitHub;
+
+/**
+ * @author Jordi Boggiano
+ */
+class GitHubDriver extends VcsDriver
+{
+ protected $cache;
+ protected $owner;
+ protected $repository;
+ protected $tags;
+ protected $branches;
+ protected $rootIdentifier;
+ protected $repoData;
+ protected $hasIssues;
+ protected $infoCache = array();
+ protected $isPrivate = false;
+
+ /**
+ * Git Driver
+ *
+ * @var GitDriver
+ */
+ protected $gitDriver;
+
+ /**
+ * {@inheritDoc}
+ */
+ public function initialize()
+ {
+ preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
+ $this->owner = $match[3];
+ $this->repository = $match[4];
+ $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
+ if ($this->originUrl === 'www.github.com') {
+ $this->originUrl = 'github.com';
+ }
+ $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
+
+ if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
+ $this->setupGitDriver($this->url);
+
+ return;
+ }
+
+ $this->fetchRootIdentifier();
+ }
+
+ public function getRepositoryUrl()
+ {
+ return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getRootIdentifier()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getRootIdentifier();
+ }
+
+ return $this->rootIdentifier;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getUrl()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getUrl();
+ }
+
+ return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getApiUrl()
+ {
+ if ('github.com' === $this->originUrl) {
+ $apiUrl = 'api.github.com';
+ } else {
+ $apiUrl = $this->originUrl . '/api/v3';
+ }
+
+ return 'https://' . $apiUrl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getSource($identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getSource($identifier);
+ }
+ if ($this->isPrivate) {
+ // Private GitHub repositories should be accessed using the
+ // SSH version of the URL.
+ $url = $this->generateSshUrl();
+ } else {
+ $url = $this->getUrl();
+ }
+
+ return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getDist($identifier)
+ {
+ $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
+
+ return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getComposerInformation($identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getComposerInformation($identifier);
+ }
+
+ if (!isset($this->infoCache[$identifier])) {
+ if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
+ return $this->infoCache[$identifier] = JsonFile::parseJson($res);
+ }
+
+ $composer = $this->getBaseComposerInformation($identifier);
+ if ($composer) {
+
+ // specials for github
+ if (!isset($composer['support']['source'])) {
+ $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
+ $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
+ }
+ if (!isset($composer['support']['issues']) && $this->hasIssues) {
+ $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
+ }
+ }
+
+ if ($this->shouldCache($identifier)) {
+ $this->cache->write($identifier, json_encode($composer));
+ }
+
+ $this->infoCache[$identifier] = $composer;
+ }
+
+ return $this->infoCache[$identifier];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFileContent($file, $identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getFileContent($file, $identifier);
+ }
+
+ $notFoundRetries = 2;
+ while ($notFoundRetries) {
+ try {
+ $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
+ $resource = JsonFile::parseJson($this->getContents($resource));
+ if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
+ throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
+ }
+
+ return $content;
+ } catch (TransportException $e) {
+ if (404 !== $e->getCode()) {
+ throw $e;
+ }
+
+ // TODO should be removed when possible
+ // retry fetching if github returns a 404 since they happen randomly
+ $notFoundRetries--;
+
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getChangeDate($identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getChangeDate($identifier);
+ }
+
+ $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
+ $commit = JsonFile::parseJson($this->getContents($resource), $resource);
+
+ return new \DateTime($commit['commit']['committer']['date']);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getTags()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getTags();
+ }
+ if (null === $this->tags) {
+ $this->tags = array();
+ $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
+
+ do {
+ $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
+ foreach ($tagsData as $tag) {
+ $this->tags[$tag['name']] = $tag['commit']['sha'];
+ }
+
+ $resource = $this->getNextPage();
+ } while ($resource);
+ }
+
+ return $this->tags;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getBranches()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getBranches();
+ }
+ if (null === $this->branches) {
+ $this->branches = array();
+ $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
+
+ $branchBlacklist = array('gh-pages');
+
+ do {
+ $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
+ foreach ($branchData as $branch) {
+ $name = substr($branch['ref'], 11);
+ if (!in_array($name, $branchBlacklist)) {
+ $this->branches[$name] = $branch['object']['sha'];
+ }
+ }
+
+ $resource = $this->getNextPage();
+ } while ($resource);
+ }
+
+ return $this->branches;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public static function supports(IOInterface $io, Config $config, $url, $deep = false)
+ {
+ if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
+ return false;
+ }
+
+ $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
+ if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
+ return false;
+ }
+
+ if (!extension_loaded('openssl')) {
+ $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Gives back the loaded /repos// result
+ *
+ * @return array|null
+ */
+ public function getRepoData()
+ {
+ $this->fetchRootIdentifier();
+
+ return $this->repoData;
+ }
+
+ /**
+ * Generate an SSH URL
+ *
+ * @return string
+ */
+ protected function generateSshUrl()
+ {
+ return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getContents($url, $fetchingRepoData = false)
+ {
+ if (isset($this->repoConfig['github-token'])) {
+ $this->io->setAuthentication("github.com", $this->repoConfig['github-token']);
+ }
+
+ try {
+ return parent::getContents($url);
+ } catch (TransportException $e) {
+ $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
+
+ switch ($e->getCode()) {
+ case 401:
+ case 404:
+ // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404
+ if (!$fetchingRepoData) {
+ throw $e;
+ }
+
+ if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
+ return parent::getContents($url);
+ }
+
+ if (!$this->io->isInteractive()) {
+ return $this->attemptCloneFallback();
+ }
+
+ $scopesIssued = array();
+ $scopesNeeded = array();
+ if ($headers = $e->getHeaders()) {
+ if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
+ $scopesIssued = explode(' ', $scopes);
+ }
+ if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
+ $scopesNeeded = explode(' ', $scopes);
+ }
+ }
+ $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
+ if (!$headers || count($scopesFailed)) {
+ $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata ('.$this->url.' )');
+ }
+
+ return parent::getContents($url);
+
+ case 403:
+ if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
+ return parent::getContents($url);
+ }
+
+ if (!$this->io->isInteractive() && $fetchingRepoData) {
+ return $this->attemptCloneFallback();
+ }
+
+ $rateLimited = false;
+ foreach ($e->getHeaders() as $header) {
+ if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
+ $rateLimited = true;
+ }
+ }
+
+ if (!$this->io->hasAuthentication($this->originUrl)) {
+ if (!$this->io->isInteractive()) {
+ $this->io->writeError('GitHub API limit exhausted. Failed to get metadata for the '.$this->url.' repository, try running in interactive mode so that you can enter your GitHub credentials to increase the API limit ');
+ throw $e;
+ }
+
+ $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit ('.$this->url.' )');
+
+ return parent::getContents($url);
+ }
+
+ if ($rateLimited) {
+ $rateLimit = $this->getRateLimit($e->getHeaders());
+ $this->io->writeError(sprintf(
+ 'GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests ',
+ $rateLimit['limit'],
+ $rateLimit['reset']
+ ));
+ }
+
+ throw $e;
+
+ default:
+ throw $e;
+ }
+ } finally {
+
+ }
+ }
+
+ /**
+ * Extract ratelimit from response.
+ *
+ * @param array $headers Headers from Composer\Downloader\TransportException.
+ *
+ * @return array Associative array with the keys limit and reset.
+ */
+ protected function getRateLimit(array $headers)
+ {
+ $rateLimit = array(
+ 'limit' => '?',
+ 'reset' => '?',
+ );
+
+ foreach ($headers as $header) {
+ $header = trim($header);
+ if (false === strpos($header, 'X-RateLimit-')) {
+ continue;
+ }
+ list($type, $value) = explode(':', $header, 2);
+ switch ($type) {
+ case 'X-RateLimit-Limit':
+ $rateLimit['limit'] = (int) trim($value);
+ break;
+ case 'X-RateLimit-Reset':
+ $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
+ break;
+ }
+ }
+
+ return $rateLimit;
+ }
+
+ /**
+ * Fetch root identifier from GitHub
+ *
+ * @throws TransportException
+ */
+ protected function fetchRootIdentifier()
+ {
+ if ($this->repoData) {
+ return;
+ }
+
+ $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
+
+ $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
+ if (null === $this->repoData && null !== $this->gitDriver) {
+ return;
+ }
+
+ $this->owner = $this->repoData['owner']['login'];
+ $this->repository = $this->repoData['name'];
+
+ $this->isPrivate = !empty($this->repoData['private']);
+ if (isset($this->repoData['default_branch'])) {
+ $this->rootIdentifier = $this->repoData['default_branch'];
+ } elseif (isset($this->repoData['master_branch'])) {
+ $this->rootIdentifier = $this->repoData['master_branch'];
+ } else {
+ $this->rootIdentifier = 'master';
+ }
+ $this->hasIssues = !empty($this->repoData['has_issues']);
+ }
+
+ protected function attemptCloneFallback()
+ {
+ $this->isPrivate = true;
+
+ try {
+ // If this repository may be private (hard to say for sure,
+ // GitHub returns 404 for private repositories) and we
+ // cannot ask for authentication credentials (because we
+ // are not interactive) then we fallback to GitDriver.
+ $this->setupGitDriver($this->generateSshUrl());
+
+ return;
+ } catch (\RuntimeException $e) {
+ $this->gitDriver = null;
+
+ $this->io->writeError('Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your GitHub credentials ');
+ throw $e;
+ }
+ }
+
+ protected function setupGitDriver($url)
+ {
+ $this->gitDriver = new GitDriver(
+ array('url' => $url),
+ $this->io,
+ $this->config,
+ $this->process,
+ $this->remoteFilesystem
+ );
+ $this->gitDriver->initialize();
+ }
+
+ protected function getNextPage()
+ {
+ $headers = $this->remoteFilesystem->getLastHeaders();
+ foreach ($headers as $header) {
+ if (substr($header, 0, 5) === 'Link:') {
+ $links = explode(',', substr($header, 5));
+ foreach ($links as $link) {
+ if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
+ return $match[1];
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/Composer/Repository/Vcs/GitLabDriver.php b/lib/Composer/Repository/Vcs/GitLabDriver.php
new file mode 100644
index 0000000..f74900d
--- /dev/null
+++ b/lib/Composer/Repository/Vcs/GitLabDriver.php
@@ -0,0 +1,442 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Repository\Vcs;
+
+use Composer\Config;
+use Composer\Cache;
+use Composer\IO\IOInterface;
+use Composer\Json\JsonFile;
+use Composer\Downloader\TransportException;
+use Composer\Util\RemoteFilesystem;
+use Composer\Util\GitLab;
+
+/**
+ * Driver for GitLab API, use the Git driver for local checkouts.
+ *
+ * @author Henrik Bjørnskov
+ * @author Jérôme Tamarelle
+ */
+class GitLabDriver extends VcsDriver
+{
+ private $scheme;
+ private $owner;
+ private $repository;
+
+ /**
+ * @var array Project data returned by GitLab API
+ */
+ private $project;
+
+ /**
+ * @var array Keeps commits returned by GitLab API
+ */
+ private $commits = array();
+
+ /**
+ * @var array List of tag => reference
+ */
+ private $tags;
+
+ /**
+ * @var array List of branch => reference
+ */
+ private $branches;
+
+ /**
+ * Git Driver
+ *
+ * @var GitDriver
+ */
+ protected $gitDriver;
+
+ /**
+ * Defaults to true unless we can make sure it is public
+ *
+ * @var bool defines whether the repo is private or not
+ */
+ private $isPrivate = true;
+
+ const URL_REGEX = '#^(?:(?Phttps?)://(?P.+?)/|git@(?P[^:]+):)(?P[^/]+)/(?P[^/]+?)(?:\.git|/)?$#';
+
+ /**
+ * Extracts information from the repository url.
+ *
+ * SSH urls use https by default. Set "secure-http": false on the repository config to use http instead.
+ *
+ * {@inheritDoc}
+ */
+ public function initialize()
+ {
+ if (!preg_match(self::URL_REGEX, $this->url, $match)) {
+ throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
+ }
+
+ $this->scheme = !empty($match['scheme']) ? $match['scheme'] : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https');
+ $this->originUrl = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
+ $this->owner = $match['owner'];
+ $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
+
+ $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
+
+ $this->fetchProject();
+ }
+
+ /**
+ * Updates the RemoteFilesystem instance.
+ * Mainly useful for tests.
+ *
+ * @internal
+ */
+ public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
+ {
+ $this->remoteFilesystem = $remoteFilesystem;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFileContent($file, $identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getFileContent($file, $identifier);
+ }
+
+ // Convert the root identifier to a cachable commit id
+ if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
+ $branches = $this->getBranches();
+ if (isset($branches[$identifier])) {
+ $identifier = $branches[$identifier];
+ }
+ }
+
+ $resource = $this->getApiUrl().'/repository/blobs/'.$identifier.'?filepath=' . $file;
+
+ try {
+ $content = $this->getContents($resource);
+ } catch (TransportException $e) {
+ if ($e->getCode() !== 404) {
+ throw $e;
+ }
+
+ return null;
+ }
+
+ return $content;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getChangeDate($identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getChangeDate($identifier);
+ }
+
+ if (isset($this->commits[$identifier])) {
+ return new \DateTime($this->commits[$identifier]['committed_date']);
+ }
+
+ return new \DateTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getRepositoryUrl()
+ {
+ return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getUrl()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getUrl();
+ }
+
+ return $this->project['web_url'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getDist($identifier)
+ {
+ $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
+
+ return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getSource($identifier)
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getSource($identifier);
+ }
+
+ return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getRootIdentifier()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getRootIdentifier();
+ }
+
+ return $this->project['default_branch'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getBranches()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getBranches();
+ }
+
+ if (!$this->branches) {
+ $this->branches = $this->getReferences('branches');
+ }
+
+ return $this->branches;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getTags()
+ {
+ if ($this->gitDriver) {
+ return $this->gitDriver->getTags();
+ }
+
+ if (!$this->tags) {
+ $this->tags = $this->getReferences('tags');
+ }
+
+ return $this->tags;
+ }
+
+ /**
+ * @return string Base URL for GitLab API v3
+ */
+ public function getApiUrl()
+ {
+ return $this->scheme.'://'.$this->originUrl.'/api/v3/projects/'.$this->urlEncodeAll($this->owner).'%2F'.$this->urlEncodeAll($this->repository);
+ }
+
+ /**
+ * Urlencode all non alphanumeric characters. rawurlencode() can not be used as it does not encode `.`
+ *
+ * @param string $string
+ * @return string
+ */
+ private function urlEncodeAll($string)
+ {
+ $encoded = '';
+ for ($i = 0; isset($string[$i]); $i++) {
+ $character = $string[$i];
+ if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
+ $character = '%' . sprintf('%02X', ord($character));
+ }
+ $encoded .= $character;
+ }
+
+ return $encoded;
+ }
+
+ /**
+ * @param string $type
+ *
+ * @return string[] where keys are named references like tags or branches and the value a sha
+ */
+ protected function getReferences($type)
+ {
+ $resource = $this->getApiUrl().'/repository/'.$type;
+
+ $data = JsonFile::parseJson($this->getContents($resource), $resource);
+
+ $references = array();
+
+ foreach ($data as $datum) {
+ $references[$datum['name']] = $datum['commit']['id'];
+
+ // Keep the last commit date of a reference to avoid
+ // unnecessary API call when retrieving the composer file.
+ $this->commits[$datum['commit']['id']] = $datum['commit'];
+ }
+
+ return $references;
+ }
+
+ protected function fetchProject()
+ {
+ // we need to fetch the default branch from the api
+ $resource = $this->getApiUrl();
+ $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
+ $this->isPrivate = !$this->project['public'];
+ }
+
+ protected function attemptCloneFallback()
+ {
+ try {
+ if ($this->isPrivate === false) {
+ $url = $this->generatePublicUrl();
+ } else {
+ $url = $this->generateSshUrl();
+ }
+
+ // If this repository may be private and we
+ // cannot ask for authentication credentials (because we
+ // are not interactive) then we fallback to GitDriver.
+ $this->setupGitDriver($url);
+
+ return;
+ } catch (\RuntimeException $e) {
+ $this->gitDriver = null;
+
+ $this->io->writeError('Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials ');
+ throw $e;
+ }
+ }
+
+ /**
+ * Generate an SSH URL
+ *
+ * @return string
+ */
+ protected function generateSshUrl()
+ {
+ return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
+ }
+
+ protected function generatePublicUrl()
+ {
+ return $this->scheme . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
+ }
+
+ protected function setupGitDriver($url)
+ {
+ $this->gitDriver = new GitDriver(
+ array('url' => $url),
+ $this->io,
+ $this->config,
+ $this->process,
+ $this->remoteFilesystem
+ );
+ $this->gitDriver->initialize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getContents($url, $fetchingRepoData = false)
+ {
+ if (isset($this->repoConfig['gitlab-token'])) {
+ $this->io->setAuthentication($this->originUrl, $this->repoConfig['gitlab-token'], 'private-token');
+ }
+
+ try {
+ $res = parent::getContents($url);
+
+ if ($fetchingRepoData) {
+ $json = JsonFile::parseJson($res, $url);
+
+ // force auth as the unauthenticated version of the API is broken
+ if (!isset($json['default_branch'])) {
+ if (!empty($json['id'])) {
+ $this->isPrivate = false;
+ }
+
+ throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
+ }
+ }
+
+ return $res;
+ } catch (TransportException $e) {
+ $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
+
+ switch ($e->getCode()) {
+ case 401:
+ case 404:
+ // try to authorize only if we are fetching the main /repos/foo/bar data, otherwise it must be a real 404
+ if (!$fetchingRepoData) {
+ throw $e;
+ }
+
+ if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
+ return parent::getContents($url);
+ }
+
+ if (!$this->io->isInteractive()) {
+ return $this->attemptCloneFallback();
+ }
+ $this->io->writeError('Failed to download ' . $this->owner . '/' . $this->repository . ':' . $e->getMessage() . ' ');
+ $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata ('.$this->url.' )');
+
+ return parent::getContents($url);
+
+ case 403:
+ if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
+ return parent::getContents($url);
+ }
+
+ if (!$this->io->isInteractive() && $fetchingRepoData) {
+ return $this->attemptCloneFallback();
+ }
+
+ throw $e;
+
+ default:
+ throw $e;
+ }
+ }
+ }
+
+ /**
+ * Uses the config `gitlab-domains` to see if the driver supports the url for the
+ * repository given.
+ *
+ * {@inheritDoc}
+ */
+ public static function supports(IOInterface $io, Config $config, $url, $deep = false)
+ {
+ if (!preg_match(self::URL_REGEX, $url, $match)) {
+ return false;
+ }
+
+ $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
+ $originUrl = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
+
+ if (!in_array($originUrl, (array) $config->get('gitlab-domains'))) {
+ return false;
+ }
+
+ if ('https' === $scheme && !extension_loaded('openssl')) {
+ $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/satis/.gitkeep b/satis/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/src/Application.php b/src/Application.php
index 9408075..401f9ea 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -18,18 +18,18 @@
use Symfony\Component\Yaml\Yaml;
use Terramar\Packages\DependencyInjection\PackagesExtension;
use Terramar\Packages\Plugin\CloneProject\Plugin as CloneProjectPlugin;
+use Terramar\Packages\Plugin\GitHub\Plugin as GitHubPlugin;
use Terramar\Packages\Plugin\GitLab\Plugin as GitLabPlugin;
+use Terramar\Packages\Plugin\PluginInterface;
use Terramar\Packages\Plugin\Sami\Plugin as SamiPlugin;
use Terramar\Packages\Plugin\Satis\Plugin as SatisPlugin;
-use Terramar\Packages\Plugin\GitHub\Plugin as GitHubPlugin;
-use Terramar\Packages\Plugin\PluginInterface;
class Application extends BaseApplication
{
/**
* @var array|PluginInterface[]
*/
- private $plugins = array();
+ private $plugins = [];
/**
* Register default extensions.
@@ -40,32 +40,30 @@ protected function registerDefaultExtensions()
$this->registerDefaultPlugins();
- $config = Yaml::parse(file_get_contents($this->getRootDir().'/config.yml'));
- $security = isset($config['security']) ? $config['security'] : array();
- $doctrine = isset($config['doctrine']) ? $config['doctrine'] : array();
- $resque = isset($config['packages'])
- ? (isset($config['packages']['resque']) ? $config['packages']['resque'] : null)
- : null;
+ $config = Yaml::parse(file_get_contents($this->getRootDir() . '/config.yml'));
+ $security = isset($config['security']) ? $config['security'] : [];
+ $doctrine = isset($config['doctrine']) ? $config['doctrine'] : [];
+ $packages = isset($config['packages']) ? $config['packages'] : [];
+ if (!isset($packages['resque'])) {
+ $packages['resque'] = [];
+ }
- $this->appendExtension(new PackagesExtension($this->plugins, array(
- 'output_dir' => $this->getRootDir().'/web',
- 'resque' => $resque,
- )));
+ $this->appendExtension(new PackagesExtension($this->plugins, $packages));
$this->appendExtension(new DoctrineOrmExtension($doctrine));
$this->appendExtension(new SessionExtension());
$this->appendExtension(new TemplatingExtension());
$this->appendExtension(new TwigExtension());
- $this->appendExtension(new SecurityExtension(array(
- 'authenticator' => array(
- 'type' => 'username',
- 'username' => isset($security['username']) ? $security['username'] : null,
- 'password' => isset($security['password'])
- ? password_hash($security['password'], PASSWORD_DEFAULT)
- : null,
- ),
- 'firewall' => '^/manage',
- 'success_path' => '/manage',
- )));
+ $this->appendExtension(new SecurityExtension([
+ 'authenticator' => [
+ 'type' => 'username',
+ 'username' => isset($security['username']) ? $security['username'] : null,
+ 'password' => isset($security['password'])
+ ? password_hash($security['password'], PASSWORD_DEFAULT)
+ : null,
+ ],
+ 'firewall' => '^/manage',
+ 'success_path' => '/manage',
+ ]));
}
/**
diff --git a/src/Console/Application.php b/src/Console/Application.php
index d2b32ab..7b1f157 100644
--- a/src/Console/Application.php
+++ b/src/Console/Application.php
@@ -9,18 +9,20 @@
namespace Terramar\Packages\Console;
+use Composer\Composer;
+use Composer\Factory;
+use Composer\IO\ConsoleIO;
+use Composer\IO\IOInterface;
+use Composer\Util\ErrorHandler;
use Doctrine\ORM\Tools\Console\ConsoleRunner;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Helper\QuestionHelper;
-use Symfony\Component\DependencyInjection\ContainerAwareInterface;
-use Terramar\Packages\Application as AppKernel;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Composer\IO\ConsoleIO;
-use Composer\Factory;
-use Composer\Util\ErrorHandler;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Terramar\Packages\Application as AppKernel;
use Terramar\Packages\Version;
/**
@@ -28,7 +30,9 @@
*/
class Application extends BaseApplication
{
+ /** @var IOInterface */
protected $io;
+ /** @var Composer */
protected $composer;
/**
@@ -58,29 +62,12 @@ public function doRun(InputInterface $input, OutputInterface $output)
return parent::doRun($input, $output);
}
- /**
- * @return Composer
- */
- public function getComposer($required = true, $config = null)
- {
- if (null === $this->composer) {
- try {
- $this->composer = Factory::create($this->io, $config);
- } catch (\InvalidArgumentException $e) {
- $this->io->write($e->getMessage());
- exit(1);
- }
- }
-
- return $this->composer;
- }
-
/**
* Initializes all the composer commands.
*/
protected function registerCommands()
{
- $this->addCommands(array(
+ $this->addCommands([
// Resque Commands
new \Terramar\Packages\Console\Command\Worker\StartCommand(),
new \Terramar\Packages\Console\Command\Worker\ListCommand(),
@@ -117,7 +104,7 @@ protected function registerCommands()
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand(),
- ));
+ ]);
$registry = $this->app->get('packages.command_registry');
foreach ($registry->getCommands() as $commandClass) {
$this->add(new $commandClass());
@@ -144,6 +131,31 @@ public function add(Command $command)
return parent::add($command);
}
+ /**
+ * @return Composer
+ */
+ public function getComposer($required = true, $config = null)
+ {
+ if (null === $this->composer) {
+ try {
+ $this->composer = Factory::create($this->io, $config);
+ } catch (\InvalidArgumentException $e) {
+ $this->io->write($e->getMessage());
+ exit(1);
+ }
+ }
+
+ return $this->composer;
+ }
+
+ /**
+ * @return IOInterface
+ */
+ public function getIO()
+ {
+ return $this->io;
+ }
+
/**
* @return array
*/
diff --git a/src/Console/Command/Queue/ClearCommand.php b/src/Console/Command/Queue/ClearCommand.php
index 30936de..3b8d14c 100755
--- a/src/Console/Command/Queue/ClearCommand.php
+++ b/src/Console/Command/Queue/ClearCommand.php
@@ -35,7 +35,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
if ($jobs <= 0) {
$output->writeln(sprintf('Queue "%s" is empty', $queue));
} else {
- $output->writeln(sprintf('Removed %d %s from queue "%s"', $jobs, count($jobs) !== 1 ? 'jobs' : 'job', $queue));
+ $output->writeln(sprintf('Removed %d %s from queue "%s"', $jobs, count($jobs) !== 1 ? 'jobs' : 'job',
+ $queue));
}
$output->writeln('');
diff --git a/src/Console/Command/Worker/ListCommand.php b/src/Console/Command/Worker/ListCommand.php
index acb2e0b..b66ba8c 100644
--- a/src/Console/Command/Worker/ListCommand.php
+++ b/src/Console/Command/Worker/ListCommand.php
@@ -31,10 +31,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$workers = \Resque_Worker::all();
if (count($workers) <= 0) {
- $output->writeln(array(
+ $output->writeln([
'No workers running',
'',
- ));
+ ]);
return 0;
}
@@ -44,34 +44,34 @@ protected function execute(InputInterface $input, OutputInterface $output)
$queueFilter = false;
}
- $workerOutput = array();
+ $workerOutput = [];
$longestName = 0;
foreach ($workers as $worker) {
- $queues = ($worker->queues(true) ?: array('*'));
+ $queues = ($worker->queues(true) ?: ['*']);
if ($queueFilter) {
if (!in_array('*', $queues) && !in_array($queueFilter, $queues)) {
continue;
}
}
- $name = (string) $worker;
+ $name = (string)$worker;
$job = ($job = $worker->job())
- ? 'Processing '.json_encode($job)
+ ? 'Processing ' . json_encode($job)
: 'Waiting for job';
if (strlen($job) > 20) {
- $job = substr($job, 0, 20).'...';
+ $job = substr($job, 0, 20) . '...';
}
- $workerOutput[] = array($name, $job);
+ $workerOutput[] = [$name, $job];
if (($thisLength = strlen($name)) > $longestName) {
$longestName = $thisLength;
}
}
- $output->writeln(sprintf('%-'.$longestName."s\t%s", 'Worker ID', 'Current Job'));
- $loopFormat = '%-'.$longestName."s\t%s ";
+ $output->writeln(sprintf('%-' . $longestName . "s\t%s", 'Worker ID', 'Current Job'));
+ $loopFormat = '%-' . $longestName . "s\t%s ";
foreach ($workerOutput as $worker) {
$output->writeln(sprintf($loopFormat, $worker[0], $worker[1]));
}
diff --git a/src/Console/Command/Worker/StartCommand.php b/src/Console/Command/Worker/StartCommand.php
index 0ac9eb0..6516216 100755
--- a/src/Console/Command/Worker/StartCommand.php
+++ b/src/Console/Command/Worker/StartCommand.php
@@ -9,12 +9,12 @@
namespace Terramar\Packages\Console\Command\Worker;
-use Symfony\Component\Process\PhpExecutableFinder;
-use Symfony\Component\Process\Process;
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\Process\PhpExecutableFinder;
+use Symfony\Component\Process\Process;
use Terramar\Packages\Console\Command\ContainerAwareCommand;
use Terramar\Packages\Helper\ResqueHelper;
@@ -27,42 +27,43 @@ protected function configure()
->setDescription('Start a resque worker')
->addArgument('queues', InputArgument::OPTIONAL, 'Queue names (separate using comma)', '*')
->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'How many workers to fork', 1)
- ->addOption('interval', 'i', InputOption::VALUE_REQUIRED, 'How often to check for new jobs across the queues', 5)
+ ->addOption('interval', 'i', InputOption::VALUE_REQUIRED,
+ 'How often to check for new jobs across the queues', 5)
->addOption('foreground', 'f', InputOption::VALUE_NONE, 'Should the worker run in foreground')
- ->addOption('memory-limit', 'm', InputOption::VALUE_REQUIRED, 'Force cli memory_limit (expressed in Mbytes)')
- ;
+ ->addOption('memory-limit', 'm', InputOption::VALUE_REQUIRED,
+ 'Force cli memory_limit (expressed in Mbytes)');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
- $env = array(
- 'QUEUE' => $input->getArgument('queues'),
- 'VERBOSE' => $input->getOption('verbose'),
- 'COUNT' => $input->getOption('count'),
+ $env = [
+ 'QUEUE' => $input->getArgument('queues'),
+ 'VERBOSE' => $input->getOption('verbose'),
+ 'COUNT' => $input->getOption('count'),
'INTERVAL' => $input->getOption('interval'),
- 'PREFIX' => 'resque:',
- );
+ 'PREFIX' => 'resque:',
+ ];
$resqueConfig = ResqueHelper::autoConfigure($this->container);
$env['REDIS_BACKEND'] = $resqueConfig['backend'];
$env['REDIS_BACKEND_DB'] = $resqueConfig['database'];
$opt = '';
- if (0 !== $m = (int) $input->getOption('memory-limit')) {
+ if (0 !== $m = (int)$input->getOption('memory-limit')) {
$opt = sprintf('-d memory_limit=%dM', $m);
}
- $workerCommand = strtr('%bin% %opt% %dir%/bin/resque', array(
+ $workerCommand = strtr('%bin% %opt% %dir%/bin/resque', [
'%bin%' => $this->getPhpBinary(),
'%opt%' => $opt,
'%dir%' => $this->container->getParameter('app.root_dir'),
- ));
+ ]);
if (!$input->getOption('foreground')) {
- $workerCommand = strtr('nohup %cmd% > %logs_dir%/resque.log 2>&1 & echo $!', array(
- '%cmd%' => $workerCommand,
+ $workerCommand = strtr('nohup %cmd% > %logs_dir%/resque.log 2>&1 & echo $!', [
+ '%cmd%' => $workerCommand,
'%logs_dir%' => $this->container->getParameter('app.log_dir'),
- ));
+ ]);
}
// In windows: When you pass an environment to CMD it replaces the old environment
@@ -70,7 +71,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// this is a workaround where we add the vars to the existing environment.
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
foreach ($env as $key => $value) {
- putenv($key.'='.$value);
+ putenv($key . '=' . $value);
}
$env = null;
}
diff --git a/src/Console/Command/Worker/StopCommand.php b/src/Console/Command/Worker/StopCommand.php
index 5c67160..278e9a7 100755
--- a/src/Console/Command/Worker/StopCommand.php
+++ b/src/Console/Command/Worker/StopCommand.php
@@ -9,11 +9,11 @@
namespace Terramar\Packages\Console\Command\Worker;
-use Terramar\Packages\Console\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 Terramar\Packages\Console\Command\ContainerAwareCommand;
use Terramar\Packages\Helper\ResqueHelper;
class StopCommand extends ContainerAwareCommand
@@ -43,14 +43,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}
- $workers = $worker ? array($worker) : array();
+ $workers = $worker ? [$worker] : [];
}
if (count($workers) <= 0) {
- $output->writeln(array(
- 'No workers running',
- '',
- ));
+ $output->writeln([
+ 'No workers running',
+ '',
+ ]);
return;
}
@@ -58,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$signal = $input->getOption('force') ? SIGTERM : SIGQUIT;
foreach ($workers as $worker) {
$output->writeln(sprintf('%s %s...', $signal === SIGTERM ? 'Force stopping' : 'Stopping', $worker));
- list(, $pid) = explode(':', (string) $worker);
+ list(, $pid) = explode(':', (string)$worker);
posix_kill($pid, $signal);
}
diff --git a/src/Console/CommandRegistry.php b/src/Console/CommandRegistry.php
index b62ff1f..c5d9045 100644
--- a/src/Console/CommandRegistry.php
+++ b/src/Console/CommandRegistry.php
@@ -11,7 +11,7 @@
class CommandRegistry
{
- private $commands = array();
+ private $commands = [];
public function addCommand($className)
{
diff --git a/src/Controller/ContainerAwareController.php b/src/Controller/ContainerAwareController.php
index 2951815..c7bcee4 100644
--- a/src/Controller/ContainerAwareController.php
+++ b/src/Controller/ContainerAwareController.php
@@ -14,16 +14,16 @@
abstract class ContainerAwareController implements ContainerAwareInterface
{
- /**
- * @var ContainerInterface|null
- */
- protected $container;
+ /**
+ * @var ContainerInterface|null
+ */
+ protected $container;
- /**
- * {@inheritdoc}
- */
- public function setContainer(ContainerInterface $container = null)
- {
- $this->container = $container;
- }
+ /**
+ * {@inheritdoc}
+ */
+ public function setContainer(ContainerInterface $container = null)
+ {
+ $this->container = $container;
+ }
}
\ No newline at end of file
diff --git a/src/Controller/DefaultController.php b/src/Controller/DefaultController.php
index 52c2211..bba474e 100644
--- a/src/Controller/DefaultController.php
+++ b/src/Controller/DefaultController.php
@@ -19,16 +19,16 @@ class DefaultController
public function indexAction(Application $app, Request $request)
{
$rootDir = $app->getRootDir();
- $packagesJson = $rootDir.'/web/packages.json';
+ $packagesJson = $rootDir . '/web/packages.json';
$mtime = null;
if (file_exists($packagesJson)) {
- $mtime = new \DateTime('@'.filemtime($packagesJson));
+ $mtime = new \DateTime('@' . filemtime($packagesJson));
}
return new Response(
- $app->get('templating')->render('Default/index.html.twig', array(
- 'updatedAt' => $mtime,
- )));
+ $app->get('templating')->render('Default/index.html.twig', [
+ 'updatedAt' => $mtime,
+ ]));
}
public function loginAction(Application $app, Request $request)
@@ -40,6 +40,6 @@ public function loginAction(Application $app, Request $request)
$session->remove(AuthenticationFailureSubscriber::AUTHENTICATION_ERROR);
}
- return new Response($app->get('templating')->render('Default/login.html.twig', array('error' => $error)));
+ return new Response($app->get('templating')->render('Default/login.html.twig', ['error' => $error]));
}
}
diff --git a/src/Controller/ManageController.php b/src/Controller/ManageController.php
index b285243..3ccc3d9 100644
--- a/src/Controller/ManageController.php
+++ b/src/Controller/ManageController.php
@@ -29,9 +29,9 @@ public function indexAction(Application $app, Request $request)
->where('c.enabled = true')
->getQuery()->getSingleScalarResult();
- return new Response($app->get('templating')->render('Manage/index.html.twig', array(
- 'packages' => $packages,
- 'remotes' => $remotes,
- )));
+ return new Response($app->get('templating')->render('Manage/index.html.twig', [
+ 'packages' => $packages,
+ 'remotes' => $remotes,
+ ]));
}
}
diff --git a/src/Controller/PackageController.php b/src/Controller/PackageController.php
index c8d552b..c0b73e8 100644
--- a/src/Controller/PackageController.php
+++ b/src/Controller/PackageController.php
@@ -15,6 +15,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Terramar\Packages\Entity\Package;
use Terramar\Packages\Event\PackageEvent;
use Terramar\Packages\Events;
use Terramar\Packages\Plugin\Actions;
@@ -31,37 +32,44 @@ public function indexAction(Application $app, Request $request)
->join('p.remote', 'r', 'WITH', 'r.enabled = true')
->getQuery()->getResult();
- return new Response($app->get('templating')->render('Package/index.html.twig', array(
- 'packages' => $packages,
- )));
+ return new Response($app->get('templating')->render('Package/index.html.twig', [
+ 'packages' => $packages,
+ ]));
}
public function editAction(Application $app, $id)
{
- /** @var \Doctrine\ORM\EntityManager $entityManager */
+ /** @var EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
+ /** @var Package $package */
$package = $entityManager->getRepository('Terramar\Packages\Entity\Package')->find($id);
if (!$package) {
throw new NotFoundHttpException('Unable to locate Package');
}
- return new Response($app->get('templating')->render('Package/edit.html.twig', array(
- 'package' => $package,
- 'remotes' => $this->getRemotes($app->get('doctrine.orm.entity_manager')),
- )));
+ return new Response($app->get('templating')->render('Package/edit.html.twig', [
+ 'package' => $package,
+ 'remotes' => $this->getRemotes($entityManager),
+ ]));
+ }
+
+ protected function getRemotes(EntityManager $entityManager)
+ {
+ return $entityManager->getRepository('Terramar\Packages\Entity\Remote')->findBy(['enabled' => true]);
}
public function updateAction(Application $app, Request $request, $id)
{
- /** @var \Doctrine\ORM\EntityManager $entityManager */
+ /** @var EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
+ /** @var Package $package */
$package = $entityManager->getRepository('Terramar\Packages\Entity\Package')->find($id);
if (!$package) {
throw new NotFoundHttpException('Unable to locate Package');
}
$enabledBefore = $package->isEnabled();
- $enabledAfter = (bool) $request->get('enabled', false);
+ $enabledAfter = (bool)$request->get('enabled', false);
$package->setName($request->request->get('name'));
$package->setDescription($request->request->get('description'));
@@ -78,9 +86,9 @@ public function updateAction(Application $app, Request $request, $id)
/** @var \Terramar\Packages\Helper\PluginHelper $helper */
$helper = $app->get('packages.helper.plugin');
- $helper->invokeAction($request, Actions::PACKAGE_UPDATE, array_merge($request->request->all(), array(
- 'id' => $id,
- )));
+ $helper->invokeAction($request, Actions::PACKAGE_UPDATE, array_merge($request->request->all(), [
+ 'id' => $id,
+ ]));
$entityManager->persist($package);
$entityManager->flush();
@@ -112,9 +120,4 @@ public function toggleAction(Application $app, $id)
return new RedirectResponse($app->get('router.url_generator')->generate('manage_packages'));
}
-
- protected function getRemotes(EntityManager $entityManager)
- {
- return $entityManager->getRepository('Terramar\Packages\Entity\Remote')->findBy(array('enabled' => true));
- }
}
diff --git a/src/Controller/RemoteController.php b/src/Controller/RemoteController.php
index 6e04acd..26bc8e8 100644
--- a/src/Controller/RemoteController.php
+++ b/src/Controller/RemoteController.php
@@ -13,6 +13,8 @@
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Terramar\Packages\Entity\Remote;
use Terramar\Packages\Event\RemoteEvent;
@@ -28,19 +30,29 @@ public function indexAction(Application $app, Request $request)
$remotes = $entityManager->getRepository('Terramar\Packages\Entity\Remote')->findAll();
- return new Response($app->get('templating')->render('Remote/index.html.twig', array(
- 'remotes' => $remotes,
- )));
+ $error = null;
+ $flashBag = $request->getSession()->getBag('flashes');
+ if ($flashBag instanceof FlashBagInterface) {
+ $errors = $flashBag->get('error');
+ if (count($errors) > 0) {
+ $error = $errors[0];
+ }
+ }
+
+ return new Response($app->get('templating')->render('Remote/index.html.twig', [
+ 'remotes' => $remotes,
+ 'last_error' => $error,
+ ]));
}
public function newAction(Application $app)
{
$adapters = $app->get('packages.helper.sync')->getAdapters();
- return new Response($app->get('templating')->render('Remote/new.html.twig', array(
- 'adapters' => $adapters,
- 'remote' => new Remote(),
- )));
+ return new Response($app->get('templating')->render('Remote/new.html.twig', [
+ 'adapters' => $adapters,
+ 'remote' => new Remote(),
+ ]));
}
public function createAction(Application $app, Request $request)
@@ -72,9 +84,9 @@ public function editAction(Application $app, $id)
throw new NotFoundHttpException('Unable to locate Remote');
}
- return new Response($app->get('templating')->render('Remote/edit.html.twig', array(
- 'remote' => $remote,
- )));
+ return new Response($app->get('templating')->render('Remote/edit.html.twig', [
+ 'remote' => $remote,
+ ]));
}
public function updateAction(Application $app, Request $request, $id)
@@ -89,7 +101,7 @@ public function updateAction(Application $app, Request $request, $id)
$remote->setName($request->get('name'));
$enabledBefore = $remote->isEnabled();
- $enabledAfter = (bool) $request->get('enabled', false);
+ $enabledAfter = (bool)$request->get('enabled', false);
$remote->setEnabled($enabledAfter);
@@ -104,9 +116,9 @@ public function updateAction(Application $app, Request $request, $id)
/** @var \Terramar\Packages\Helper\PluginHelper $helper */
$helper = $app->get('packages.helper.plugin');
- $helper->invokeAction($request, Actions::REMOTE_UPDATE, array_merge($request->request->all(), array(
- 'id' => $id,
- )));
+ $helper->invokeAction($request, Actions::REMOTE_UPDATE, array_merge($request->request->all(), [
+ 'id' => $id,
+ ]));
$entityManager->persist($remote);
$entityManager->flush();
@@ -114,7 +126,7 @@ public function updateAction(Application $app, Request $request, $id)
return new RedirectResponse($app->get('router.url_generator')->generate('manage_remotes'));
}
- public function syncAction(Application $app, $id)
+ public function syncAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
@@ -125,7 +137,15 @@ public function syncAction(Application $app, $id)
/** @var \Terramar\Packages\Helper\SyncHelper $helper */
$helper = $app->get('packages.helper.sync');
- $packages = $helper->synchronizePackages($remote);
+ try {
+ $packages = $helper->synchronizePackages($remote);
+ } catch (\RuntimeException $e) {
+ $flashBag = $request->getSession()->getBag('flashes');
+ if ($flashBag instanceof FlashBagInterface) {
+ $flashBag->add('error', $e->getMessage());
+ }
+ return new RedirectResponse($app->get('router.url_generator')->generate('manage_remotes'));
+ }
foreach ($packages as $package) {
$entityManager->persist($package);
}
diff --git a/src/Controller/WebHookController.php b/src/Controller/WebHookController.php
index 2511196..7df1d1a 100644
--- a/src/Controller/WebHookController.php
+++ b/src/Controller/WebHookController.php
@@ -20,11 +20,14 @@ class WebHookController extends ContainerAwareController
{
public function receiveAction(Application $app, Request $request, $id)
{
- ResqueHelper::autoConfigure($this->container);
+ ResqueHelper::autoConfigure($this->container);
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $package = $entityManager->getRepository('Terramar\Packages\Entity\Package')->findOneBy(array('id' => $id, 'enabled' => true));
+ $package = $entityManager->getRepository('Terramar\Packages\Entity\Package')->findOneBy([
+ 'id' => $id,
+ 'enabled' => true,
+ ]);
if (!$package || !$package->isEnabled() || !$package->getRemote()->isEnabled()) {
return new Response('Project not found', 404);
}
diff --git a/src/DependencyInjection/Compiler/OverrideServicesCompilerPass.php b/src/DependencyInjection/Compiler/OverrideServicesCompilerPass.php
new file mode 100644
index 0000000..3034d53
--- /dev/null
+++ b/src/DependencyInjection/Compiler/OverrideServicesCompilerPass.php
@@ -0,0 +1,28 @@
+getDefinition('security.security_subscriber')
+ ->setClass('Terramar\Packages\Security\FirewallSubscriber');
+ }
+}
\ No newline at end of file
diff --git a/src/DependencyInjection/PackagesConfiguration.php b/src/DependencyInjection/PackagesConfiguration.php
index e70a922..31949a0 100644
--- a/src/DependencyInjection/PackagesConfiguration.php
+++ b/src/DependencyInjection/PackagesConfiguration.php
@@ -27,8 +27,13 @@ public function getConfigTreeBuilder()
$rootNode
->children()
->scalarNode('site_name')->defaultValue('Private Composer Repository')->end()
- ->scalarNode('homepage')->defaultValue('https://github.com/terramar-labs/packages')->end()
- ->scalarNode('output_dir')->defaultValue('%app.root_dir%/web')->end()
+ ->scalarNode('name')->defaultNull()->end()
+ ->scalarNode('homepage')->defaultValue('')->end()
+ ->scalarNode('base_path')->defaultValue('')->end()
+ ->scalarNode('archive')->defaultValue(false)->end()
+ ->scalarNode('contact_email')->defaultValue('')->end()
+ ->scalarNode('secure_satis')->defaultFalse()->end()
+ ->scalarNode('output_dir')->defaultValue('%app.root_dir%/satis')->end()
->arrayNode('resque')
->addDefaultsIfNotSet()
->children()
@@ -36,8 +41,7 @@ public function getConfigTreeBuilder()
->scalarNode('port')->defaultValue('6379')->end()
->scalarNode('database')->defaultNull()->end()
->end()
- ->end()
- ->end();
+ ->end();
return $treeBuilder;
}
diff --git a/src/DependencyInjection/PackagesExtension.php b/src/DependencyInjection/PackagesExtension.php
index ea802f3..b59c2c2 100644
--- a/src/DependencyInjection/PackagesExtension.php
+++ b/src/DependencyInjection/PackagesExtension.php
@@ -9,52 +9,45 @@
namespace Terramar\Packages\DependencyInjection;
+use Nice\DependencyInjection\CompilerAwareExtensionInterface;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Reference;
+use Terramar\Packages\DependencyInjection\Compiler\OverrideServicesCompilerPass;
+use Terramar\Packages\Plugin\CompilerAwarePluginInterface;
use Terramar\Packages\Plugin\PluginInterface;
+use Terramar\Packages\Plugin\RouterPluginInterface;
-class PackagesExtension extends Extension
+class PackagesExtension extends Extension implements CompilerAwareExtensionInterface
{
/**
* @var array
*/
- private $options = array();
+ private $options = [];
/**
* @var array|PluginInterface[]
*/
- private $plugins = array();
+ private $plugins = [];
/**
* Constructor.
*
+ * @param array $plugins
* @param array $options
*/
- public function __construct(array $plugins = array(), array $options = array())
+ public function __construct(array $plugins = [], array $options = [])
{
$this->plugins = $plugins;
$this->options = $options;
}
- /**
- * Returns extension configuration.
- *
- * @param array $config An array of configuration values
- * @param ContainerBuilder $container A ContainerBuilder instance
- *
- * @return PackagesConfiguration
- */
- public function getConfiguration(array $config, ContainerBuilder $container)
- {
- return new PackagesConfiguration();
- }
-
/**
* Loads a specific configuration.
*
- * @param array $configs An array of configuration values
+ * @param array $configs An array of configuration values
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws \InvalidArgumentException When provided tag is not defined in this extension
@@ -65,7 +58,17 @@ public function load(array $configs, ContainerBuilder $container)
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
- $container->register('router.collector', 'Terramar\Packages\Router\RouteCollector')
+ $container->setParameter('packages.configuration', [
+ 'name' => empty($config['name']) ? $config['site_name'] : $config['name'],
+ 'homepage' => $config['homepage'],
+ 'base_path' => $config['base_path'],
+ 'archive' => $config['archive'],
+ 'output_dir' => $container->getParameterBag()->resolveValue($config['output_dir']),
+ 'contact_email' => $config['contact_email'],
+ 'secure_satis' => $config['secure_satis'],
+ ]);
+
+ $collector = $container->register('router.collector', 'Terramar\Packages\Router\RouteCollector')
->addArgument(new Reference('router.parser'))
->addArgument(new Reference('router.data_generator'));
@@ -74,12 +77,6 @@ public function load(array $configs, ContainerBuilder $container)
$container->register('packages.helper.sync', 'Terramar\Packages\Helper\SyncHelper')
->addArgument(new Reference('event_dispatcher'));
- $container->setParameter('packages.configuration', array(
- 'name' => $config['site_name'],
- 'homepage' => $config['homepage'],
- 'output_dir' => $config['output_dir'],
- ));
-
$container->register('packages.helper.resque', 'Terramar\Packages\Helper\ResqueHelper');
$container->setParameter('packages.resque.host', $config['resque']['host']);
@@ -88,52 +85,108 @@ public function load(array $configs, ContainerBuilder $container)
$container->register('packages.controller_manager', 'Terramar\Packages\Plugin\ControllerManager');
- $container->register('packages.fragment_handler.inline_renderer', 'Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer')
+ $container->register('packages.fragment_handler.inline_renderer',
+ 'Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer')
->addArgument(new Reference('http_kernel'))
->addArgument(new Reference('event_dispatcher'));
$container->register('packages.fragment_handler', 'Symfony\Component\HttpKernel\Fragment\FragmentHandler')
- ->addArgument(array(
- new Reference('packages.fragment_handler.inline_renderer'),
- ))
+ ->addArgument([
+ new Reference('packages.fragment_handler.inline_renderer'),
+ ])
->addArgument(false)
- ->addMethodCall('setRequest', array(new Reference(
+ ->addMethodCall('setRequest', [
+ new Reference(
'request',
ContainerInterface::NULL_ON_INVALID_REFERENCE,
false
- )));
+ ),
+ ]);
+
+ $container->register('packages.twig_extension.packages_conf', 'Terramar\Packages\Twig\PackagesConfigExtension')
+ ->addArgument('%packages.configuration%')
+ ->addTag('twig.extension');
$container->register('packages.twig_extension.plugin', 'Terramar\Packages\Twig\PluginControllerExtension')
->addArgument(new Reference('packages.controller_manager'))
->addArgument(new Reference('packages.fragment_handler'))
- ->addMethodCall('setRequest', array(new Reference(
+ ->addMethodCall('setRequest', [
+ new Reference(
+ 'request',
+ ContainerInterface::NULL_ON_INVALID_REFERENCE,
+ false
+ ),
+ ])
+ ->addTag('twig.extension');
+
+ $container->register('packages.twig_extension.security', 'Terramar\Packages\Twig\SecurityExtension')
+ ->addMethodCall('setRequest', [
+ new Reference(
'request',
ContainerInterface::NULL_ON_INVALID_REFERENCE,
false
- )))
+ ),
+ ])
->addTag('twig.extension');
$container->register('packages.fragment_handler.uri_signer', 'Symfony\Component\HttpKernel\UriSigner')
->addArgument('');
- $container->register('packages.fragment_handler.listener', 'Symfony\Component\HttpKernel\EventListener\FragmentListener')
+ $container->register('packages.fragment_handler.listener',
+ 'Symfony\Component\HttpKernel\EventListener\FragmentListener')
->addArgument(new Reference('packages.fragment_handler.uri_signer'))
->addTag('kernel.event_subscriber');
$container->register('packages.helper.plugin', 'Terramar\Packages\Helper\PluginHelper')
->addArgument(new Reference('packages.controller_manager'))
->addArgument(new Reference('packages.fragment_handler'))
- ->addMethodCall('setRequest', array(new Reference(
+ ->addMethodCall('setRequest', [
+ new Reference(
'request',
ContainerInterface::NULL_ON_INVALID_REFERENCE,
false
- )));
+ ),
+ ]);
- $plugins = array();
+ $plugins = [];
foreach ($this->plugins as $plugin) {
+ $name = preg_replace('/[^a-z0-9]/', '', strtolower($plugin->getName()));
+ $container->register('packages.plugin.'.$name, get_class($plugin));
$plugin->configure($container);
- $plugins[$plugin->getName()] = $plugin->getVersion();
+ $plugins[$name] = $plugin->getVersion();
+ if ($plugin instanceof RouterPluginInterface) {
+ $collector->addMethodCall('registerPlugin', [new Reference('packages.plugin.'.$name)]);
+ }
}
$container->setParameter('packages.registered_plugins', $plugins);
}
+
+ /**
+ * Returns extension configuration.
+ *
+ * @param array $config An array of configuration values
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ *
+ * @return PackagesConfiguration
+ */
+ public function getConfiguration(array $config, ContainerBuilder $container)
+ {
+ return new PackagesConfiguration();
+ }
+
+ /**
+ * Gets the CompilerPasses this extension requires.
+ *
+ * @return array|CompilerPassInterface[]
+ */
+ public function getCompilerPasses()
+ {
+ $passes = [new OverrideServicesCompilerPass()];
+ foreach ($this->plugins as $plugin) {
+ if ($plugin instanceof CompilerAwarePluginInterface) {
+ $passes = array_merge($passes, $plugin->getCompilerPasses());
+ }
+ }
+ return $passes;
+ }
}
diff --git a/src/Entity/Package.php b/src/Entity/Package.php
index 6c91319..9180a36 100644
--- a/src/Entity/Package.php
+++ b/src/Entity/Package.php
@@ -12,7 +12,7 @@
use Doctrine\ORM\Mapping as ORM;
/**
- * @ORM\Entity
+ * @ORM\Entity
* @ORM\Table(name="packages")
*/
class Package
@@ -75,7 +75,7 @@ class Package
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
@@ -107,7 +107,7 @@ public function getDescription()
*/
public function setDescription($description)
{
- $this->description = (string) $description;
+ $this->description = (string)$description;
}
/**
@@ -123,7 +123,7 @@ public function getName()
*/
public function setName($name)
{
- $this->name = (string) $name;
+ $this->name = (string)$name;
}
/**
@@ -155,7 +155,7 @@ public function getExternalId()
*/
public function setExternalId($externalId)
{
- $this->externalId = (string) $externalId;
+ $this->externalId = (string)$externalId;
}
/**
@@ -171,7 +171,7 @@ public function getHookExternalId()
*/
public function setHookExternalId($hookExternalId)
{
- $this->hookExternalId = (string) $hookExternalId;
+ $this->hookExternalId = (string)$hookExternalId;
}
/**
@@ -187,7 +187,7 @@ public function getFqn()
*/
public function setFqn($fqn)
{
- $this->fqn = (string) $fqn;
+ $this->fqn = (string)$fqn;
}
/**
@@ -203,7 +203,7 @@ public function getSshUrl()
*/
public function setSshUrl($sshUrl)
{
- $this->sshUrl = (string) $sshUrl;
+ $this->sshUrl = (string)$sshUrl;
}
/**
@@ -219,6 +219,14 @@ public function getWebUrl()
*/
public function setWebUrl($webUrl)
{
- $this->webUrl = (string) $webUrl;
+ $this->webUrl = (string)$webUrl;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return sprintf("%d:%d", $this->remote->getId(), $this->externalId);
}
}
diff --git a/src/Entity/Remote.php b/src/Entity/Remote.php
index 4b8e3cf..bfe2c1c 100644
--- a/src/Entity/Remote.php
+++ b/src/Entity/Remote.php
@@ -52,7 +52,7 @@ public function isEnabled()
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
@@ -76,7 +76,7 @@ public function getName()
*/
public function setName($name)
{
- $this->name = (string) $name;
+ $this->name = (string)$name;
}
/**
@@ -92,6 +92,6 @@ public function getAdapter()
*/
public function setAdapter($adapter)
{
- $this->adapter = (string) $adapter;
+ $this->adapter = (string)$adapter;
}
}
diff --git a/src/Event/PackageUpdateEvent.php b/src/Event/PackageUpdateEvent.php
index f953a19..2958f18 100644
--- a/src/Event/PackageUpdateEvent.php
+++ b/src/Event/PackageUpdateEvent.php
@@ -20,9 +20,9 @@ class PackageUpdateEvent extends PackageEvent
/**
* Constructor.
- *
+ *
* @param Package $package The updated package
- * @param mixed $payload Any data received from the remote host
+ * @param mixed $payload Any data received from the remote host
*/
public function __construct(Package $package, $payload)
{
diff --git a/src/Events.php b/src/Events.php
index 6c7e2e4..f845a70 100644
--- a/src/Events.php
+++ b/src/Events.php
@@ -12,7 +12,7 @@
/**
* Events defines constants describing the possible events to subscribe to.
*
- * @see http://docs.terramarlabs.com/packages/3.1/plugins/event-reference
+ * @see http://docs.terramarlabs.com/packages/3.2/plugins/event-reference
*/
final class Events
{
diff --git a/src/Helper/PluginHelper.php b/src/Helper/PluginHelper.php
index dbd0de2..a7e7cfb 100644
--- a/src/Helper/PluginHelper.php
+++ b/src/Helper/PluginHelper.php
@@ -35,7 +35,7 @@ class PluginHelper
* Constructor.
*
* @param ControllerManagerInterface $manager
- * @param FragmentHandler $handler
+ * @param FragmentHandler $handler
*/
public function __construct(ControllerManagerInterface $manager, FragmentHandler $handler)
{
@@ -53,13 +53,14 @@ public function setRequest(Request $request = null)
/**
* Invoke the given action using the given Request.
- *
+ *
* @param Request $request
- * @param string $action
+ * @param string $action
*/
- public function invokeAction(Request $request, $action, $params = array())
+ public function invokeAction(Request $request, $action, $params = [])
{
- $controllers = $this->getControllers($action, $params, array_merge($request->query->all(), $request->request->all()));
+ $controllers = $this->getControllers($action, $params,
+ array_merge($request->query->all(), $request->request->all()));
foreach ($controllers as $controller) {
$this->handler->render($controller);
@@ -71,12 +72,12 @@ public function invokeAction(Request $request, $action, $params = array())
*
* @return array|ControllerReference[]
*/
- private function getControllers($action, $params = array(), $query = array())
+ private function getControllers($action, $params = [], $query = [])
{
$params['app'] = $this->request->get('app');
return array_map(function ($controller) use ($params, $query) {
- return new ControllerReference($controller, $params, $query);
- }, $this->manager->getControllers($action));
+ return new ControllerReference($controller, $params, $query);
+ }, $this->manager->getControllers($action));
}
}
diff --git a/src/Helper/ResqueHelper.php b/src/Helper/ResqueHelper.php
index aaf9295..78f8a0c 100644
--- a/src/Helper/ResqueHelper.php
+++ b/src/Helper/ResqueHelper.php
@@ -13,78 +13,54 @@
class ResqueHelper
{
- /**
- * Configure Resque
- *
- * @param ContainerInterface $container
- * @return array
- */
- public static function autoConfigure(ContainerInterface $container)
- {
- $redisHost = $container->getParameter('packages.resque.host');
- $redisPort = $container->getParameter('packages.resque.port');
- $redisDatabase = $container->getParameter('packages.resque.database');
-
- if (!isset($redisDatabase)) {
- $redisDatabase = 0;
- }
-
- $backend = strpos($redisHost, 'unix:') === false ? $redisHost.':'.$redisPort : $redisHost;
-
- \Resque::setBackend($backend, $redisDatabase);
-
- return array(
- 'backend' => $backend,
- 'database' => $redisDatabase
- );
- }
-
/**
- * Get jobs for the given queue.
- *
- * @param string $queue The name of the queue or "*" for all queues
+ * Configure Resque
*
- * @return array|\Resque_Job[]
+ * @param ContainerInterface $container
+ * @return array
*/
- public function getJobs($queue = null)
+ public static function autoConfigure(ContainerInterface $container)
{
- if (!$queue || $queue === '*') {
- $queues = \Resque::queues();
- $jobs = array();
- foreach ($queues as $queue) {
- $jobs = array_merge($jobs, $this->getJobs($queue));
- }
+ $redisHost = $container->getParameter('packages.resque.host');
+ $redisPort = $container->getParameter('packages.resque.port');
+ $redisDatabase = $container->getParameter('packages.resque.database');
- return $jobs;
+ if (!isset($redisDatabase)) {
+ $redisDatabase = 0;
}
- return array_map(function ($job) use ($queue) {
- return new \Resque_Job($queue, json_decode($job, true));
- }, \Resque::redis()->lrange('queue:'.$queue, 0, -1));
+ $backend = strpos($redisHost, 'unix:') === false ? $redisHost . ':' . $redisPort : $redisHost;
+
+ \Resque::setBackend($backend, $redisDatabase);
+
+ return [
+ 'backend' => $backend,
+ 'database' => $redisDatabase,
+ ];
}
/**
* Clear the given queue.
- *
+ *
* @param string $queue The name of the queue
*
* @return int The number of removed items
*/
public function clearQueue($queue)
{
- $length = \Resque::redis()->llen('queue:'.$queue);
- \Resque::redis()->del('queue:'.$queue);
+ $length = \Resque::redis()->llen('queue:' . $queue);
+ \Resque::redis()->del('queue:' . $queue);
return $length;
}
/**
* Enqueue a job, but only if it is not already in the queue.
- *
+ *
* @param string $queue
* @param string $class
- * @param array $args
- * @param bool $trackStatus
+ * @param array $args
+ * @param bool $trackStatus
*
* @return string The enqueued job ID
*/
@@ -99,13 +75,37 @@ public function enqueueOnce($queue, $class, $args = null, $trackStatus = false)
return $this->enqueue($queue, $class, $args, $trackStatus);
}
+ /**
+ * Get jobs for the given queue.
+ *
+ * @param string $queue The name of the queue or "*" for all queues
+ *
+ * @return array|\Resque_Job[]
+ */
+ public function getJobs($queue = null)
+ {
+ if (!$queue || $queue === '*') {
+ $queues = \Resque::queues();
+ $jobs = [];
+ foreach ($queues as $queue) {
+ $jobs = array_merge($jobs, $this->getJobs($queue));
+ }
+
+ return $jobs;
+ }
+
+ return array_map(function ($job) use ($queue) {
+ return new \Resque_Job($queue, json_decode($job, true));
+ }, \Resque::redis()->lrange('queue:' . $queue, 0, -1));
+ }
+
/**
* Enqueue a job.
- *
+ *
* @param string $queue
* @param string $class
- * @param array $args
- * @param bool $trackStatus
+ * @param array $args
+ * @param bool $trackStatus
*
* @return string The enqueued job ID
*/
diff --git a/src/Helper/SyncAdapterInterface.php b/src/Helper/SyncAdapterInterface.php
index a9d1abf..ccdeaae 100644
--- a/src/Helper/SyncAdapterInterface.php
+++ b/src/Helper/SyncAdapterInterface.php
@@ -9,14 +9,14 @@
namespace Terramar\Packages\Helper;
-use Terramar\Packages\Entity\Remote;
use Terramar\Packages\Entity\Package;
+use Terramar\Packages\Entity\Remote;
interface SyncAdapterInterface
{
/**
* Returns true if the adapter supports the given configuration.
- *
+ *
* @param Remote $remote
*
* @return bool
@@ -25,7 +25,7 @@ public function supports(Remote $remote);
/**
* Synchronizes the given adapter, returning any new Packages.
- *
+ *
* @param Remote $remote
*
* @return Package[]
@@ -34,7 +34,7 @@ public function synchronizePackages(Remote $remote);
/**
* Gets the name of the adapter.
- *
+ *
* @return string
*/
public function getName();
diff --git a/src/Helper/SyncHelper.php b/src/Helper/SyncHelper.php
index a894550..2faa7e1 100644
--- a/src/Helper/SyncHelper.php
+++ b/src/Helper/SyncHelper.php
@@ -24,11 +24,11 @@ class SyncHelper
/**
* @var array|SyncAdapterInterface[]
*/
- private $adapters = array();
+ private $adapters = [];
/**
* Constructor.
- *
+ *
* @param EventDispatcherInterface $eventDispatcher
*/
public function __construct(EventDispatcherInterface $eventDispatcher)
@@ -38,7 +38,7 @@ public function __construct(EventDispatcherInterface $eventDispatcher)
/**
* Register an adapter with the helper.
- *
+ *
* @param SyncAdapterInterface $adapter
*/
public function registerAdapter(SyncAdapterInterface $adapter)
@@ -48,7 +48,7 @@ public function registerAdapter(SyncAdapterInterface $adapter)
/**
* Synchronize packages in the given configuration.
- *
+ *
* @param Remote $configuration
*
* @return \Terramar\Packages\Entity\Package[]
@@ -67,14 +67,6 @@ public function synchronizePackages(Remote $configuration)
return $packages;
}
- /**
- * @return array|SyncAdapterInterface[]
- */
- public function getAdapters()
- {
- return array_values($this->adapters);
- }
-
private function getAdapter(Remote $configuration)
{
foreach ($this->adapters as $adapter) {
@@ -85,4 +77,12 @@ private function getAdapter(Remote $configuration)
throw new \RuntimeException('No adapter registered supports the given configuration');
}
+
+ /**
+ * @return array|SyncAdapterInterface[]
+ */
+ public function getAdapters()
+ {
+ return array_values($this->adapters);
+ }
}
diff --git a/src/Job/ContainerAwareJob.php b/src/Job/ContainerAwareJob.php
index 71b6031..c89bad7 100644
--- a/src/Job/ContainerAwareJob.php
+++ b/src/Job/ContainerAwareJob.php
@@ -27,13 +27,23 @@ abstract class ContainerAwareJob
/**
* @var array The job args
*/
- public $args = array();
+ public $args = [];
/**
* @var Application
*/
private $app = null;
+ /**
+ * Perform the work.
+ */
+ public function perform()
+ {
+ $this->run($this->args);
+ }
+
+ abstract protected function run($args);
+
/**
* @return ContainerInterface
*/
@@ -58,14 +68,4 @@ protected function createApplication()
isset($this->args['app.cache']) ? $this->args['app.cache'] : true
);
}
-
- /**
- * Perform the work.
- */
- public function perform()
- {
- $this->run($this->args);
- }
-
- abstract protected function run($args);
}
diff --git a/src/Migration/Version3100.php b/src/Migration/Version3100.php
index dcf80f6..16d806e 100644
--- a/src/Migration/Version3100.php
+++ b/src/Migration/Version3100.php
@@ -25,7 +25,7 @@ public function up(Schema $schema)
{
$table = $schema->createTable('packages_sami_configurations');
$table->addColumn('id', 'integer');
- $table->setPrimaryKey(array('id'));
+ $table->setPrimaryKey(['id']);
$table->addColumn('enabled', 'boolean');
$table->addColumn('package_id', 'integer');
$table->addColumn('docs_path', 'string');
@@ -36,14 +36,14 @@ public function up(Schema $schema)
$table->addColumn('tags', 'string');
$table->addColumn('refs', 'string');
$table->addColumn('templates_dir', 'string');
- $table->addForeignKeyConstraint('packages', array('package_id'), array('id'));
+ $table->addForeignKeyConstraint('packages', ['package_id'], ['id']);
$table = $schema->createTable('packages_cloneproject_configurations');
$table->addColumn('id', 'integer');
- $table->setPrimaryKey(array('id'));
+ $table->setPrimaryKey(['id']);
$table->addColumn('enabled', 'boolean');
$table->addColumn('package_id', 'integer');
- $table->addForeignKeyConstraint('packages', array('package_id'), array('id'));
+ $table->addForeignKeyConstraint('packages', ['package_id'], ['id']);
}
public function postUp(Schema $schema)
diff --git a/src/Plugin/Actions.php b/src/Plugin/Actions.php
index 6808f8f..dd0cabb 100644
--- a/src/Plugin/Actions.php
+++ b/src/Plugin/Actions.php
@@ -12,7 +12,7 @@
/**
* Actions defines constants for the various actions available to plugins.
*
- * @see http://docs.terramarlabs.com/packages/3.1/plugins/action-reference
+ * @see http://docs.terramarlabs.com/packages/3.2/plugins/action-reference
*/
final class Actions
{
diff --git a/src/Plugin/CloneProject/CloneProjectJob.php b/src/Plugin/CloneProject/CloneProjectJob.php
index a719d92..78fd3a5 100644
--- a/src/Plugin/CloneProject/CloneProjectJob.php
+++ b/src/Plugin/CloneProject/CloneProjectJob.php
@@ -17,30 +17,6 @@
class CloneProjectJob extends ContainerAwareJob
{
- /**
- * @return string
- */
- private function getCacheDir(Package $package)
- {
- return $this->getContainer()->getParameter('app.cache_dir').'/cloned_project/'.$package->getFqn();
- }
-
- /**
- * @return EntityManager
- */
- private function getEntityManager()
- {
- return $this->getContainer()->get('doctrine.orm.entity_manager');
- }
-
- /**
- * @return EventDispatcherInterface
- */
- private function getEventDispatcher()
- {
- return $this->getContainer()->get('event_dispatcher');
- }
-
public function run($args)
{
$package = $this->getEntityManager()->find('Terramar\Packages\Entity\Package', $args['id']);
@@ -56,7 +32,7 @@ public function run($args)
mkdir($directory, 0777, true);
- $builder = new ProcessBuilder(array('clone', $package->getSshUrl(), $directory));
+ $builder = new ProcessBuilder(['clone', $package->getSshUrl(), $directory]);
$builder->setPrefix('git');
$process = $builder->getProcess();
@@ -70,13 +46,37 @@ public function run($args)
}
}
+ /**
+ * @return EntityManager
+ */
+ private function getEntityManager()
+ {
+ return $this->getContainer()->get('doctrine.orm.entity_manager');
+ }
+
+ /**
+ * @return string
+ */
+ private function getCacheDir(Package $package)
+ {
+ return $this->getContainer()->getParameter('app.cache_dir') . '/cloned_project/' . $package->getFqn();
+ }
+
private function emptyAndRemoveDirectory($directory)
{
- $files = array_diff(scandir($directory), array('.', '..'));
+ $files = array_diff(scandir($directory), ['.', '..']);
foreach ($files as $file) {
(is_dir("$directory/$file")) ? $this->emptyAndRemoveDirectory("$directory/$file") : unlink("$directory/$file");
}
return rmdir($directory);
}
+
+ /**
+ * @return EventDispatcherInterface
+ */
+ private function getEventDispatcher()
+ {
+ return $this->getContainer()->get('event_dispatcher');
+ }
}
diff --git a/src/Plugin/CloneProject/Controller.php b/src/Plugin/CloneProject/Controller.php
index 89637af..b67c0ea 100644
--- a/src/Plugin/CloneProject/Controller.php
+++ b/src/Plugin/CloneProject/Controller.php
@@ -19,22 +19,22 @@ public function editAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\CloneProject\PackageConfiguration')->findOneBy(array(
- 'package' => $id,
- ));
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\CloneProject\PackageConfiguration')->findOneBy([
+ 'package' => $id,
+ ]);
- return new Response($app->get('twig')->render('Plugin/CloneProject/edit.html.twig', array(
- 'config' => $config,
- )));
+ return new Response($app->get('twig')->render('Plugin/CloneProject/edit.html.twig', [
+ 'config' => $config,
+ ]));
}
public function updateAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\CloneProject\PackageConfiguration')->findOneBy(array(
- 'package' => $id,
- ));
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\CloneProject\PackageConfiguration')->findOneBy([
+ 'package' => $id,
+ ]);
$config->setEnabled($request->get('cloneproject_enabled') ? true : false);
$entityManager->persist($config);
diff --git a/src/Plugin/CloneProject/EventSubscriber.php b/src/Plugin/CloneProject/EventSubscriber.php
index 2e8cce0..c2897b3 100644
--- a/src/Plugin/CloneProject/EventSubscriber.php
+++ b/src/Plugin/CloneProject/EventSubscriber.php
@@ -31,7 +31,7 @@ class EventSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param ResqueHelper $resqueHelper
+ * @param ResqueHelper $resqueHelper
* @param EntityManager $entityManager
*/
public function __construct(ResqueHelper $resqueHelper, EntityManager $entityManager)
@@ -40,20 +40,33 @@ public function __construct(ResqueHelper $resqueHelper, EntityManager $entityMan
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::PACKAGE_CREATE => ['onCreatePackage', 0],
+ Events::PACKAGE_UPDATE => ['onUpdatePackage', 0],
+ ];
+ }
+
/**
* @param PackageUpdateEvent $event
*/
public function onUpdatePackage(PackageUpdateEvent $event)
{
$package = $event->getPackage();
+ /** @var \Terramar\Packages\Plugin\CloneProject\PackageConfiguration $config */
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\CloneProject\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config || !$config->isEnabled() || !$package->isEnabled()) {
return;
}
- $this->resqueHelper->enqueue('default', 'Terramar\Packages\Plugin\CloneProject\CloneProjectJob', array('id' => $event->getPackage()->getId()));
+ $this->resqueHelper->enqueue('default', 'Terramar\Packages\Plugin\CloneProject\CloneProjectJob',
+ ['id' => $event->getPackage()->getId()]);
}
/**
@@ -63,7 +76,7 @@ public function onCreatePackage(PackageEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\CloneProject\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config) {
$config = new PackageConfiguration();
@@ -72,15 +85,4 @@ public function onCreatePackage(PackageEvent $event)
$this->entityManager->persist($config);
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::PACKAGE_CREATE => array('onCreatePackage', 0),
- Events::PACKAGE_UPDATE => array('onUpdatePackage', 0),
- );
- }
}
diff --git a/src/Plugin/CloneProject/PackageCloneEvent.php b/src/Plugin/CloneProject/PackageCloneEvent.php
index 5aa0d5b..99025df 100644
--- a/src/Plugin/CloneProject/PackageCloneEvent.php
+++ b/src/Plugin/CloneProject/PackageCloneEvent.php
@@ -22,8 +22,8 @@ class PackageCloneEvent extends PackageEvent
/**
* Constructor.
*
- * @param Package $package The updated package
- * @param string $repositoryPath The path to the cloned repository
+ * @param Package $package The updated package
+ * @param string $repositoryPath The path to the cloned repository
*/
public function __construct(Package $package, $repositoryPath)
{
diff --git a/src/Plugin/CloneProject/PackageConfiguration.php b/src/Plugin/CloneProject/PackageConfiguration.php
index 2ed4c62..42c0af7 100644
--- a/src/Plugin/CloneProject/PackageConfiguration.php
+++ b/src/Plugin/CloneProject/PackageConfiguration.php
@@ -41,7 +41,7 @@ class PackageConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
diff --git a/src/Plugin/CloneProject/Plugin.php b/src/Plugin/CloneProject/Plugin.php
index f64055d..d24efd3 100644
--- a/src/Plugin/CloneProject/Plugin.php
+++ b/src/Plugin/CloneProject/Plugin.php
@@ -31,14 +31,17 @@ class Plugin implements PluginInterface
*/
public function configure(ContainerBuilder $container)
{
- $container->register('packages.plugin.clone_project.subscriber', 'Terramar\Packages\Plugin\CloneProject\EventSubscriber')
+ $container->register('packages.plugin.clone_project.subscriber',
+ 'Terramar\Packages\Plugin\CloneProject\EventSubscriber')
->addArgument(new Reference('packages.helper.resque'))
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('kernel.event_subscriber');
$container->getDefinition('packages.controller_manager')
- ->addMethodCall('registerController', array(Actions::PACKAGE_EDIT, 'Terramar\Packages\Plugin\CloneProject\Controller::editAction'))
- ->addMethodCall('registerController', array(Actions::PACKAGE_UPDATE, 'Terramar\Packages\Plugin\CloneProject\Controller::updateAction'));
+ ->addMethodCall('registerController',
+ [Actions::PACKAGE_EDIT, 'Terramar\Packages\Plugin\CloneProject\Controller::editAction'])
+ ->addMethodCall('registerController',
+ [Actions::PACKAGE_UPDATE, 'Terramar\Packages\Plugin\CloneProject\Controller::updateAction']);
}
/**
@@ -57,7 +60,7 @@ public function getName()
public function getVersion()
{
if (!$this->version) {
- $matches = array();
+ $matches = [];
preg_match('/version (\d\.\d{1,2}\.\d{1,2})/', exec('git --version'), $matches);
$this->version = $matches[1];
}
diff --git a/src/Plugin/CompilerAwarePluginInterface.php b/src/Plugin/CompilerAwarePluginInterface.php
new file mode 100644
index 0000000..9afee04
--- /dev/null
+++ b/src/Plugin/CompilerAwarePluginInterface.php
@@ -0,0 +1,28 @@
+controllers[$action])) {
- $this->controllers[$action] = array();
+ $this->controllers[$action] = [];
}
$this->controllers[$action][] = $controller;
@@ -24,6 +24,6 @@ public function registerController($action, $controller)
public function getControllers($action)
{
- return isset($this->controllers[$action]) ? $this->controllers[$action] : array();
+ return isset($this->controllers[$action]) ? $this->controllers[$action] : [];
}
}
diff --git a/src/Plugin/ControllerManagerInterface.php b/src/Plugin/ControllerManagerInterface.php
index aa57544..bec7f5f 100644
--- a/src/Plugin/ControllerManagerInterface.php
+++ b/src/Plugin/ControllerManagerInterface.php
@@ -16,7 +16,7 @@ interface ControllerManagerInterface
{
/**
* Register a controller for the given action.
- *
+ *
* @param string $action
* @param string $controller
*/
diff --git a/src/Plugin/GitHub/Controller.php b/src/Plugin/GitHub/Controller.php
index bdfe061..8e52e76 100644
--- a/src/Plugin/GitHub/Controller.php
+++ b/src/Plugin/GitHub/Controller.php
@@ -44,22 +44,22 @@ public function editAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')->findOneBy(array(
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')->findOneBy([
'remote' => $id,
- ));
+ ]);
- return new Response($app->get('twig')->render('Plugin/GitHub/edit.html.twig', array(
+ return new Response($app->get('twig')->render('Plugin/GitHub/edit.html.twig', [
'config' => $config ?: new RemoteConfiguration(),
- )));
+ ]));
}
public function updateAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')->findOneBy(array(
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')->findOneBy([
'remote' => $id,
- ));
+ ]);
if (!$config) {
return new Response();
diff --git a/src/Plugin/GitHub/PackageConfiguration.php b/src/Plugin/GitHub/PackageConfiguration.php
index 3adc093..e170d4d 100644
--- a/src/Plugin/GitHub/PackageConfiguration.php
+++ b/src/Plugin/GitHub/PackageConfiguration.php
@@ -41,7 +41,7 @@ class PackageConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
diff --git a/src/Plugin/GitHub/PackageSubscriber.php b/src/Plugin/GitHub/PackageSubscriber.php
index 5606b0a..a946021 100644
--- a/src/Plugin/GitHub/PackageSubscriber.php
+++ b/src/Plugin/GitHub/PackageSubscriber.php
@@ -29,7 +29,7 @@ class PackageSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param SyncAdapter $adapter
+ * @param SyncAdapter $adapter
* @param EntityManager $entityManager
*/
public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
@@ -38,6 +38,18 @@ public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::PACKAGE_CREATE => ['onCreatePackage', 255],
+ Events::PACKAGE_ENABLE => ['onEnablePackage', 255],
+ Events::PACKAGE_DISABLE => ['onDisablePackage', 255],
+ ];
+ }
+
/**
* @param PackageEvent $event
*/
@@ -45,7 +57,7 @@ public function onCreatePackage(PackageEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\GitHub\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config) {
$config = new PackageConfiguration();
@@ -80,16 +92,4 @@ public function onDisablePackage(PackageEvent $event)
$this->adapter->disableHook($package);
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::PACKAGE_CREATE => array('onCreatePackage', 255),
- Events::PACKAGE_ENABLE => array('onEnablePackage', 255),
- Events::PACKAGE_DISABLE => array('onDisablePackage', 255),
- );
- }
}
diff --git a/src/Plugin/GitHub/Plugin.php b/src/Plugin/GitHub/Plugin.php
index 4127305..ff03b36 100644
--- a/src/Plugin/GitHub/Plugin.php
+++ b/src/Plugin/GitHub/Plugin.php
@@ -31,23 +31,29 @@ public function configure(ContainerBuilder $container)
->addArgument(new Reference('router.url_generator'));
$container->getDefinition('packages.helper.sync')
- ->addMethodCall('registerAdapter', array(new Reference('packages.plugin.github.adapter')));
+ ->addMethodCall('registerAdapter', [new Reference('packages.plugin.github.adapter')]);
- $container->register('packages.plugin.github.package_subscriber', 'Terramar\Packages\Plugin\GitHub\PackageSubscriber')
+ $container->register('packages.plugin.github.package_subscriber',
+ 'Terramar\Packages\Plugin\GitHub\PackageSubscriber')
->addArgument(new Reference('packages.plugin.github.adapter'))
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('kernel.event_subscriber');
- $container->register('packages.plugin.github.remote_subscriber', 'Terramar\Packages\Plugin\GitHub\RemoteSubscriber')
+ $container->register('packages.plugin.github.remote_subscriber',
+ 'Terramar\Packages\Plugin\GitHub\RemoteSubscriber')
->addArgument(new Reference('packages.plugin.github.adapter'))
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('kernel.event_subscriber');
$container->getDefinition('packages.controller_manager')
- ->addMethodCall('registerController', array(Actions::REMOTE_NEW, 'Terramar\Packages\Plugin\GitHub\Controller::newAction'))
- ->addMethodCall('registerController', array(Actions::REMOTE_CREATE, 'Terramar\Packages\Plugin\GitHub\Controller::createAction'))
- ->addMethodCall('registerController', array(Actions::REMOTE_EDIT, 'Terramar\Packages\Plugin\GitHub\Controller::editAction'))
- ->addMethodCall('registerController', array(Actions::REMOTE_UPDATE, 'Terramar\Packages\Plugin\GitHub\Controller::updateAction'));
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_NEW, 'Terramar\Packages\Plugin\GitHub\Controller::newAction'])
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_CREATE, 'Terramar\Packages\Plugin\GitHub\Controller::createAction'])
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_EDIT, 'Terramar\Packages\Plugin\GitHub\Controller::editAction'])
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_UPDATE, 'Terramar\Packages\Plugin\GitHub\Controller::updateAction']);
}
/**
diff --git a/src/Plugin/GitHub/RemoteConfiguration.php b/src/Plugin/GitHub/RemoteConfiguration.php
index 460f324..f0af334 100644
--- a/src/Plugin/GitHub/RemoteConfiguration.php
+++ b/src/Plugin/GitHub/RemoteConfiguration.php
@@ -51,7 +51,7 @@ class RemoteConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
@@ -99,7 +99,7 @@ public function getUsername()
*/
public function setUsername($username)
{
- $this->username = (string) $username;
+ $this->username = (string)$username;
}
/**
@@ -115,6 +115,6 @@ public function getToken()
*/
public function setToken($token)
{
- $this->token = (string) $token;
+ $this->token = (string)$token;
}
}
diff --git a/src/Plugin/GitHub/RemoteSubscriber.php b/src/Plugin/GitHub/RemoteSubscriber.php
index 33c9054..92dff85 100644
--- a/src/Plugin/GitHub/RemoteSubscriber.php
+++ b/src/Plugin/GitHub/RemoteSubscriber.php
@@ -29,7 +29,7 @@ class RemoteSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param SyncAdapter $adapter
+ * @param SyncAdapter $adapter
* @param EntityManager $entityManager
*/
public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
@@ -38,6 +38,16 @@ public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::REMOTE_DISABLE => ['onDisableRemote', 255],
+ ];
+ }
+
/**
* @param RemoteEvent $event
*/
@@ -49,21 +59,11 @@ public function onDisableRemote(RemoteEvent $event)
}
$packages = $this->entityManager->getRepository('Terramar\Packages\Entity\Package')
- ->findBy(array('remote' => $remote));
+ ->findBy(['remote' => $remote]);
foreach ($packages as $package) {
$this->adapter->disableHook($package);
$package->setEnabled(false);
}
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::REMOTE_DISABLE => array('onDisableRemote', 255),
- );
- }
}
diff --git a/src/Plugin/GitHub/SyncAdapter.php b/src/Plugin/GitHub/SyncAdapter.php
index 8dce6b4..cd32448 100644
--- a/src/Plugin/GitHub/SyncAdapter.php
+++ b/src/Plugin/GitHub/SyncAdapter.php
@@ -13,8 +13,8 @@
use Github\Client;
use Github\HttpClient\Message\ResponseMediator;
use Nice\Router\UrlGeneratorInterface;
-use Terramar\Packages\Entity\Remote;
use Terramar\Packages\Entity\Package;
+use Terramar\Packages\Entity\Remote;
use Terramar\Packages\Helper\SyncAdapterInterface;
class SyncAdapter implements SyncAdapterInterface
@@ -31,8 +31,8 @@ class SyncAdapter implements SyncAdapterInterface
/**
* Constructor.
- *
- * @param EntityManager $entityManager
+ *
+ * @param EntityManager $entityManager
* @param UrlGeneratorInterface $urlGenerator
*/
public function __construct(EntityManager $entityManager, UrlGeneratorInterface $urlGenerator)
@@ -51,6 +51,14 @@ public function supports(Remote $remote)
return $remote->getAdapter() === $this->getName();
}
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return 'GitHub';
+ }
+
/**
* @param Remote $remote
*
@@ -58,40 +66,97 @@ public function supports(Remote $remote)
*/
public function synchronizePackages(Remote $remote)
{
- $existingPackages = $this->entityManager->getRepository('Terramar\Packages\Entity\Package')->findBy(array('remote' => $remote));
+ $existingPackages = $this->entityManager->getRepository('Terramar\Packages\Entity\Package')->findBy(['remote' => $remote]);
$projects = $this->getAllProjects($remote);
- $packages = array();
+ $packages = [];
foreach ($projects as $project) {
- if (!$this->packageExists($existingPackages, $project['id'])) {
+ $package = $this->getExistingPackage($existingPackages, $project['id']);
+ if ($package === null) {
$package = new Package();
$package->setExternalId($project['id']);
- $package->setName($project['name']);
- $package->setDescription($project['description']);
- $package->setFqn($project['full_name']);
- $package->setWebUrl($project['clone_url']);
- $package->setSshUrl($project['ssh_url']);
- $package->setHookExternalId('');
$package->setRemote($remote);
- $packages[] = $package;
}
+ $package->setName($project['name']);
+ $package->setDescription($project['description']);
+ $package->setFqn($project['full_name']);
+ $package->setWebUrl($project['clone_url']);
+ $package->setSshUrl($project['ssh_url']);
+ $packages[] = $package;
+ }
+
+ $removed = array_diff($existingPackages, $packages);
+ foreach ($removed as $package) {
+ $this->entityManager->remove($package);
}
return $packages;
}
+ private function getAllProjects(Remote $remote)
+ {
+ $client = $this->getClient($remote);
+
+ $projects = [];
+ $page = 1;
+ while (true) {
+ $response = $client->getHttpClient()->get('/user/repos', [
+ 'page' => $page,
+ 'per_page' => 100,
+ ]);
+ $projects = array_merge($projects, ResponseMediator::getContent($response));
+ $pageInfo = ResponseMediator::getPagination($response);
+ if (!isset($pageInfo['next'])) {
+ break;
+ }
+
+ ++$page;
+ }
+
+ return $projects;
+ }
+
+ private function getClient(Remote $remote)
+ {
+ $config = $this->getRemoteConfig($remote);
+
+ $client = new Client();
+ $client->authenticate($config->getToken(), Client::AUTH_HTTP_TOKEN);
+
+ return $client;
+ }
+
/**
- * @return string
+ * @param Remote $remote
+ *
+ * @return RemoteConfiguration
*/
- public function getName()
+ private function getRemoteConfig(Remote $remote)
{
- return 'GitHub';
+ return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')->findOneBy(['remote' => $remote]);
+ }
+
+ /**
+ * @param $existingPackages []Package
+ * @param $gitlabId
+ * @return Package|null
+ */
+ private function getExistingPackage($existingPackages, $gitlabId)
+ {
+ $res = array_filter($existingPackages, function (Package $package) use ($gitlabId) {
+ return (string)$package->getExternalId() === (string)$gitlabId;
+ });
+ if (count($res) === 0) {
+ return null;
+ }
+ return array_shift($res);
}
+
/**
* Enable a GitHub webhook for the given Package.
- *
+ *
* @param Package $package
*
* @return bool
@@ -103,28 +168,40 @@ public function enableHook(Package $package)
return true;
}
- $client = $this->getClient($package->getRemote());
- $url = 'repos/'.$package->getFqn().'/hooks';
- $response = $client->getHttpClient()->post($url, json_encode(array(
- 'name' => 'web',
- 'config' => array(
- 'url' => $this->urlGenerator->generate('webhook_receive', array('id' => $package->getId()), true),
- 'content_type' => 'json',
- ),
- 'events' => array('push', 'create'),
- )));
+ try {
+ $client = $this->getClient($package->getRemote());
+ $url = 'repos/' . $package->getFqn() . '/hooks';
+ $response = $client->getHttpClient()->post($url, json_encode([
+ 'name' => 'web',
+ 'config' => [
+ 'url' => $this->urlGenerator->generate('webhook_receive', ['id' => $package->getId()],
+ true),
+ 'content_type' => 'json',
+ ],
+ 'events' => ['push', 'create'],
+ ]));
+
+ $hook = ResponseMediator::getContent($response);
+
+ $package->setHookExternalId($hook['id']);
+ $config->setEnabled(true);
- $hook = ResponseMediator::getContent($response);
+ return true;
- $package->setHookExternalId($hook['id']);
- $config->setEnabled(true);
+ } catch (\Exception $e) {
+ // TODO: Log the exception
+ return false;
+ }
+ }
- return true;
+ private function getConfig(Package $package)
+ {
+ return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitHub\PackageConfiguration')->findOneBy(['package' => $package]);
}
/**
* Disable a GitHub webhook for the given Package.
- *
+ *
* @param Package $package
*
* @return bool
@@ -136,70 +213,24 @@ public function disableHook(Package $package)
return true;
}
- if ($package->getHookExternalId()) {
- $client = $this->getClient($package->getRemote());
- $url = 'repos/'.$package->getFqn().'/hooks/'.$package->getHookExternalId();
- $client->getHttpClient()->delete($url);
- }
-
- $package->setHookExternalId('');
- $config->setEnabled(false);
-
- return true;
- }
-
- private function getConfig(Package $package)
- {
- return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitHub\PackageConfiguration')->findOneBy(array('package' => $package));
- }
-
- /**
- * @param Remote $remote
- *
- * @return RemoteConfiguration
- */
- private function getRemoteConfig(Remote $remote)
- {
- return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')->findOneBy(array('remote' => $remote));
- }
-
- private function getAllProjects(Remote $remote)
- {
- $client = $this->getClient($remote);
-
- $projects = array();
- $page = 1;
- while (true) {
- $response = $client->getHttpClient()->get('/user/repos', array(
- 'page' => $page,
- 'per_page' => 100,
- ));
- $projects = array_merge($projects, ResponseMediator::getContent($response));
- $pageInfo = ResponseMediator::getPagination($response);
- if (!isset($pageInfo['next'])) {
- break;
+ try {
+ if ($package->getHookExternalId()) {
+ $client = $this->getClient($package->getRemote());
+ $url = 'repos/' . $package->getFqn() . '/hooks/' . $package->getHookExternalId();
+ $client->getHttpClient()->delete($url);
}
- ++$page;
- }
+ $package->setHookExternalId('');
+ $config->setEnabled(false);
- return $projects;
- }
-
- private function getClient(Remote $remote)
- {
- $config = $this->getRemoteConfig($remote);
-
- $client = new Client();
- $client->authenticate($config->getToken(), Client::AUTH_HTTP_TOKEN);
+ return true;
- return $client;
- }
+ } catch (\Exception $e) {
+ // TODO: Log the exception
+ $package->setHookExternalId('');
+ $config->setEnabled(false);
- private function packageExists($existingPackages, $githubId)
- {
- return count(array_filter($existingPackages, function (Package $package) use ($githubId) {
- return (string) $package->getExternalId() === (string) $githubId;
- })) > 0;
+ return false;
+ }
}
}
diff --git a/src/Plugin/GitLab/Controller.php b/src/Plugin/GitLab/Controller.php
index 0e4b772..ce7d21c 100644
--- a/src/Plugin/GitLab/Controller.php
+++ b/src/Plugin/GitLab/Controller.php
@@ -44,22 +44,22 @@ public function editAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')->findOneBy(array(
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')->findOneBy([
'remote' => $id,
- ));
+ ]);
- return new Response($app->get('twig')->render('Plugin/GitLab/edit.html.twig', array(
+ return new Response($app->get('twig')->render('Plugin/GitLab/edit.html.twig', [
'config' => $config ?: new RemoteConfiguration(),
- )));
+ ]));
}
public function updateAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')->findOneBy(array(
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')->findOneBy([
'remote' => $id,
- ));
+ ]);
if (!$config) {
return new Response();
diff --git a/src/Plugin/GitLab/PackageConfiguration.php b/src/Plugin/GitLab/PackageConfiguration.php
index d214f59..60ecfa1 100644
--- a/src/Plugin/GitLab/PackageConfiguration.php
+++ b/src/Plugin/GitLab/PackageConfiguration.php
@@ -41,7 +41,7 @@ class PackageConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
diff --git a/src/Plugin/GitLab/PackageSubscriber.php b/src/Plugin/GitLab/PackageSubscriber.php
index ea5afe3..ec3a9a0 100644
--- a/src/Plugin/GitLab/PackageSubscriber.php
+++ b/src/Plugin/GitLab/PackageSubscriber.php
@@ -29,7 +29,7 @@ class PackageSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param SyncAdapter $adapter
+ * @param SyncAdapter $adapter
* @param EntityManager $entityManager
*/
public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
@@ -38,6 +38,18 @@ public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::PACKAGE_CREATE => ['onCreatePackage', 255],
+ Events::PACKAGE_ENABLE => ['onEnablePackage', 255],
+ Events::PACKAGE_DISABLE => ['onDisablePackage', 255],
+ ];
+ }
+
/**
* @param PackageEvent $event
*/
@@ -45,7 +57,7 @@ public function onCreatePackage(PackageEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\GitLab\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config) {
$config = new PackageConfiguration();
@@ -80,16 +92,4 @@ public function onDisablePackage(PackageEvent $event)
$this->adapter->disableHook($package);
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::PACKAGE_CREATE => array('onCreatePackage', 255),
- Events::PACKAGE_ENABLE => array('onEnablePackage', 255),
- Events::PACKAGE_DISABLE => array('onDisablePackage', 255),
- );
- }
}
diff --git a/src/Plugin/GitLab/Plugin.php b/src/Plugin/GitLab/Plugin.php
index 5d7e166..1abb269 100644
--- a/src/Plugin/GitLab/Plugin.php
+++ b/src/Plugin/GitLab/Plugin.php
@@ -31,23 +31,29 @@ public function configure(ContainerBuilder $container)
->addArgument(new Reference('router.url_generator'));
$container->getDefinition('packages.helper.sync')
- ->addMethodCall('registerAdapter', array(new Reference('packages.plugin.gitlab.adapter')));
+ ->addMethodCall('registerAdapter', [new Reference('packages.plugin.gitlab.adapter')]);
- $container->register('packages.plugin.gitlab.package_subscriber', 'Terramar\Packages\Plugin\GitLab\PackageSubscriber')
+ $container->register('packages.plugin.gitlab.package_subscriber',
+ 'Terramar\Packages\Plugin\GitLab\PackageSubscriber')
->addArgument(new Reference('packages.plugin.gitlab.adapter'))
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('kernel.event_subscriber');
- $container->register('packages.plugin.gitlab.remote_subscriber', 'Terramar\Packages\Plugin\GitLab\RemoteSubscriber')
+ $container->register('packages.plugin.gitlab.remote_subscriber',
+ 'Terramar\Packages\Plugin\GitLab\RemoteSubscriber')
->addArgument(new Reference('packages.plugin.gitlab.adapter'))
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('kernel.event_subscriber');
$container->getDefinition('packages.controller_manager')
- ->addMethodCall('registerController', array(Actions::REMOTE_NEW, 'Terramar\Packages\Plugin\GitLab\Controller::newAction'))
- ->addMethodCall('registerController', array(Actions::REMOTE_CREATE, 'Terramar\Packages\Plugin\GitLab\Controller::createAction'))
- ->addMethodCall('registerController', array(Actions::REMOTE_EDIT, 'Terramar\Packages\Plugin\GitLab\Controller::editAction'))
- ->addMethodCall('registerController', array(Actions::REMOTE_UPDATE, 'Terramar\Packages\Plugin\GitLab\Controller::updateAction'));
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_NEW, 'Terramar\Packages\Plugin\GitLab\Controller::newAction'])
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_CREATE, 'Terramar\Packages\Plugin\GitLab\Controller::createAction'])
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_EDIT, 'Terramar\Packages\Plugin\GitLab\Controller::editAction'])
+ ->addMethodCall('registerController',
+ [Actions::REMOTE_UPDATE, 'Terramar\Packages\Plugin\GitLab\Controller::updateAction']);
}
/**
diff --git a/src/Plugin/GitLab/RemoteConfiguration.php b/src/Plugin/GitLab/RemoteConfiguration.php
index 248f08a..b23edd5 100644
--- a/src/Plugin/GitLab/RemoteConfiguration.php
+++ b/src/Plugin/GitLab/RemoteConfiguration.php
@@ -51,7 +51,7 @@ class RemoteConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
@@ -99,7 +99,7 @@ public function getUrl()
*/
public function setUrl($url)
{
- $this->url = (string) $url;
+ $this->url = (string)$url;
}
/**
@@ -115,6 +115,6 @@ public function getToken()
*/
public function setToken($token)
{
- $this->token = (string) $token;
+ $this->token = (string)$token;
}
}
diff --git a/src/Plugin/GitLab/RemoteSubscriber.php b/src/Plugin/GitLab/RemoteSubscriber.php
index 4edca54..5caefad 100644
--- a/src/Plugin/GitLab/RemoteSubscriber.php
+++ b/src/Plugin/GitLab/RemoteSubscriber.php
@@ -29,7 +29,7 @@ class RemoteSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param SyncAdapter $adapter
+ * @param SyncAdapter $adapter
* @param EntityManager $entityManager
*/
public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
@@ -38,6 +38,16 @@ public function __construct(SyncAdapter $adapter, EntityManager $entityManager)
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::REMOTE_DISABLE => ['onDisableRemote', 255],
+ ];
+ }
+
/**
* @param RemoteEvent $event
*/
@@ -49,21 +59,11 @@ public function onDisableRemote(RemoteEvent $event)
}
$packages = $this->entityManager->getRepository('Terramar\Packages\Entity\Package')
- ->findBy(array('remote' => $remote));
+ ->findBy(['remote' => $remote]);
foreach ($packages as $package) {
$this->adapter->disableHook($package);
$package->setEnabled(false);
}
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::REMOTE_DISABLE => array('onDisableRemote', 255),
- );
- }
}
diff --git a/src/Plugin/GitLab/SyncAdapter.php b/src/Plugin/GitLab/SyncAdapter.php
index 841f165..8e96f4e 100644
--- a/src/Plugin/GitLab/SyncAdapter.php
+++ b/src/Plugin/GitLab/SyncAdapter.php
@@ -13,8 +13,8 @@
use Gitlab\Client;
use Gitlab\Model\Project;
use Nice\Router\UrlGeneratorInterface;
-use Terramar\Packages\Entity\Remote;
use Terramar\Packages\Entity\Package;
+use Terramar\Packages\Entity\Remote;
use Terramar\Packages\Helper\SyncAdapterInterface;
class SyncAdapter implements SyncAdapterInterface
@@ -31,8 +31,8 @@ class SyncAdapter implements SyncAdapterInterface
/**
* Constructor.
- *
- * @param EntityManager $entityManager
+ *
+ * @param EntityManager $entityManager
* @param UrlGeneratorInterface $urlGenerator
*/
public function __construct(EntityManager $entityManager, UrlGeneratorInterface $urlGenerator)
@@ -51,6 +51,14 @@ public function supports(Remote $remote)
return $remote->getAdapter() === $this->getName();
}
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return 'GitLab';
+ }
+
/**
* @param Remote $remote
*
@@ -58,102 +66,33 @@ public function supports(Remote $remote)
*/
public function synchronizePackages(Remote $remote)
{
- $existingPackages = $this->entityManager->getRepository('Terramar\Packages\Entity\Package')->findBy(array('remote' => $remote));
+ /** @var []Package $existingPackages */
+ $existingPackages = $this->entityManager->getRepository('Terramar\Packages\Entity\Package')->findBy(['remote' => $remote]);
$projects = $this->getAllProjects($remote);
- $packages = array();
+ $packages = [];
foreach ($projects as $project) {
- if (!$this->packageExists($existingPackages, $project['id'])) {
+ $package = $this->getExistingPackage($existingPackages, $project['id']);
+ if ($package === null) {
$package = new Package();
$package->setExternalId($project['id']);
- $package->setName($project['name']);
- $package->setDescription($project['description']);
- $package->setFqn($project['path_with_namespace']);
- $package->setWebUrl($project['web_url']);
- $package->setSshUrl($project['ssh_url_to_repo']);
- $package->setHookExternalId('');
$package->setRemote($remote);
- $packages[] = $package;
}
+ $package->setName($project['name']);
+ $package->setDescription($project['description']);
+ $package->setFqn($project['path_with_namespace']);
+ $package->setWebUrl($project['web_url']);
+ $package->setSshUrl($project['ssh_url_to_repo']);
+ $packages[] = $package;
}
- return $packages;
- }
-
- /**
- * @return string
- */
- public function getName()
- {
- return 'GitLab';
- }
-
- /**
- * Enable a GitLab webhook for the given Package.
- *
- * @param Package $package
- *
- * @return bool
- */
- public function enableHook(Package $package)
- {
- $config = $this->getConfig($package);
- if ($config->isEnabled()) {
- return true;
+ $removed = array_diff($existingPackages, $packages);
+ foreach ($removed as $package) {
+ $this->entityManager->remove($package);
}
- $client = $this->getClient($package->getRemote());
- $project = Project::fromArray($client, (array) $client->api('projects')->show($package->getExternalId()));
- $hook = $project->addHook(
- $this->urlGenerator->generate('webhook_receive', array('id' => $package->getId()), true),
- array('push_events' => true, 'tag_push_events' => true)
- );
- $package->setHookExternalId($hook->id);
- $config->setEnabled(true);
-
- return true;
- }
-
- /**
- * Disable a GitLab webhook for the given Package.
- *
- * @param Package $package
- *
- * @return bool
- */
- public function disableHook(Package $package)
- {
- $config = $this->getConfig($package);
- if (!$config->isEnabled()) {
- return true;
- }
-
- if ($package->getHookExternalId()) {
- $client = $this->getClient($package->getRemote());
- $project = Project::fromArray($client, (array) $client->api('projects')->show($package->getExternalId()));
- $project->removeHook($package->getHookExternalId());
- }
-
- $package->setHookExternalId('');
- $config->setEnabled(false);
-
- return true;
- }
-
- private function getConfig(Package $package)
- {
- return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitLab\PackageConfiguration')->findOneBy(array('package' => $package));
- }
-
- /**
- * @param Remote $remote
- *
- * @return RemoteConfiguration
- */
- private function getRemoteConfig(Remote $remote)
- {
- return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')->findOneBy(array('remote' => $remote));
+ return $packages;
}
private function getAllProjects(Remote $remote)
@@ -161,7 +100,7 @@ private function getAllProjects(Remote $remote)
$client = $this->getClient($remote);
$isAdmin = $client->api('users')->me()['is_admin'];
- $projects = array();
+ $projects = [];
$page = 1;
while (true) {
@@ -191,16 +130,107 @@ private function getClient(Remote $remote)
{
$config = $this->getRemoteConfig($remote);
- $client = new Client(rtrim($config->getUrl(), '/').'/api/v3/');
+ $client = new Client(rtrim($config->getUrl(), '/') . '/api/v3/');
$client->authenticate($config->getToken(), Client::AUTH_HTTP_TOKEN);
return $client;
}
- private function packageExists($existingPackages, $gitlabId)
+ /**
+ * @param Remote $remote
+ *
+ * @return RemoteConfiguration
+ */
+ private function getRemoteConfig(Remote $remote)
+ {
+ return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')->findOneBy(['remote' => $remote]);
+ }
+
+ /**
+ * @param $existingPackages
+ * @param $gitlabId
+ * @return Package|null
+ */
+ private function getExistingPackage($existingPackages, $gitlabId)
+ {
+ $res = array_filter($existingPackages, function (Package $package) use ($gitlabId) {
+ return (string)$package->getExternalId() === (string)$gitlabId;
+ });
+ if (count($res) === 0) {
+ return null;
+ }
+ return array_shift($res);
+ }
+
+ /**
+ * Enable a GitLab webhook for the given Package.
+ *
+ * @param Package $package
+ *
+ * @return bool
+ */
+ public function enableHook(Package $package)
{
- return count(array_filter($existingPackages, function (Package $package) use ($gitlabId) {
- return (string) $package->getExternalId() === (string) $gitlabId;
- })) > 0;
+ $config = $this->getConfig($package);
+ if ($config->isEnabled()) {
+ return true;
+ }
+ try {
+ $client = $this->getClient($package->getRemote());
+ $project = Project::fromArray($client, (array)$client->api('projects')->show($package->getExternalId()));
+ $hook = $project->addHook(
+ $this->urlGenerator->generate('webhook_receive', ['id' => $package->getId()], true),
+ ['push_events' => true, 'tag_push_events' => true]
+ );
+ $package->setHookExternalId($hook->id);
+ $config->setEnabled(true);
+
+ return true;
+
+ } catch (\Exception $e) {
+ // TODO: Log the exception
+ return false;
+ }
+ }
+
+ private function getConfig(Package $package)
+ {
+ return $this->entityManager->getRepository('Terramar\Packages\Plugin\GitLab\PackageConfiguration')->findOneBy(['package' => $package]);
+ }
+
+ /**
+ * Disable a GitLab webhook for the given Package.
+ *
+ * @param Package $package
+ *
+ * @return bool
+ */
+ public function disableHook(Package $package)
+ {
+ $config = $this->getConfig($package);
+ if (!$config->isEnabled()) {
+ return true;
+ }
+
+ try {
+ if ($package->getHookExternalId()) {
+ $client = $this->getClient($package->getRemote());
+ $project = Project::fromArray($client,
+ (array)$client->api('projects')->show($package->getExternalId()));
+ $project->removeHook($package->getHookExternalId());
+ }
+
+ $package->setHookExternalId('');
+ $config->setEnabled(false);
+
+ return true;
+
+ } catch (\Exception $e) {
+ // TODO: Log the exception
+ $package->setHookExternalId('');
+ $config->setEnabled(false);
+
+ return false;
+ }
}
}
diff --git a/src/Plugin/PluginInterface.php b/src/Plugin/PluginInterface.php
index 3aaed32..c9f8022 100644
--- a/src/Plugin/PluginInterface.php
+++ b/src/Plugin/PluginInterface.php
@@ -14,7 +14,7 @@
/**
* PluginInterface defines the implementation of a Packages plugin.
*
- * @see http://docs.terramarlabs.com/packages/3.1/plugins/creating-a-plugin
+ * @see http://docs.terramarlabs.com/packages/3.2/plugins/creating-a-plugin
*/
interface PluginInterface
{
@@ -30,14 +30,14 @@ public function configure(ContainerBuilder $container);
/**
* Get the plugin name.
- *
+ *
* @return string
*/
public function getName();
/**
* Get a string identifying the plugin's (or underlying tool's) version.
- *
+ *
* @return string|null
*/
public function getVersion();
diff --git a/src/Plugin/RouterPluginInterface.php b/src/Plugin/RouterPluginInterface.php
new file mode 100644
index 0000000..47b85b8
--- /dev/null
+++ b/src/Plugin/RouterPluginInterface.php
@@ -0,0 +1,32 @@
+get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')->findOneBy(array(
- 'package' => $id,
- ));
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')->findOneBy([
+ 'package' => $id,
+ ]);
- return new Response($app->get('twig')->render('Plugin/Sami/edit.html.twig', array(
- 'config' => $config,
- )));
+ return new Response($app->get('twig')->render('Plugin/Sami/edit.html.twig', [
+ 'config' => $config,
+ ]));
}
public function updateAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')->findOneBy(array(
- 'package' => $id,
- ));
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')->findOneBy([
+ 'package' => $id,
+ ]);
$config->setEnabled($request->get('sami_enabled') ? true : false);
$config->setTitle($request->get('sami_title'));
diff --git a/src/Plugin/Sami/EventSubscriber.php b/src/Plugin/Sami/EventSubscriber.php
index 6ad7c4b..9c84f42 100644
--- a/src/Plugin/Sami/EventSubscriber.php
+++ b/src/Plugin/Sami/EventSubscriber.php
@@ -32,7 +32,7 @@ class EventSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param ResqueHelper $resqueHelper
+ * @param ResqueHelper $resqueHelper
* @param EntityManager $entityManager
*/
public function __construct(ResqueHelper $resqueHelper, EntityManager $entityManager)
@@ -41,6 +41,17 @@ public function __construct(ResqueHelper $resqueHelper, EntityManager $entityMan
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::PACKAGE_CREATE => ['onCreatePackage', 0],
+ CloneProjectEvents::PACKAGE_CLONED => ['onClonePackage', 0],
+ ];
+ }
+
/**
* @param PackageCloneEvent $event
*/
@@ -48,7 +59,7 @@ public function onClonePackage(PackageCloneEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config || !$config->isEnabled() || !$package->isEnabled()) {
return;
@@ -59,7 +70,7 @@ public function onClonePackage(PackageCloneEvent $event)
$this->entityManager->persist($config);
$this->entityManager->flush($config);
- $this->resqueHelper->enqueue('default', 'Terramar\Packages\Plugin\Sami\UpdateJob', array('id' => $package->getId()));
+ $this->resqueHelper->enqueue('default', 'Terramar\Packages\Plugin\Sami\UpdateJob', ['id' => $package->getId()]);
}
/**
@@ -69,7 +80,7 @@ public function onCreatePackage(PackageEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config) {
$config = new PackageConfiguration();
@@ -78,15 +89,4 @@ public function onCreatePackage(PackageEvent $event)
$this->entityManager->persist($config);
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::PACKAGE_CREATE => array('onCreatePackage', 0),
- CloneProjectEvents::PACKAGE_CLONED => array('onClonePackage', 0),
- );
- }
}
diff --git a/src/Plugin/Sami/PackageConfiguration.php b/src/Plugin/Sami/PackageConfiguration.php
index f5dbcdf..5555366 100644
--- a/src/Plugin/Sami/PackageConfiguration.php
+++ b/src/Plugin/Sami/PackageConfiguration.php
@@ -81,7 +81,7 @@ class PackageConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
@@ -129,7 +129,7 @@ public function getRepositoryPath()
*/
public function setRepositoryPath($repositoryPath)
{
- $this->repositoryPath = (string) $repositoryPath;
+ $this->repositoryPath = (string)$repositoryPath;
}
/**
@@ -145,7 +145,7 @@ public function getRemoteRepoPath()
*/
public function setRemoteRepoPath($remoteRepoPath)
{
- $this->remoteRepoPath = (string) $remoteRepoPath;
+ $this->remoteRepoPath = (string)$remoteRepoPath;
}
/**
@@ -161,7 +161,7 @@ public function getTitle()
*/
public function setTitle($title)
{
- $this->title = (string) $title;
+ $this->title = (string)$title;
}
/**
@@ -177,7 +177,7 @@ public function getTheme()
*/
public function setTheme($theme)
{
- $this->theme = (string) $theme;
+ $this->theme = (string)$theme;
}
/**
@@ -193,7 +193,7 @@ public function getTags()
*/
public function setTags($tags)
{
- $this->tags = (string) $tags;
+ $this->tags = (string)$tags;
}
/**
@@ -209,7 +209,7 @@ public function getRefs()
*/
public function setRefs($refs)
{
- $this->refs = (string) $refs;
+ $this->refs = (string)$refs;
}
/**
@@ -225,7 +225,7 @@ public function getDocsPath()
*/
public function setDocsPath($docsPath)
{
- $this->docsPath = (string) $docsPath;
+ $this->docsPath = (string)$docsPath;
}
/**
@@ -241,6 +241,6 @@ public function getTemplatesDir()
*/
public function setTemplatesDir($templatesDir)
{
- $this->templatesDir = (string) $templatesDir;
+ $this->templatesDir = (string)$templatesDir;
}
}
diff --git a/src/Plugin/Sami/Plugin.php b/src/Plugin/Sami/Plugin.php
index 4dcbdca..e8e8692 100644
--- a/src/Plugin/Sami/Plugin.php
+++ b/src/Plugin/Sami/Plugin.php
@@ -33,8 +33,10 @@ public function configure(ContainerBuilder $container)
->addTag('kernel.event_subscriber');
$container->getDefinition('packages.controller_manager')
- ->addMethodCall('registerController', array(Actions::PACKAGE_EDIT, 'Terramar\Packages\Plugin\Sami\Controller::editAction'))
- ->addMethodCall('registerController', array(Actions::PACKAGE_UPDATE, 'Terramar\Packages\Plugin\Sami\Controller::updateAction'));
+ ->addMethodCall('registerController',
+ [Actions::PACKAGE_EDIT, 'Terramar\Packages\Plugin\Sami\Controller::editAction'])
+ ->addMethodCall('registerController',
+ [Actions::PACKAGE_UPDATE, 'Terramar\Packages\Plugin\Sami\Controller::updateAction']);
}
/**
diff --git a/src/Plugin/Sami/UpdateJob.php b/src/Plugin/Sami/UpdateJob.php
index c84b8cb..429afd6 100644
--- a/src/Plugin/Sami/UpdateJob.php
+++ b/src/Plugin/Sami/UpdateJob.php
@@ -17,22 +17,6 @@
class UpdateJob extends ContainerAwareJob
{
- /**
- * @return string
- */
- private function getCacheDir(Package $package)
- {
- return $this->getContainer()->getParameter('app.cache_dir').'/sami/'.$package->getFqn();
- }
-
- /**
- * @return EntityManager
- */
- private function getEntityManager()
- {
- return $this->getContainer()->get('doctrine.orm.entity_manager');
- }
-
public function run($args)
{
$package = $this->getEntityManager()->find('Terramar\Packages\Entity\Package', $args['id']);
@@ -41,7 +25,7 @@ public function run($args)
}
$config = $this->getEntityManager()->getRepository('Terramar\Packages\Plugin\Sami\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config) {
throw new \RuntimeException('Invalid project configuration');
@@ -53,12 +37,12 @@ public function run($args)
mkdir($cachePath, 0777, true);
}
- $configFilePath = $cachePath.'/config.php';
+ $configFilePath = $cachePath . '/config.php';
$this->writeConfig($configFilePath, $package, $config);
echo "Wrote config file to: $configFilePath\n";
$finder = new PhpExecutableFinder();
- $builder = new ProcessBuilder(array('vendor/bin/sami.php', 'update', $configFilePath));
+ $builder = new ProcessBuilder(['vendor/bin/sami.php', 'update', $configFilePath]);
$builder->setEnv('HOME', $this->getContainer()->getParameter('app.root_dir'));
$builder->setPrefix($finder->find());
@@ -73,15 +57,15 @@ public function run($args)
if ($config->getRemoteRepoPath()) {
echo "Updating configured remote with doc changes...\n";
- $localRepoPath = $cachePath.'/remote';
+ $localRepoPath = $cachePath . '/remote';
$this->emptyAndRemoveDirectory($localRepoPath);
- $buildPath = $cachePath.'/build';
+ $buildPath = $cachePath . '/build';
- $builder = new ProcessBuilder(array(
+ $builder = new ProcessBuilder([
'clone',
$config->getRemoteRepoPath(),
$localRepoPath,
- ));
+ ]);
$builder->setPrefix('git');
$process = $builder->getProcess();
$process->run(function ($type, $message) {
@@ -89,15 +73,15 @@ public function run($args)
});
if (!$process->isSuccessful()) {
- throw new \RuntimeException('Unable to clone remote repository "'.$config->getRemoteRepoPath()."\"\n");
+ throw new \RuntimeException('Unable to clone remote repository "' . $config->getRemoteRepoPath() . "\"\n");
}
echo "Copying generated files into repository...\n";
- $builder = new ProcessBuilder(array(
+ $builder = new ProcessBuilder([
'-R',
- $buildPath.'/',
+ $buildPath . '/',
'.',
- ));
+ ]);
$builder->setPrefix('cp');
$process = $builder->getProcess();
$process->setWorkingDirectory($localRepoPath);
@@ -106,10 +90,10 @@ public function run($args)
});
echo "Adding all files...\n";
- $builder = new ProcessBuilder(array(
+ $builder = new ProcessBuilder([
'add',
'.',
- ));
+ ]);
$builder->setPrefix('git');
$process = $builder->getProcess();
$process->setWorkingDirectory($localRepoPath);
@@ -118,11 +102,11 @@ public function run($args)
});
echo "Committing...\n";
- $builder = new ProcessBuilder(array(
+ $builder = new ProcessBuilder([
'commit',
'-m',
'Automated commit',
- ));
+ ]);
$builder->setPrefix('git');
$process = $builder->getProcess();
$process->setWorkingDirectory($localRepoPath);
@@ -131,10 +115,10 @@ public function run($args)
});
echo "Pushing...\n";
- $builder = new ProcessBuilder(array(
+ $builder = new ProcessBuilder([
'push',
'origin',
- ));
+ ]);
$builder->setPrefix('git');
$process = $builder->getProcess();
$process->setWorkingDirectory($localRepoPath);
@@ -144,25 +128,35 @@ public function run($args)
}
}
- private function getRefs(PackageConfiguration $config)
+ /**
+ * @return EntityManager
+ */
+ private function getEntityManager()
{
- return array_map(function ($value) {
- return explode(':', $value);
- }, explode(',', $config->getRefs()));
+ return $this->getContainer()->get('doctrine.orm.entity_manager');
+ }
+
+ /**
+ * @return string
+ */
+ private function getCacheDir(Package $package)
+ {
+ return $this->getContainer()->getParameter('app.cache_dir') . '/sami/' . $package->getFqn();
}
private function writeConfig($configFilePath, Package $package, PackageConfiguration $config)
{
$cachePath = $this->getCacheDir($package);
- $tagsCode = $config->getTags() ? ' ->addFromTags(\''.implode('\',\'', explode(',', $config->getTags())).'\)'.PHP_EOL : '';
+ $tagsCode = $config->getTags() ? ' ->addFromTags(\'' . implode('\',\'',
+ explode(',', $config->getTags())) . '\)' . PHP_EOL : '';
$refsCode = '';
foreach ($this->getRefs($config) as $ref) {
- $refsCode .= ' ->add(\''.$ref[0].'\', \''.$ref[1].'\')'.PHP_EOL;
+ $refsCode .= ' ->add(\'' . $ref[0] . '\', \'' . $ref[1] . '\')' . PHP_EOL;
}
$templatesCode = '';
if ($templatesDir = $config->getTemplatesDir()) {
- $templatesCode = ' \'templates_dir\' => array(\''.$templatesDir.'\'),'."\n";
+ $templatesCode = ' \'templates_dir\' => array(\'' . $templatesDir . '\'),' . "\n";
}
$code = <<getRefs()));
+ }
+
private function emptyAndRemoveDirectory($directory)
{
- $files = array_diff(scandir($directory), array('.', '..'));
+ $files = array_diff(scandir($directory), ['.', '..']);
foreach ($files as $file) {
(is_dir("$directory/$file")) ? $this->emptyAndRemoveDirectory("$directory/$file") : unlink("$directory/$file");
}
diff --git a/src/Plugin/Satis/Command/BuildCommand.php b/src/Plugin/Satis/Command/BuildCommand.php
index 21081ca..b9ef9a1 100644
--- a/src/Plugin/Satis/Command/BuildCommand.php
+++ b/src/Plugin/Satis/Command/BuildCommand.php
@@ -11,11 +11,12 @@
use Composer\Satis\Console\Command\BuildCommand as BaseCommand;
use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+use Terramar\Packages\Console\Application;
/**
* Wraps Satis build command.
@@ -27,6 +28,16 @@ class BuildCommand extends BaseCommand implements ContainerAwareInterface
*/
protected $container;
+ /**
+ * Sets the container.
+ *
+ * @param ContainerInterface|null $container A ContainerInterface instance or null
+ */
+ public function setContainer(ContainerInterface $container = null)
+ {
+ $this->container = $container;
+ }
+
protected function configure()
{
parent::configure();
@@ -34,7 +45,8 @@ protected function configure()
$this->setName('satis:build');
$def = $this->getDefinition();
$args = $def->getArguments();
- $args['file'] = new InputArgument('file', InputArgument::OPTIONAL, 'Satis configuration file. If left blank, one will be generated.');
+ $args['file'] = new InputArgument('file', InputArgument::OPTIONAL,
+ 'Satis configuration file. If left blank, one will be generated.');
$def->setArguments($args);
}
@@ -50,16 +62,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$input->setArgument('file', $configFile);
}
- parent::execute($input, $output);
- }
+ $input->setOption('skip-errors', true);
- /**
- * Sets the container.
- *
- * @param ContainerInterface|null $container A ContainerInterface instance or null
- */
- public function setContainer(ContainerInterface $container = null)
- {
- $this->container = $container;
+ $app = $this->getApplication();
+ if ($app instanceof Application) {
+ $this->setIO($app->getIO());
+ }
+
+ parent::execute($input, $output);
}
}
diff --git a/src/Plugin/Satis/Command/UpdateCommand.php b/src/Plugin/Satis/Command/UpdateCommand.php
index 5d05d0f..514ca95 100644
--- a/src/Plugin/Satis/Command/UpdateCommand.php
+++ b/src/Plugin/Satis/Command/UpdateCommand.php
@@ -10,15 +10,17 @@
namespace Terramar\Packages\Plugin\Satis\Command;
use Symfony\Component\Console\Input\ArrayInput;
+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\Console\Input\InputArgument;
use Terramar\Packages\Console\Command\ContainerAwareCommand;
-use Terramar\Packages\Entity\Package;
/**
* Updates the projects satis.json.
+ *
+ * @deprecated
+ * @see BuildCommand
*/
class UpdateCommand extends ContainerAwareCommand
{
@@ -27,24 +29,27 @@ protected function configure()
$this
->setName('satis:update')
->setDescription('Updates the project\'s satis.json file')
- ->setDefinition(array(
+ ->setDefinition([
new InputArgument('scan-dir', InputArgument::OPTIONAL, 'Directory to look for git repositories'),
new InputOption('build', 'b', InputOption::VALUE_NONE, 'Build packages.json after update'),
new InputOption('skip-errors', null, InputOption::VALUE_NONE, 'Skip Download or Archive errors'),
- ));
+ ]);
}
/**
- * @param InputInterface $input The input instance
+ * @param InputInterface $input The input instance
* @param OutputInterface $output The output instance
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $output->writeln(array('WARNING: The satis:update command is deprecated. It does not do anything functional but remains for backwards compatibility.', ''));
+ $output->writeln([
+ 'WARNING: The satis:update command is deprecated. It does not do anything functional but remains for backwards compatibility.',
+ '',
+ ]);
$configHelper = $this->container->get('packages.plugin.satis.config_helper');
$configFile = $configHelper->generateConfiguration();
- $skipErrors = (bool) $input->getOption('skip-errors');
+ $skipErrors = (bool)$input->getOption('skip-errors');
$data = json_decode(file_get_contents($configFile), true);
@@ -52,13 +57,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$output->writeln(sprintf('Found repository: %s ', $repository['url']));
}
- $output->writeln(array(
+ $output->writeln([
'satis.json updated successfully. ',
- ));
+ ]);
- $output->writeln(array(
+ $output->writeln([
sprintf('Found %s repositories. ', count($data['repositories'])),
- ));
+ ]);
if ($input->getOption('build')) {
$command = $this->getApplication()->find('satis:build');
diff --git a/src/Plugin/Satis/ConfigurationHelper.php b/src/Plugin/Satis/ConfigurationHelper.php
index 7abc21a..99c49b5 100644
--- a/src/Plugin/Satis/ConfigurationHelper.php
+++ b/src/Plugin/Satis/ConfigurationHelper.php
@@ -10,8 +10,8 @@
namespace Terramar\Packages\Plugin\Satis;
use Doctrine\ORM\EntityManager;
+use Nice\Router\UrlGeneratorInterface;
use Symfony\Component\Filesystem\Filesystem;
-use Terramar\Packages\Entity\Package;
class ConfigurationHelper
{
@@ -25,6 +25,11 @@ class ConfigurationHelper
*/
private $entityManager;
+ /**
+ * @var \Nice\Router\UrlGeneratorInterface
+ */
+ private $urlGenerator;
+
/**
* @var string
*/
@@ -42,29 +47,47 @@ class ConfigurationHelper
/**
* @param EntityManager $entityManager
- * @param string $rootDir
- * @param $cacheDir
+ * @param UrlGeneratorInterface $urlGenerator
+ * @paramstring $rootDir
+ * @param string $cacheDir
+ * @param array $config
*/
- public function __construct(EntityManager $entityManager, $rootDir, $cacheDir, array $config)
- {
+ public function __construct(
+ EntityManager $entityManager,
+ UrlGeneratorInterface $urlGenerator,
+ $rootDir,
+ $cacheDir,
+ array $config
+ ) {
$this->entityManager = $entityManager;
+ $this->urlGenerator = $urlGenerator;
$this->filesystem = new Filesystem();
$this->rootDir = $rootDir;
$this->cacheDir = $cacheDir;
$this->config = $config;
}
- public function generateConfiguration(array $options = array())
+ public function generateConfiguration(array $options = [])
{
- $data = array_merge($options, array(
- 'name' => $this->config['name'],
- 'homepage' => $this->config['homepage'],
- 'output-dir' => realpath($this->config['output_dir']),
- 'repositories' => array(),
- 'output-html' => false,
- 'require-dependencies' => true,
+ $data = array_merge($options, [
+ 'name' => $this->config['name'],
+ 'homepage' => $this->config['homepage'],
+ 'output-dir' => realpath($this->config['output_dir']),
+ 'repositories' => [],
+ 'output-html' => false,
+ 'require-dependencies' => true,
'require-dev-dependencies' => true,
- ));
+ 'config' => ['gitlab-domains' => []],
+ ]);
+
+ if (isset($this->config['archive']) && $this->config['archive'] === true) {
+ $data['archive'] = [
+ 'directory' => 'dist',
+ 'format' => 'tar',
+ 'prefix-url' => $this->config['base_path'],
+ 'skip-dev' => true,
+ ];
+ }
$packages = $this->entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')
->createQueryBuilder('pc')
@@ -74,23 +97,59 @@ public function generateConfiguration(array $options = array())
->getQuery()
->getResult();
- $repositories = array_map(function (PackageConfiguration $config) {
- return $config->getPackage()->getSshUrl();
- }, $packages);
- foreach ($repositories as $repository) {
- $data['repositories'][] = array(
+ $data['repositories'] = array_map(function (PackageConfiguration $config) use (&$data) {
+ $options = [
'type' => 'vcs',
- 'url' => $repository,
- );
- }
-
- $this->filesystem->mkdir($this->cacheDir.'/satis');
-
- $filename = tempnam($this->cacheDir.'/satis', 'satis_');
+ 'url' => $config->getPackage()->getSshUrl(),
+ ];
+ $remote = $config->getPackage()->getRemote();
+ switch ($remote->getAdapter()) {
+ case 'GitHub':
+ /** @var \Terramar\Packages\Plugin\GitHub\RemoteConfiguration $remoteConfig */
+ $remoteConfig = $this->entityManager->getRepository('Terramar\Packages\Plugin\GitHub\RemoteConfiguration')
+ ->findOneBy(['remote' => $remote]);
+ if (!$remoteConfig) {
+ throw new \RuntimeException('Unable to find RemoteConfiguration for ' . $remote->getAdapter() . ' ' . $remote->getName());
+ }
+
+ $options['github-token'] = $remoteConfig->getToken();
+
+ break;
+
+ case 'GitLab':
+ /** @var \Terramar\Packages\Plugin\GitLab\RemoteConfiguration $remoteConfig */
+ $remoteConfig = $this->entityManager->getRepository('Terramar\Packages\Plugin\GitLab\RemoteConfiguration')
+ ->findOneBy(['remote' => $remote]);
+ if (!$remoteConfig) {
+ throw new \RuntimeException('Unable to find RemoteConfiguration for ' . $remote->getAdapter() . ' ' . $remote->getName());
+ }
+
+ $url = parse_url($remoteConfig->getUrl(), PHP_URL_HOST);
+ if (!in_array($url, $data['config']['gitlab-domains'])) {
+ $data['config']['gitlab-domains'][] = $url;
+ }
+
+ $options['gitlab-token'] = $remoteConfig->getToken();
+ if (parse_url($remoteConfig->getUrl(), PHP_URL_SCHEME) === "http") {
+ $options['secure-http'] = false;
+ $data['config']['secure-http'] = false;
+ }
+
+ break;
+ }
+
+ return $options;
+ }, $packages);
+
+ $this->filesystem->mkdir($this->cacheDir . '/satis');
+
+ $filename = tempnam($this->cacheDir . '/satis', 'satis_');
$this->filesystem->dumpFile($filename, json_encode($data, JSON_PRETTY_PRINT));
+ echo json_encode($data, JSON_PRETTY_PRINT) . "\n";
+
return $filename;
}
}
diff --git a/src/Plugin/Satis/Controller.php b/src/Plugin/Satis/Controller.php
index 397b75c..0a59dd7 100644
--- a/src/Plugin/Satis/Controller.php
+++ b/src/Plugin/Satis/Controller.php
@@ -19,22 +19,22 @@ public function editAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')->findOneBy(array(
- 'package' => $id,
- ));
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')->findOneBy([
+ 'package' => $id,
+ ]);
- return new Response($app->get('twig')->render('Plugin/Satis/edit.html.twig', array(
- 'config' => $config,
- )));
+ return new Response($app->get('twig')->render('Plugin/Satis/edit.html.twig', [
+ 'config' => $config,
+ ]));
}
public function updateAction(Application $app, Request $request, $id)
{
/** @var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $app->get('doctrine.orm.entity_manager');
- $config = $entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')->findOneBy(array(
- 'package' => $id,
- ));
+ $config = $entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')->findOneBy([
+ 'package' => $id,
+ ]);
$config->setEnabled($request->get('satis_enabled') ? true : false);
$entityManager->persist($config);
diff --git a/src/Plugin/Satis/EventSubscriber.php b/src/Plugin/Satis/EventSubscriber.php
index 0444f2b..5ed0ecb 100644
--- a/src/Plugin/Satis/EventSubscriber.php
+++ b/src/Plugin/Satis/EventSubscriber.php
@@ -31,7 +31,7 @@ class EventSubscriber implements EventSubscriberInterface
/**
* Constructor.
*
- * @param ResqueHelper $resqueHelper
+ * @param ResqueHelper $resqueHelper
* @param EntityManager $entityManager
*/
public function __construct(ResqueHelper $resqueHelper, EntityManager $entityManager)
@@ -40,6 +40,17 @@ public function __construct(ResqueHelper $resqueHelper, EntityManager $entityMan
$this->entityManager = $entityManager;
}
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ Events::PACKAGE_UPDATE => ['onUpdatePackage', 0],
+ Events::PACKAGE_CREATE => ['onCreatePackage', 0],
+ ];
+ }
+
/**
* @param PackageUpdateEvent $event
*/
@@ -47,13 +58,15 @@ public function onUpdatePackage(PackageUpdateEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config || !$config->isEnabled() || !$package->isEnabled()) {
return;
}
- $this->resqueHelper->enqueueOnce('default', 'Terramar\Packages\Plugin\Satis\UpdateAndBuildJob');
+ $this->resqueHelper->enqueueOnce('default', 'Terramar\Packages\Plugin\Satis\UpdateAndBuildJob', [
+ 'package_id' => $package->getId(),
+ ]);
}
/**
@@ -63,7 +76,7 @@ public function onCreatePackage(PackageEvent $event)
{
$package = $event->getPackage();
$config = $this->entityManager->getRepository('Terramar\Packages\Plugin\Satis\PackageConfiguration')
- ->findOneBy(array('package' => $package));
+ ->findOneBy(['package' => $package]);
if (!$config) {
$config = new PackageConfiguration();
@@ -72,15 +85,4 @@ public function onCreatePackage(PackageEvent $event)
$this->entityManager->persist($config);
}
-
- /**
- * @return array
- */
- public static function getSubscribedEvents()
- {
- return array(
- Events::PACKAGE_UPDATE => array('onUpdatePackage', 0),
- Events::PACKAGE_CREATE => array('onCreatePackage', 0),
- );
- }
}
diff --git a/src/Plugin/Satis/FirewallCompilerPass.php b/src/Plugin/Satis/FirewallCompilerPass.php
new file mode 100644
index 0000000..1bea410
--- /dev/null
+++ b/src/Plugin/Satis/FirewallCompilerPass.php
@@ -0,0 +1,30 @@
+getParameterBag()->resolveValue('%packages.configuration%');
+ if (isset($config['secure_satis']) && $config['secure_satis'] === true) {
+ $container->getDefinition('security.firewall_matcher')
+ ->addMethodCall('matchPath', ['^/manage|^/packages(?!\.)']);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Plugin/Satis/FrontendController.php b/src/Plugin/Satis/FrontendController.php
new file mode 100644
index 0000000..5fbb185
--- /dev/null
+++ b/src/Plugin/Satis/FrontendController.php
@@ -0,0 +1,112 @@
+secure = isset($config['secure_satis']) ? (bool)$config['secure_satis'] : true;
+ $this->outputDir = $config['output_dir'];
+ $this->basePath = $config['base_path'];
+ $this->authenticator = $authenticator;
+ }
+
+ /**
+ * Handles packages.json and include/*.json requests.
+ *
+ * If secure_satis is enabled, HTTP Basic authentication will be required.
+ * The username and password required are those defined in config.yml.
+ *
+ * @param Request $request
+ * @return Response
+ */
+ public function outputAction(Request $request)
+ {
+ if ($this->secure) {
+ $username = $request->getUser();
+ $password = $request->getPassword();
+ if (
+ $this->authenticator->authenticate(new Request(['username' => $username, 'password' => $password])) !== true
+ ) {
+ return new Response('', 401, ['WWW-Authenticate' => 'Basic realm="'.$this->basePath.'"']);
+ }
+ }
+
+ $path = $this->outputDir.urldecode($request->getPathInfo());
+ if (!file_exists($path)) {
+ return new Response('Not Found', Response::HTTP_NOT_FOUND);
+ }
+
+ return new Response(
+ file_get_contents($path),
+ Response::HTTP_OK,
+ ['Content-type' => 'application/json']);
+ }
+
+ /**
+ * Handles dist/* requests when archive is enabled.
+ *
+ * If secure_satis is enabled, HTTP Basic authentication will be required.
+ * The username and password required are those defined in config.yml.
+ *
+ * @param Request $request
+ * @return Response
+ */
+ public function distAction(Request $request)
+ {
+ if ($this->secure) {
+ $username = $request->getUser();
+ $password = $request->getPassword();
+ if (
+ $this->authenticator->authenticate(new Request(['username' => $username, 'password' => $password])) !== true
+ ) {
+ return new Response('', 401, ['WWW-Authenticate' => 'Basic realm="'.$this->basePath.'"']);
+ }
+ }
+
+ $path = $this->outputDir.urldecode($request->getPathInfo());
+ if (!file_exists($path)) {
+ return new Response('Not Found', Response::HTTP_NOT_FOUND);
+ }
+
+ return new Response(
+ file_get_contents($path),
+ Response::HTTP_OK,
+ ['Content-type' => 'application/x-tar', 'Content-disposition' => 'attachment']);
+ }
+}
diff --git a/src/Plugin/Satis/InventoryController.php b/src/Plugin/Satis/InventoryController.php
new file mode 100644
index 0000000..0b89881
--- /dev/null
+++ b/src/Plugin/Satis/InventoryController.php
@@ -0,0 +1,104 @@
+getRepository();
+
+ $contents = [];
+ foreach ($repository->getPackages() as $package) {
+ /* @var \Composer\Package\CompletePackage $package */
+ $contents[$package->getName()]['name'] = $package->getName();
+ $contents[$package->getName()]['versions'][] = $package->getPrettyVersion();
+ }
+
+ return new Response($app->get('templating')->render('Plugin/Satis/Inventory/index.html.twig', [
+ 'contents' => $contents,
+ ]));
+ }
+
+ /**
+ * Displays the details for a given package.
+ */
+ public function viewAction(Application $app, $id, $version = null)
+ {
+ $repository = $this->getRepository();
+
+ $id = str_replace('+', '/', $id);
+ if ($version) {
+ $version = str_replace('+', '/', $version);
+ }
+
+ $packages = $repository->findPackages($id);
+
+ usort($packages, function ($a, $b) {
+ if ($a->getReleaseDate() > $b->getReleaseDate()) {
+ return -1;
+ }
+
+ return 1;
+ });
+
+ $package = null;
+ if ($version) {
+ foreach ($packages as $p) {
+ if ($p->getPrettyVersion() == $version) {
+ $package = $p;
+ }
+ }
+ } else {
+ /* @var \Composer\Package\CompletePackage $package */
+ $package = $packages[0];
+ }
+
+ return new Response($app->get('templating')->render('Plugin/Satis/Inventory/view.html.twig', [
+ 'packages' => $packages,
+ 'package' => $package,
+ ]));
+ }
+
+ /**
+ * @return \Composer\Repository\ComposerRepository
+ */
+ private function getRepository()
+ {
+ $configuration = $this->container->getParameter('packages.configuration');
+
+ $io = new ConsoleIO(new ArgvInput(), new ConsoleOutput(), new HelperSet([]));
+ $config = new Config();
+ $config->merge([
+ 'config' => [
+ 'home' => $this->container->getParameter('app.root_dir'),
+ ],
+ ]);
+ $repository = new ComposerRepository([
+ 'url' => 'file://' . $configuration['output_dir'] . '/packages.json',
+ ], $io, $config);
+
+ return $repository;
+ }
+}
diff --git a/src/Plugin/Satis/PackageConfiguration.php b/src/Plugin/Satis/PackageConfiguration.php
index 14c8ee8..84f2a7d 100644
--- a/src/Plugin/Satis/PackageConfiguration.php
+++ b/src/Plugin/Satis/PackageConfiguration.php
@@ -41,7 +41,7 @@ class PackageConfiguration
*/
public function setEnabled($enabled)
{
- $this->enabled = (bool) $enabled;
+ $this->enabled = (bool)$enabled;
}
/**
diff --git a/src/Plugin/Satis/Plugin.php b/src/Plugin/Satis/Plugin.php
index c9731d1..44f5305 100644
--- a/src/Plugin/Satis/Plugin.php
+++ b/src/Plugin/Satis/Plugin.php
@@ -10,12 +10,17 @@
namespace Terramar\Packages\Plugin\Satis;
use Composer\Satis\Satis;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Terramar\Packages\Plugin\Actions;
+use Terramar\Packages\Plugin\CompilerAwarePluginInterface;
use Terramar\Packages\Plugin\PluginInterface;
+use Terramar\Packages\Plugin\RouterPluginInterface;
+use Terramar\Packages\Router\RouteCollector;
-class Plugin implements PluginInterface
+class Plugin implements PluginInterface, RouterPluginInterface, CompilerAwarePluginInterface
{
/**
* Configure the given ContainerBuilder.
@@ -32,19 +37,53 @@ public function configure(ContainerBuilder $container)
->addArgument(new Reference('doctrine.orm.entity_manager'))
->addTag('kernel.event_subscriber');
- $container->register('packages.plugin.satis.config_helper', 'Terramar\Packages\Plugin\Satis\ConfigurationHelper')
+ $container->register('packages.plugin.satis.config_helper',
+ 'Terramar\Packages\Plugin\Satis\ConfigurationHelper')
->addArgument(new Reference('doctrine.orm.entity_manager'))
+ ->addArgument(new Reference('router.url_generator'))
->addArgument('%app.root_dir%')
->addArgument('%app.cache_dir%')
->addArgument('%packages.configuration%');
+ $container->register('packages.plugin.satis.frontend_controller', 'Terramar\Packages\Plugin\Satis\FrontendController')
+ ->addArgument('%packages.configuration%')
+ ->addArgument(new Reference('security.authenticator'));
+
+ $container->register('packages.plugin.satis.inventory_controller', 'Terramar\Packages\Plugin\Satis\InventoryController')
+ ->addMethodCall('setContainer', [new Reference('service_container')]);
+
$container->getDefinition('packages.controller_manager')
- ->addMethodCall('registerController', array(Actions::PACKAGE_EDIT, 'Terramar\Packages\Plugin\Satis\Controller::editAction'))
- ->addMethodCall('registerController', array(Actions::PACKAGE_UPDATE, 'Terramar\Packages\Plugin\Satis\Controller::updateAction'));
+ ->addMethodCall('registerController',
+ [Actions::PACKAGE_EDIT, 'Terramar\Packages\Plugin\Satis\Controller::editAction'])
+ ->addMethodCall('registerController',
+ [Actions::PACKAGE_UPDATE, 'Terramar\Packages\Plugin\Satis\Controller::updateAction']);
$container->getDefinition('packages.command_registry')
- ->addMethodCall('addCommand', array('Terramar\Packages\Plugin\Satis\Command\BuildCommand'))
- ->addMethodCall('addCommand', array('Terramar\Packages\Plugin\Satis\Command\UpdateCommand'));
+ ->addMethodCall('addCommand', ['Terramar\Packages\Plugin\Satis\Command\BuildCommand'])
+ ->addMethodCall('addCommand', ['Terramar\Packages\Plugin\Satis\Command\UpdateCommand']);
+ }
+
+ /**
+ * Configure the given RouteCollector.
+ *
+ * This method allows a plugin to register additional HTTP routes with the
+ * RouteCollector.
+ *
+ * @param RouteCollector $collector
+ * @return void
+ */
+ public function collect(RouteCollector $collector)
+ {
+ $collector->map('/packages.json', 'satis_packages', 'packages.plugin.satis.frontend_controller:outputAction');
+ $collector->map('/include/{file}', null, 'packages.plugin.satis.frontend_controller:outputAction');
+ $collector->map('/dist/{group}/{package}/{file}', null, 'packages.plugin.satis.frontend_controller:distAction');
+
+ $collector->map('/packages', 'packages_index',
+ 'packages.plugin.satis.inventory_controller:indexAction');
+ $collector->map('/packages/{id}', 'packages_view',
+ 'packages.plugin.satis.inventory_controller:viewAction');
+ $collector->map('/packages/{id}/{version}', 'packages_view_version',
+ 'packages.plugin.satis.inventory_controller:viewAction');
}
/**
@@ -64,4 +103,14 @@ public function getVersion()
{
return Satis::VERSION;
}
+
+ /**
+ * Gets the CompilerPasses this plugin requires.
+ *
+ * @return array|CompilerPassInterface[]
+ */
+ public function getCompilerPasses()
+ {
+ return array(new FirewallCompilerPass());
+ }
}
diff --git a/src/Plugin/Satis/UpdateAndBuildJob.php b/src/Plugin/Satis/UpdateAndBuildJob.php
index b0f4f35..103de72 100644
--- a/src/Plugin/Satis/UpdateAndBuildJob.php
+++ b/src/Plugin/Satis/UpdateAndBuildJob.php
@@ -9,23 +9,44 @@
namespace Terramar\Packages\Plugin\Satis;
+use Doctrine\ORM\EntityManager;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\ProcessBuilder;
+use Terramar\Packages\Entity\Package;
use Terramar\Packages\Job\ContainerAwareJob;
class UpdateAndBuildJob extends ContainerAwareJob
{
public function run($args)
{
+ /** @var Package $package */
+ $package = $this->getEntityManager()->getRepository(Package::class)->find($args['package_id']);
+
$finder = new PhpExecutableFinder();
- $builder = new ProcessBuilder(array('bin/console', 'satis:update', '--build', '--skip-errors'));
+ $builder = new ProcessBuilder([
+ 'bin/console',
+ 'satis:build',
+ '--repository-url',
+ $package->getSshUrl(),
+ ]);
+
$builder->setEnv('HOME', $this->getContainer()->getParameter('app.root_dir'));
$builder->setPrefix($finder->find());
$builder->setTimeout(null);
+ echo $builder->getProcess()->getCommandLine() . "\n";
+
$process = $builder->getProcess();
$process->run(function ($type, $message) {
echo $message;
});
}
+
+ /**
+ * @return EntityManager
+ */
+ private function getEntityManager()
+ {
+ return $this->getContainer()->get('doctrine.orm.entity_manager');
+ }
}
diff --git a/src/Router/RouteCollector.php b/src/Router/RouteCollector.php
index 201daee..bd48d55 100644
--- a/src/Router/RouteCollector.php
+++ b/src/Router/RouteCollector.php
@@ -10,9 +10,24 @@
namespace Terramar\Packages\Router;
use Nice\Router\RouteCollector as BaseCollector;
+use Terramar\Packages\Plugin\RouterPluginInterface;
class RouteCollector extends BaseCollector
{
+ /**
+ * @var RouterPluginInterface[]
+ */
+ private $plugins = [];
+
+ /**
+ * Register a router plugin with the collector.
+ *
+ * @param RouterPluginInterface $plugin
+ */
+ public function registerPlugin(RouterPluginInterface $plugin) {
+ $this->plugins[$plugin->getName()] = $plugin;
+ }
+
/**
* Perform any collection.
*/
@@ -22,20 +37,34 @@ protected function collectRoutes()
$this->map('/login', 'login', 'Terramar\Packages\Controller\DefaultController::loginAction');
$this->map('/logout', 'logout', '');
- $this->map('/webhook/{id}/receive', 'webhook_receive', 'Terramar\Packages\Controller\WebHookController::receiveAction', ['POST']);
+ $this->map('/webhook/{id}/receive', 'webhook_receive',
+ 'Terramar\Packages\Controller\WebHookController::receiveAction', ['POST']);
$this->map('/manage', 'manage', 'Terramar\Packages\Controller\ManageController::indexAction');
- $this->map('/manage/packages', 'manage_packages', 'Terramar\Packages\Controller\PackageController::indexAction');
- $this->map('/manage/package/{id}/edit', 'manage_package_edit', 'Terramar\Packages\Controller\PackageController::editAction');
- $this->map('/manage/package/{id}/update', 'manage_package_update', 'Terramar\Packages\Controller\PackageController::updateAction', ['POST']);
- $this->map('/manage/package/{id}/toggle', 'manage_package_toggle', 'Terramar\Packages\Controller\PackageController::toggleAction');
+ $this->map('/manage/packages', 'manage_packages',
+ 'Terramar\Packages\Controller\PackageController::indexAction');
+ $this->map('/manage/package/{id}/edit', 'manage_package_edit',
+ 'Terramar\Packages\Controller\PackageController::editAction');
+ $this->map('/manage/package/{id}/update', 'manage_package_update',
+ 'Terramar\Packages\Controller\PackageController::updateAction', ['POST']);
+ $this->map('/manage/package/{id}/toggle', 'manage_package_toggle',
+ 'Terramar\Packages\Controller\PackageController::toggleAction');
$this->map('/manage/remotes', 'manage_remotes', 'Terramar\Packages\Controller\RemoteController::indexAction');
- $this->map('/manage/remote/new', 'manage_remote_new', 'Terramar\Packages\Controller\RemoteController::newAction');
- $this->map('/manage/remote/create', 'manage_remote_create', 'Terramar\Packages\Controller\RemoteController::createAction', ['POST']);
- $this->map('/manage/remote/{id}/edit', 'manage_remote_edit', 'Terramar\Packages\Controller\RemoteController::editAction');
- $this->map('/manage/remote/{id}/update', 'manage_remote_update', 'Terramar\Packages\Controller\RemoteController::updateAction', ['POST']);
- $this->map('/manage/remote/{id}/sync', 'manage_remote_sync', 'Terramar\Packages\Controller\RemoteController::syncAction');
+ $this->map('/manage/remote/new', 'manage_remote_new',
+ 'Terramar\Packages\Controller\RemoteController::newAction');
+ $this->map('/manage/remote/create', 'manage_remote_create',
+ 'Terramar\Packages\Controller\RemoteController::createAction', ['POST']);
+ $this->map('/manage/remote/{id}/edit', 'manage_remote_edit',
+ 'Terramar\Packages\Controller\RemoteController::editAction');
+ $this->map('/manage/remote/{id}/update', 'manage_remote_update',
+ 'Terramar\Packages\Controller\RemoteController::updateAction', ['POST']);
+ $this->map('/manage/remote/{id}/sync', 'manage_remote_sync',
+ 'Terramar\Packages\Controller\RemoteController::syncAction');
+
+ foreach ($this->plugins as $plugin) {
+ $plugin->collect($this);
+ }
}
}
diff --git a/src/Security/FirewallSubscriber.php b/src/Security/FirewallSubscriber.php
new file mode 100644
index 0000000..683e1f8
--- /dev/null
+++ b/src/Security/FirewallSubscriber.php
@@ -0,0 +1,200 @@
+firewallMatcher = $firewallMatcher;
+ $this->authMatcher = $authMatcher;
+ $this->logoutMatcher = $logoutMatcher;
+ $this->loginPath = $loginPath;
+ $this->successPath = $successPath;
+ $this->tokenKey = $tokenKey;
+ $this->authenticator = $authenticator;
+ $this->eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * @param GetResponseEvent $event
+ */
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
+ return;
+ }
+
+ $request = $event->getRequest();
+ if ($this->authMatcher->matches($request)) {
+ $this->handleAuthentication($event);
+
+ return;
+ }
+
+ if ($this->logoutMatcher->matches($request)) {
+ $this->handleLogout($event);
+
+ return;
+ }
+
+ if (!$this->firewallMatcher->matches($request)) {
+ return;
+ }
+
+ if (!$request->hasSession()) {
+ $event->setResponse(new Response('', 403));
+
+ return;
+ }
+
+ if (!$request->getSession()->has($this->tokenKey)) {
+ $this->redirectForAuthentication($event);
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => array('onKernelRequest', 8),
+ );
+ }
+
+ private function handleAuthentication(GetResponseEvent $event)
+ {
+ $request = $event->getRequest();
+ $session = $request->getSession();
+
+ if (!$session) {
+ $event->setResponse(new Response('', 403));
+
+ return;
+ }
+
+ if ($this->authenticator->authenticate($request)) {
+ $session->set($this->tokenKey, true);
+
+ $successEvent = new SecurityEvent($request);
+ $this->eventDispatcher->dispatch(Events::LOGIN_SUCCESS, $successEvent);
+
+ $successPath = $request->getSession()->get(self::SUCCESS_REDIR_SESSION_KEY, $this->successPath);
+ if ($successPath === $this->loginPath || $successPath === '/logout') {
+ // TODO: The '/logout' check is a hack, should probably inject the configuration value.
+ $successPath = $this->successPath;
+ }
+ $request->getSession()->remove(self::SUCCESS_REDIR_SESSION_KEY);
+ $event->setResponse(new RedirectResponse($event->getRequest()->getBaseUrl().$successPath));
+ } else {
+ $failEvent = new SecurityEvent($request);
+ $this->eventDispatcher->dispatch(Events::LOGIN_FAIL, $failEvent);
+
+ $this->redirectForAuthentication($event);
+ }
+ }
+
+ private function redirectForAuthentication(GetResponseEvent $event)
+ {
+ $request = $event->getRequest();
+ $request->getSession()->set(self::SUCCESS_REDIR_SESSION_KEY, $request->getPathInfo());
+ $event->setResponse(new RedirectResponse($event->getRequest()->getBaseUrl().$this->loginPath));
+ }
+
+ private function handleLogout(GetResponseEvent $event)
+ {
+ $request = $event->getRequest();
+ $session = $request->getSession();
+ $session->remove($this->tokenKey);
+
+ $logoutEvent = new SecurityEvent($request);
+ $this->eventDispatcher->dispatch(Events::LOGOUT, $logoutEvent);
+
+ $this->redirectForAuthentication($event);
+ }
+}
diff --git a/src/Twig/PackagesConfigExtension.php b/src/Twig/PackagesConfigExtension.php
new file mode 100644
index 0000000..5bcc502
--- /dev/null
+++ b/src/Twig/PackagesConfigExtension.php
@@ -0,0 +1,54 @@
+config = $config;
+ }
+
+ /**
+ * @return array
+ */
+ public function getGlobals()
+ {
+ return [
+ 'packages_conf' => [
+ 'name' => $this->config['name'],
+ 'homepage' => $this->config['homepage'],
+ 'contact_email' => $this->config['contact_email'],
+ ],
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return 'packages_conf';
+ }
+}
diff --git a/src/Twig/PluginControllerExtension.php b/src/Twig/PluginControllerExtension.php
index c168077..dd7fb73 100644
--- a/src/Twig/PluginControllerExtension.php
+++ b/src/Twig/PluginControllerExtension.php
@@ -10,8 +10,8 @@
namespace Terramar\Packages\Twig;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
use Terramar\Packages\Plugin\ControllerManagerInterface;
/**
@@ -38,7 +38,7 @@ class PluginControllerExtension extends \Twig_Extension
* Constructor.
*
* @param ControllerManagerInterface $manager
- * @param FragmentHandler $handler
+ * @param FragmentHandler $handler
*/
public function __construct(ControllerManagerInterface $manager, FragmentHandler $handler)
{
@@ -59,10 +59,11 @@ public function setRequest(Request $request = null)
*/
public function getFunctions()
{
- return array(
- new \Twig_SimpleFunction('render', array($this, 'render'), array('is_safe' => array('html'))),
- new \Twig_SimpleFunction('plugin_controllers', array($this, 'getControllers')),
- );
+ return [
+ new \Twig_SimpleFunction('render', [$this, 'render'], ['is_safe' => ['html']]),
+ new \Twig_SimpleFunction('plugin_controllers', [$this, 'getControllers']),
+ new \Twig_SimpleFunction('md5', 'md5'),
+ ];
}
/**
@@ -83,13 +84,13 @@ public function render($uri)
* @param array $params
* @return array|ControllerReference
*/
- public function getControllers($action, $params = array())
+ public function getControllers($action, $params = [])
{
$params['app'] = $this->request->get('app');
return array_map(function ($controller) use ($params) {
- return new ControllerReference($controller, $params);
- }, $this->manager->getControllers($action));
+ return new ControllerReference($controller, $params);
+ }, $this->manager->getControllers($action));
}
/**
diff --git a/src/Twig/SecurityExtension.php b/src/Twig/SecurityExtension.php
new file mode 100644
index 0000000..1fc6819
--- /dev/null
+++ b/src/Twig/SecurityExtension.php
@@ -0,0 +1,55 @@
+request !== null) {
+ return $this->request->getSession()->get('__nice.is_authenticated', false);
+ }
+ return false;
+ })
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return 'security';
+ }
+
+ /**
+ * @param Request|null $request
+ */
+ public function setRequest(Request $request = null)
+ {
+ $this->request = $request;
+ }
+}
diff --git a/src/Version.php b/src/Version.php
index ee81d62..51e54f9 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -11,5 +11,5 @@
class Version
{
- const VERSION = '3.1.5';
+ const VERSION = '3.2.0';
}
diff --git a/views/Default/base.html.twig b/views/Default/base.html.twig
index fbd2400..65deb36 100644
--- a/views/Default/base.html.twig
+++ b/views/Default/base.html.twig
@@ -2,12 +2,11 @@
- Packages - Terramar Labs
+ Packages - {{ packages_conf.name }}
-
-
-
+
+
@@ -22,12 +21,19 @@
@@ -35,14 +41,19 @@
{% block body %}
{% endblock %}
-
+ {% if packages_conf.homepage is not empty %}
+ {% endif %}
+
+
+
Proudly powered by Satis {{ constant('Composer\\Satis\\Satis::VERSION') }}
+ and Packages {{ constant('Terramar\\Packages\\Version::VERSION') }}
+ {% if updatedAt %}Last updated: {{ updatedAt|date('Y-m-d H:i:s') }} {% endif %}
+
diff --git a/views/Default/index.html.twig b/views/Default/index.html.twig
index 7efd567..77ac56a 100644
--- a/views/Default/index.html.twig
+++ b/views/Default/index.html.twig
@@ -2,7 +2,10 @@
{% block body %}
This is a private repository.
+ {% if packages_conf.contact_email is not empty %}
If you should have access, contact us.
-
+ {{ packages_conf.contact_email }}
+ {% endif %}
+ Available Packages
{% endblock %}
diff --git a/views/Manage/index.html.twig b/views/Manage/index.html.twig
index c219112..c19b5e1 100644
--- a/views/Manage/index.html.twig
+++ b/views/Manage/index.html.twig
@@ -18,7 +18,7 @@
-
+