diff --git a/.gitignore b/.gitignore index d7c2d0c..10e98f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -/config/parameters.yml -/vendor/ +vendor/ +composer.phar +config.yaml diff --git a/LICENSE b/LICENSE index e68eb77..df82f0a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,7 @@ -The MIT License (MIT) +Copyright 2018 Velocity, A Managed Services Company -Copyright (c) 2015 Olivier Balais +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: -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. +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/README.md b/README.md index ff2f3c4..152e9c9 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,65 @@ -# Create a Gitlab issue from a mail +# GITLAB ISSUE BY E-MAIL -Add new issue to your Gitlab by sending an email to bug@yourdomain.com +Summary: create an Issue in Gitlab by sending an e-mail ## Why? -Gitlab is a fantastic tool to work with and is getting more awesome everyday. +Gitlab is a fantastic solution to work with and manage source code and issues. Its main features are private repository hosting, issue tracking, code review, and complete workflow all the way through deployment and production. -It offers you in just a few minutes Private Repositories Hosting, great Code Review tooling for your team, Wiki, -Issue Tracker and everything. +As great as it is, there are still a few missing features that we'd all like to have. One of these is the ability to send an e-mail and have an issue automatically created. -But as awesome as it is, we must admit that the Issue Tracker lacks a few features. One of them, is the ability for your -team or customers to send a mail to some mail address of yours and see it transformed into a beautiful Gitab Issue. +## How does it work? -This is the purpose of this ridiculously simple project. +This simple CLI application checks an IMAP e-mail box for any new messages. It uses the subject of the e-mail as the issue title and the body of the e-mail as the issue description and creates a Gitlab issue using Gitlab's API, then the e-mail is deleted. This command can then be executed periodically with a crontab or systemd timer. -## How does it work? +## DEPENDENCIES + +- PHP >= `5.6.0` +- PHP extensions + - `imap` + - `pdo-pgsql` + +## Quick Start + +1. `git clone` this repository +2. `cp config.yaml.example config.yaml` +3. Edit `config.yaml` to match your setup +4. `composer install` +5. `./console gitlab:fetch-mail` + +## `confg.yaml` Example + +```yaml +mail: + server: imap.yourdomain.tld + type: imap + port: 143 + username: gouzigouza + password: passw0rd + +gitlab: + host: gitlab.com + projectId: 1 + token: 123456789 +``` -This project is a simple command you can execute every X minutes to poll mail from any address of yours. -If a new mail is detected, the script parse its content, create an issue with the mail subject as title and content as -description and delete it from your mail server. That's all. Nothing more! +## Composer -## Setup +This application uses `composer` to pull in 3rd-party dependencies. If you are unable to install composer from your operating system's repositories, you may use the provided script to fetch a local copy of it. To do this, run the following command: -1. `git clone ...` -2. `cp config/parameters.yml.dist config/parameters.yml` and edit it to fit your needs +`scripts/get_composer.sh` (run from the application's root directory) - ```yaml - mail: - server: imap.yourdomain.tld - type: imap - port: 143 - username: gouzigouza - password: passw0rd +This will create an executable file called `composer.phar`. - gitlab: - host: gitlab.com - projectId: 1 - token: 123456789 - ``` +Executing `./composer.phar install` will install all dependencies -3. `bin/console gitlab:fetch-mail -v` +## Optional configuration -You should create some kind of CRON to run this command regularly. +- Set up a crontab or systemd timer to periodically run `./console gitlab:fetch-mail` at regular intervals. This is outside the scope of this document. -## TODO +## To-do / Planned Features +- Support STARTTLS +- Support multiple API keys (for different users) - Extract attachments and add them to Gitlab issue - Add unit tests diff --git a/bin/console b/bin/console deleted file mode 100755 index dd4045d..0000000 --- a/bin/console +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env php -add(new FetchMailCommand()); -$application->run(); diff --git a/composer.json b/composer.json index a7fa028..f9d9743 100644 --- a/composer.json +++ b/composer.json @@ -1,12 +1,39 @@ { + "name": "velocityorg/gitlab-issue-by-email", + "description": "Create a Gitlab issue by sending an e-mail", + "version": "1.0.1", + "type": "project", + "keywords": [ + "gitlab", "email", "mail", "imap", "issue", "git" + ], + "license": "MIT", + "authors": [ + { + "name": "Steven Cook", + "email": "scook@velocity.org", + "role": "Developer" + } + ], + "support": { + "email": "is@velocity.org" + }, "require": { - "symfony/console": "^2.6", - "tedivm/fetch": "^0.6.1", - "m4tthumphrey/php-gitlab-api": "^7.10", - "symfony/yaml": "^2.6", - "symfony/config": "^2.6" + "guzzlehttp/psr7": "1.4.2", + "m4tthumphrey/php-gitlab-api": "^9.10", + "monolog/monolog": "^1.23", + "php-http/curl-client": "v1.7.1", + "php-http/guzzle6-adapter": "v1.1.1", + "php-http/message": "1.7.0", + "symfony/config": "^v4.1", + "symfony/console": "^v4.1", + "symfony/yaml": "^v4.1", + "tedivm/fetch": "^0.7.1", + "nette/database": "^2.4" }, "autoload": { - "psr-4": { "Bobey\\": "src/Bobey" } + "psr-4": { + "Bobey\\": "src/Bobey", + "Velocityorg\\": "src/Velocityorg" + } } } diff --git a/composer.lock b/composer.lock index 35d4b96..df84613 100644 --- a/composer.lock +++ b/composer.lock @@ -1,38 +1,1069 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "e38abde75b06dae0d5d189493de13261", + "content-hash": "bdc28ce98060717fdfdb1873e8c13d06", "packages": [ { - "name": "kriswallsmith/buzz", - "version": "v0.13", + "name": "clue/stream-filter", + "version": "v1.4.0", "source": { "type": "git", - "url": "https://github.com/kriswallsmith/Buzz.git", - "reference": "487760b05d6269a4c2c374364325326cfa65b12c" + "url": "https://github.com/clue/php-stream-filter.git", + "reference": "d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kriswallsmith/Buzz/zipball/487760b05d6269a4c2c374364325326cfa65b12c", - "reference": "487760b05d6269a4c2c374364325326cfa65b12c", + "url": "https://api.github.com/repos/clue/php-stream-filter/zipball/d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0", + "reference": "d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^5.0 || ^4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\StreamFilter\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@lueck.tv" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "time": "2017-08-18T09:54:01+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-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": "2018-04-22T15:46:56+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": "m4tthumphrey/php-gitlab-api", + "version": "9.10.0", + "source": { + "type": "git", + "url": "https://github.com/m4tthumphrey/php-gitlab-api.git", + "reference": "c946569ae75eff6317a5691ab590b6eb071bdb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/m4tthumphrey/php-gitlab-api/zipball/c946569ae75eff6317a5691ab590b6eb071bdb26", + "reference": "c946569ae75eff6317a5691ab590b6eb071bdb26", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^5.6 || ^7.0", + "php-http/client-common": "^1.6", + "php-http/client-implementation": "^1.0", + "php-http/discovery": "^1.2", + "php-http/httplug": "^1.1", + "php-http/multipart-stream-builder": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.2", + "php-http/guzzle6-adapter": "^1.0", + "php-http/mock-client": "^1.0", + "phpunit/phpunit": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Gitlab\\": "lib/Gitlab/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thibault Duplessis", + "email": "thibault.duplessis@gmail.com", + "homepage": "http://ornicar.github.com" + }, + { + "name": "KnpLabs Team", + "homepage": "http://knplabs.com" + }, + { + "name": "Matt Humphrey", + "homepage": "http://m4tt.io" + } + ], + "description": "GitLab API client", + "homepage": "https://github.com/m4tthumphrey/php-gitlab-api", + "keywords": [ + "api", + "gitlab" + ], + "time": "2018-06-15T13:59:39+00:00" + }, + { + "name": "monolog/monolog", + "version": "1.23.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", + "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", + "swiftmailer/swiftmailer": "^5.3|^6.0" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2017-06-19T01:22:40+00:00" + }, + { + "name": "nette/caching", + "version": "v2.5.8", + "source": { + "type": "git", + "url": "https://github.com/nette/caching.git", + "reference": "7fba7c7ab2585fafb7b31152f2595e1551120555" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/caching/zipball/7fba7c7ab2585fafb7b31152f2595e1551120555", + "reference": "7fba7c7ab2585fafb7b31152f2595e1551120555", + "shasum": "" + }, + "require": { + "nette/finder": "^2.2 || ~3.0.0", + "nette/utils": "^2.4 || ~3.0.0", + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "latte/latte": "^2.4", + "nette/di": "^2.4 || ~3.0.0", + "nette/tester": "^2.0", + "tracy/tracy": "^2.4" + }, + "suggest": { + "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.", + "homepage": "https://nette.org", + "keywords": [ + "cache", + "journal", + "memcached", + "nette", + "sqlite" + ], + "time": "2018-03-21T11:04:32+00:00" + }, + { + "name": "nette/database", + "version": "v2.4.7", + "source": { + "type": "git", + "url": "https://github.com/nette/database.git", + "reference": "b7b1b990abdc612d45f5dd6fe24618329768f864" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/database/zipball/b7b1b990abdc612d45f5dd6fe24618329768f864", + "reference": "b7b1b990abdc612d45f5dd6fe24618329768f864", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "nette/caching": "^2.2", + "nette/utils": "^2.4", + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "mockery/mockery": "^1.0.0", + "nette/di": "^2.4 || ~3.0.0", + "nette/tester": "^2.0", + "tracy/tracy": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💾 Nette Database: layer with a familiar PDO-like API but much more powerful. Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.", + "homepage": "https://nette.org", + "keywords": [ + "database", + "mssql", + "mysql", + "nette", + "notorm", + "oracle", + "pdo", + "postgresql", + "queries", + "sqlite" + ], + "time": "2018-10-16T12:52:07+00:00" + }, + { + "name": "nette/finder", + "version": "v2.4.2", + "source": { + "type": "git", + "url": "https://github.com/nette/finder.git", + "reference": "ee951a656cb8ac622e5dd33474a01fd2470505a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/finder/zipball/ee951a656cb8ac622e5dd33474a01fd2470505a0", + "reference": "ee951a656cb8ac622e5dd33474a01fd2470505a0", + "shasum": "" + }, + "require": { + "nette/utils": "~2.4", + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "~2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🔍 Nette Finder: find files and directories with an intuitive API.", + "homepage": "https://nette.org", + "keywords": [ + "filesystem", + "glob", + "iterator", + "nette" + ], + "time": "2018-06-28T11:49:23+00:00" + }, + { + "name": "nette/utils", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/17b9f76f2abd0c943adfb556e56f2165460b15ce", + "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "~2.0", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize() and toAscii()", + "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/loader.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "time": "2018-09-18T10:22:16+00:00" + }, + { + "name": "php-http/client-common", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/client-common.git", + "reference": "0b9ce659aa46aee106f8c66597ea0c070fcd9dff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/client-common/zipball/0b9ce659aa46aee106f8c66597ea0c070fcd9dff", + "reference": "0b9ce659aa46aee106f8c66597ea0c070fcd9dff", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "php-http/httplug": "^1.1", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.4", + "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2" + }, + "suggest": { + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "common", + "http", + "httplug" + ], + "time": "2018-10-09T06:46:29+00:00" + }, + { + "name": "php-http/curl-client", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/curl-client.git", + "reference": "6341a93d00e5d953fc868a3928b5167e6513f2b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/curl-client/zipball/6341a93d00e5d953fc868a3928b5167e6513f2b6", + "reference": "6341a93d00e5d953fc868a3928b5167e6513f2b6", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": "^5.5 || ^7.0", + "php-http/discovery": "^1.0", + "php-http/httplug": "^1.0", + "php-http/message": "^1.2", + "php-http/message-factory": "^1.0.2" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.0", + "php-http/client-integration-tests": "^0.6", + "phpunit/phpunit": "^4.8.27", + "zendframework/zend-diactoros": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Client\\Curl\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Михаил Красильников", + "email": "m.krasilnikov@yandex.ru" + } + ], + "description": "cURL client for PHP-HTTP", + "homepage": "http://php-http.org", + "keywords": [ + "curl", + "http" + ], + "time": "2018-03-26T19:21:48+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "9a6cb24de552bfe1aa9d7d1569e2d49c5b169a33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/9a6cb24de552bfe1aa9d7d1569e2d49c5b169a33", + "reference": "9a6cb24de552bfe1aa9d7d1569e2d49c5b169a33", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^2.0.2", + "php-http/httplug": "^1.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^2.4", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", + "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr7" + ], + "time": "2018-02-06T10:55:24+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/message", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "741f2266a202d59c4ed75436671e1b8e6f475ea3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/741f2266a202d59c4ed75436671e1b8e6f475ea3", + "reference": "741f2266a202d59c4ed75436671e1b8e6f475ea3", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.4", + "php": "^5.4 || ^7.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "akeneo/phpspec-skip-example-extension": "^1.0", + "coduo/phpspec-data-provider-extension": "^1.0", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4", + "slim/slim": "^3.0", + "zendframework/zend-diactoros": "^1.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation", + "zendframework/zend-diactoros": "Used with Diactoros Factories" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + }, + "files": [ + "src/filters.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "time": "2018-08-15T06:37:30+00:00" + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" }, - "require-dev": { - "phpunit/phpunit": "3.7.*" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "" }, - "suggest": { - "ext-curl": "*" + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { - "psr-0": { - "Buzz": "lib/" + "psr-4": { + "Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -41,45 +1072,55 @@ ], "authors": [ { - "name": "Kris Wallsmith", - "email": "kris.wallsmith@gmail.com", - "homepage": "http://kriswallsmith.net/" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Lightweight HTTP client", - "homepage": "https://github.com/kriswallsmith/Buzz", + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", "keywords": [ - "curl", - "http client" + "factory", + "http", + "message", + "stream", + "uri" ], - "time": "2014-09-15 12:42:36" + "time": "2015-12-19T14:08:53+00:00" }, { - "name": "m4tthumphrey/php-gitlab-api", - "version": "7.10.0", + "name": "php-http/multipart-stream-builder", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/m4tthumphrey/php-gitlab-api.git", - "reference": "2b320f76baafadf2715cfb92358f793e383d923d" + "url": "https://github.com/php-http/multipart-stream-builder.git", + "reference": "1fa3c623fc813a43b39494b2a1612174e36e0fb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/m4tthumphrey/php-gitlab-api/zipball/2b320f76baafadf2715cfb92358f793e383d923d", - "reference": "2b320f76baafadf2715cfb92358f793e383d923d", + "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/1fa3c623fc813a43b39494b2a1612174e36e0fb0", + "reference": "1fa3c623fc813a43b39494b2a1612174e36e0fb0", "shasum": "" }, "require": { - "ext-curl": "*", - "kriswallsmith/buzz": ">=0.7", - "php": ">=5.3.2" + "php": "^5.5 || ^7.0", + "php-http/discovery": "^1.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~4.5" + "php-http/message": "^1.5", + "phpunit/phpunit": "^4.8 || ^5.4", + "zendframework/zend-diactoros": "^1.3.5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, "autoload": { - "psr-0": { - "Gitlab\\": "lib/" + "psr-4": { + "Http\\Message\\MultipartStream\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -88,59 +1129,212 @@ ], "authors": [ { - "name": "Thibault Duplessis", - "email": "thibault.duplessis@gmail.com", - "homepage": "http://ornicar.github.com" - }, + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "A builder class that help you create a multipart stream", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "multipart stream", + "stream" + ], + "time": "2017-05-21T17:45:25+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": "KnpLabs Team", - "homepage": "http://knplabs.com" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" }, { - "name": "Matt Humphrey", - "homepage": "http://m4tt.io" + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" } ], - "description": "GitLab API client", - "homepage": "https://github.com/m4tthumphrey/php-gitlab-api", + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", "keywords": [ - "api", - "gitlab" + "promise" + ], + "time": "2016-01-26T13:27:02+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", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } ], - "time": "2015-05-06 14:58:16" + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" }, { "name": "symfony/config", - "version": "v2.6.9", - "target-dir": "Symfony/Component/Config", + "version": "v4.1.6", "source": { "type": "git", - "url": "https://github.com/symfony/Config.git", - "reference": "2696c5bc7c31485a482c10865d713de9fcc7aa31" + "url": "https://github.com/symfony/config.git", + "reference": "b3d4d7b567d7a49e6dfafb6d4760abc921177c96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/2696c5bc7c31485a482c10865d713de9fcc7aa31", - "reference": "2696c5bc7c31485a482c10865d713de9fcc7aa31", + "url": "https://api.github.com/repos/symfony/config/zipball/b3d4d7b567d7a49e6dfafb6d4760abc921177c96", + "reference": "b3d4d7b567d7a49e6dfafb6d4760abc921177c96", "shasum": "" }, "require": { - "php": ">=5.3.3", - "symfony/filesystem": "~2.3" + "php": "^7.1.3", + "symfony/filesystem": "~3.4|~4.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<3.4" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "4.1-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Config\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -158,47 +1352,57 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-05-15 13:32:45" + "time": "2018-09-08T13:24:10+00:00" }, { "name": "symfony/console", - "version": "v2.6.8", - "target-dir": "Symfony/Component/Console", + "version": "v4.1.6", "source": { "type": "git", - "url": "https://github.com/symfony/Console.git", - "reference": "2343f6d8026306bd330e0c987e4c102483c213e7" + "url": "https://github.com/symfony/console.git", + "reference": "dc7122fe5f6113cfaba3b3de575d31112c9aa60b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/2343f6d8026306bd330e0c987e4c102483c213e7", - "reference": "2343f6d8026306bd330e0c987e4c102483c213e7", + "url": "https://api.github.com/repos/symfony/console/zipball/dc7122fe5f6113cfaba3b3de575d31112c9aa60b", + "reference": "dc7122fe5f6113cfaba3b3de575d31112c9aa60b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" }, "require-dev": { "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", + "symfony/lock": "", "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "4.1-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Console\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -216,39 +1420,39 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-05-22 14:53:08" + "time": "2018-10-03T08:15:46+00:00" }, { "name": "symfony/filesystem", - "version": "v2.6.9", - "target-dir": "Symfony/Component/Filesystem", + "version": "v4.1.6", "source": { "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "1f8429f72a5bfa58b33fd96824bea146fc4b3f49" + "url": "https://github.com/symfony/filesystem.git", + "reference": "596d12b40624055c300c8b619755b748ca5cf0b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/1f8429f72a5bfa58b33fd96824bea146fc4b3f49", - "reference": "1f8429f72a5bfa58b33fd96824bea146fc4b3f49", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/596d12b40624055c300c8b619755b748ca5cf0b5", + "reference": "596d12b40624055c300c8b619755b748ca5cf0b5", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "4.1-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Filesystem\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -266,39 +1470,219 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-05-15 13:32:45" + "time": "2018-10-02T12:40:59+00:00" }, { - "name": "symfony/yaml", - "version": "v2.6.9", - "target-dir": "Symfony/Component/Yaml", + "name": "symfony/options-resolver", + "version": "v4.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "40f0e40d37c1c8a762334618dea597d64bbb75ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/40f0e40d37c1c8a762334618dea597d64bbb75ff", + "reference": "40f0e40d37c1c8a762334618dea597d64bbb75ff", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2018-09-18T12:45:12+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.9.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.9.0", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", + "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "367e689b2fdc19965be435337b50bc8adf2746c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9", + "reference": "367e689b2fdc19965be435337b50bc8adf2746c9", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "4.1-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Yaml\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -316,20 +1700,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2018-10-02T16:36:10+00:00" }, { "name": "tedivm/fetch", - "version": "v0.6.1", + "version": "v0.7.1", "source": { "type": "git", "url": "https://github.com/tedious/Fetch.git", - "reference": "154a84fdfa0d045c2871dd9f8708362fb9ea4acf" + "reference": "ea3f1bbde6bd6388488105240640642dc82c06a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tedious/Fetch/zipball/154a84fdfa0d045c2871dd9f8708362fb9ea4acf", - "reference": "154a84fdfa0d045c2871dd9f8708362fb9ea4acf", + "url": "https://api.github.com/repos/tedious/Fetch/zipball/ea3f1bbde6bd6388488105240640642dc82c06a6", + "reference": "ea3f1bbde6bd6388488105240640642dc82c06a6", "shasum": "" }, "require": { @@ -365,7 +1749,7 @@ "imap", "pop3" ], - "time": "2015-01-08 03:22:20" + "time": "2015-08-02T03:38:12+00:00" } ], "packages-dev": [], diff --git a/config.yaml.example b/config.yaml.example new file mode 100644 index 0000000..2e96b55 --- /dev/null +++ b/config.yaml.example @@ -0,0 +1,24 @@ +mail: + # Your e-mail server's address + server: imap.yourdomain.tld + + # Protocol (one of "pop" or "imap", defaults to "imap") + type: imap + + # Port (usually 110 for POP3 or 143/993 for IMAP/IMAPS) + # Note: The underlying library does not support STARTTLS) + port: 143 + + # Credentials + username: gouzigouza + password: passw0rd + +gitlab: + # Your Gitlab server host + host: gitlab.com + + # Issues will be created under this project ID + projectId: 1 + + # Your API token (must have write access) + token: 123456789 diff --git a/config/parameters.yml.dist b/config/parameters.yml.dist deleted file mode 100644 index b803c1b..0000000 --- a/config/parameters.yml.dist +++ /dev/null @@ -1,11 +0,0 @@ -mail: - server: imap.yourdomain.tld - type: imap - port: 143 - username: gouzigouza - password: passw0rd - -gitlab: - host: gitlab.com - projectId: 1 - token: 123456789 diff --git a/console b/console new file mode 100755 index 0000000..45b8f58 --- /dev/null +++ b/console @@ -0,0 +1,20 @@ +#!/usr/bin/env php +add(new FetchMailCommand()); +$application->run(); diff --git a/scripts/get_composer.sh b/scripts/get_composer.sh new file mode 100755 index 0000000..f4fac88 --- /dev/null +++ b/scripts/get_composer.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Download the latest composer binary + +# File will be named "composer.phar" + +if [[ ! -d "scripts" ]]; then + >&2 echo "Please run this script from the project's root directory." + exit 1 +fi + +EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)" +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +ACTUAL_SIGNATURE="$(php -r "echo hash_file('SHA384', 'composer-setup.php');")" + +if [[ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]]; then + >&2 echo 'ERROR: Invalid installer signature' + rm composer-setup.php + exit 1 +fi + +php composer-setup.php --quiet +RESULT=$? +rm composer-setup.php + +if [[ -f "composer.phar" ]]; then + >&1 echo "Composer successfully downloaded." +fi + +exit $RESULT diff --git a/src/Bobey/GitlabIssueByMail/Command/FetchMailCommand.php b/src/Bobey/GitlabIssueByMail/Command/FetchMailCommand.php deleted file mode 100644 index d40b76f..0000000 --- a/src/Bobey/GitlabIssueByMail/Command/FetchMailCommand.php +++ /dev/null @@ -1,81 +0,0 @@ -setName('gitlab:fetch-mail') - ->setDescription('Fetch emails from given mail address and create Gitlab Issues from it'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $yaml = new Parser(); - - $config = $yaml->parse(file_get_contents( __DIR__ . '/../../../../config/parameters.yml')); - - $processor = new Processor(); - $configuration = new ParametersConfiguration(); - $processedConfiguration = $processor->processConfiguration($configuration, [$config]); - - // Gitlab parameters - $token = $processedConfiguration['gitlab']['token']; - $projectId = $processedConfiguration['gitlab']['projectId']; - $gitlabUrl = $processedConfiguration['gitlab']['host']; - - // Mail parameters - $server = $processedConfiguration['mail']['server']; - $port = $processedConfiguration['mail']['port']; - $type = $processedConfiguration['mail']['type']; - $username = $processedConfiguration['mail']['username']; - $password = $processedConfiguration['mail']['password']; - - $server = new Server($server, $port, $type); - $server->setAuthentication($username, $password); - - $client = new GitlabClient(sprintf('%s/api/v3/', $gitlabUrl)); - $client->authenticate($token, GitlabClient::AUTH_URL_TOKEN); - - $project = new GitlabProject($projectId, $client); - - /** @var Message[] $messages */ - $messages = $server->getMessages(); - - foreach ($messages as $message) { - - $issueTitle = $message->getSubject(); - $issueContent = $message->getMessageBody(); - - $project->createIssue($issueTitle, [ - 'description' => $issueContent, - ]); - - if ($output->getVerbosity() <= OutputInterface::VERBOSITY_VERBOSE) { - $output->writeln(sprintf('Created a new issue: %s', $issueTitle)); - } - - $message->delete(); - } - - $output->writeln(count($messages) ? - sprintf('Created %d new issue%s', count($messages), count($messages) > 1 ? 's' : '') : - 'No new issue created' - ); - - $server->expunge(); - } -} diff --git a/src/Velocityorg/Db.php b/src/Velocityorg/Db.php new file mode 100644 index 0000000..c3831f0 --- /dev/null +++ b/src/Velocityorg/Db.php @@ -0,0 +1,16 @@ +connection = new Connection($dsn, $user, $password); + } + + public function getConnection() { + return $this->connection; + } +} diff --git a/src/Velocityorg/GitlabIssueByMail/Command/FetchMailCommand.php b/src/Velocityorg/GitlabIssueByMail/Command/FetchMailCommand.php new file mode 100644 index 0000000..b6d9b9e --- /dev/null +++ b/src/Velocityorg/GitlabIssueByMail/Command/FetchMailCommand.php @@ -0,0 +1,156 @@ +setName('gitlab:fetch-mail') + ->setDescription('Fetch e-mail(s) and create Gitlab issue(s) from the result'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $yaml = new Parser(); + $config = $yaml->parse(file_get_contents('config.yaml')); + + $dbConnection = new Db( + $config['db']['type'] . ':dbname=' . $config['db']['database'], + $config['db']['user'], + $config['db']['password'] + ); + + $db = $dbConnection->getConnection(); + + $server = new Server( + $config['mail']['server'], + $config['mail']['port'], + (array_key_exists('type', $config['mail'])) ? $config['mail']['type'] : 'imap' + ); + + $server->setAuthentication( + $config['mail']['username'], + $config['mail']['password'] + ); + + $client = GitlabClient::create($config['gitlab']['host']) + ->authenticate($config['gitlab']['token'], GitlabClient::AUTH_URL_TOKEN); + + /** @var Message[] $messages */ + $messages = $server->getMessages(); + + $project = new GitlabProject( + $config['gitlab']['projectId'], + $client + ); + + if (count($messages) > 0) { + $this->writeOutput($output, sprintf("Found %d new message(s)", count($messages))); + } else { + $this->writeOutput($output, "No messages found, goodbye"); + } + + foreach ($messages as $message) { + //print_r($message->msgno); + $headers = $message->getHeaders(); + + $issueTitle = $message->getSubject(); + $issueContent = $message->getMessageBody(); + + $email = $this->processAddressObject($message->getHeaders()->from); + $userRecord = $this->getUserByEmail($client, $email['address']); + + // Only continue if we have a matching user record + if ($userRecord) { + $this->writeOutput($output, sprintf("E-mail from %s : Matched user %s", $email['address'], $userRecord['username'] . ' (' . $userRecord['name']. ')')); + + $result = $project->createIssue( + $issueTitle, + [ + 'description' => $issueContent + ] + ); + + /* + * Update issue in the database + */ + $db->query( + 'UPDATE issues SET', + [ + 'author_id' => $userRecord['id'] + ], + 'WHERE id = ?', $result->id + ); + + $this->writeOutput($output, sprintf('Created new issue %d : %s', $result->iid, $issueTitle)); + } else { + $this->writeOutput($output, sprintf("E-mail from %s : User not found, skipping", $email['address'])); + } + + $this->writeOutput($output, sprintf('Deleting e-mail message %d', $message->getOverview()->msgno)); + + $message->delete(); + } + + // Expunge deleted e-mail messages + $server->expunge(); + } + + protected function processAddressObject($addresses) { + $outputAddresses = []; + + if (is_array($addresses)) + { + foreach ($addresses as $address) { + if (property_exists($address, 'mailbox') && $address->mailbox != 'undisclosed-recipients') + { + $currentAddress = []; + $currentAddress['address'] = $address->mailbox . '@' . $address->host; + + if (isset($address->personal)) + { + $currentAddress['name'] = $address->personal; + } + + $outputAddresses[] = $currentAddress; + } + } + } + + return $outputAddresses[0]; + } + + protected function getUserByEmail($client, $email) + { + $users = new Users($client); + + // Find the user with the given e-mail address + $user = $users->all( + [ + 'search' => $email + ] + ); + + return (is_array($user) && count($user) > 0) ? $user[0] : false; + } + + protected function writeOutput(OutputInterface $output, $message) + { + $timestamp = date('Y-m-d h:i:s'); + + if ($output->getVerbosity() <= OutputInterface::VERBOSITY_VERBOSE) { + $output->writeln("${timestamp} ${message}"); + } + } +} diff --git a/src/Bobey/GitlabIssueByMail/Configuration/ParametersConfiguration.php b/src/Velocityorg/GitlabIssueByMail/Configuration/ParametersConfiguration.php similarity index 84% rename from src/Bobey/GitlabIssueByMail/Configuration/ParametersConfiguration.php rename to src/Velocityorg/GitlabIssueByMail/Configuration/ParametersConfiguration.php index 817507d..eedd8a5 100644 --- a/src/Bobey/GitlabIssueByMail/Configuration/ParametersConfiguration.php +++ b/src/Velocityorg/GitlabIssueByMail/Configuration/ParametersConfiguration.php @@ -1,20 +1,16 @@ root('parameters'); $rootNode ->children() - ->arrayNode('mail') ->children() ->scalarNode('server')->end() @@ -34,9 +30,7 @@ public function getConfigTreeBuilder() ->scalarNode('token')->end() ->end() ->end() - - ->end() - ; + ->end(); return $treeBuilder; }