diff --git a/.gitignore b/.gitignore
index d484c87..3722a23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
-/bin
-/vendor
+/bin/behat
+/bin/phpspec
+/vendor
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 21b5433..29321dd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,9 +6,6 @@ php:
- 5.5
- hhvm
-services:
- - redis-server
-
matrix:
allow_failures:
- php: hhvm
@@ -17,7 +14,8 @@ before_script:
- COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev --no-interaction install
script:
- - bin/phpunit -v
+ - bin/phpspec run --format=pretty
+ - bin/behat
notifications:
email:
diff --git a/README.md b/README.md
index 9592d55..d1b35e9 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,106 @@ PHP badges poser
================
This is a php library that creates badges,
-according to [Shields specification](https://github.com/badges/shields#specification).
\ No newline at end of file
+according to [Shields specification](https://github.com/badges/shields#specification).
+
+``` bash
+ ________________
+ |_ _ _| _ _ | _ _ _ _ _ |
+ |_)(_|(_|(_|(/_ | |_)(_)_\(/_| |
+ _| |_|______________|
+
+```
+
+This library create this: ![badge-poser](badge-poser.svg) and ![I'm a badge](i_m-badge.svg) and ![dark](today-dark.svg)...
+
+This library is used by the most used badge creator in php https://poser.pugx.org/
+
+## Usage as library
+
+#### 1. Add to composer
+
+`composer require badge/poser ~0.1`
+
+#### 2. Use in your project as lib
+
+``` php
+ use PUGX\Poser\Render\SvgRender;
+ use PUGX\Poser\Poser;
+
+ $render = new SvgRender();
+ $poser = new Poser(array('svg' => $render));
+
+ echo $poser->generate('license', 'MIT', '428F7E', 'svg');
+ // or
+ echo $poser->generateFromURI('license-MIT-428F7E.svg');
+```
+
+## Use in your project as command
+
+#### 1. Add to composer
+
+`$ composer require badges/poser ~0.1`
+
+or create a project
+
+`$ composer create-project badges/poser ~0.1`
+
+and make the link
+
+`$ ln -s poser/bin/poser /usr/local/bin/poser`
+
+#### 2. lunch the command
+
+Creating an image
+
+`$ poser license MIT blue -p "license.svg"`
+
+Flushing the image
+
+`$ poser license MIT blue`
+
+## Encoding
+
+Dashes `--` → `-` Dash
+
+Underscores `__` → `_` Underscore
+
+`_` or Space → Space
+
+## More
+
+For *more info* please see the [behat features](./features/)
+and the examples in the [php-spec folder](./spec/)
+
+## Contribution
+
+Active contribution and patches are very welcome.
+See the [github issues](https://github.com/PUGX/poser/issues?state=open).
+To keep things in shape we have quite a bunch of examples and features. If you're submitting pull requests please
+make sure that they are still passing and if you add functionality please
+take a look at the coverage as well it should be pretty high :)
+
+- First fork or clone the repository
+
+```
+git clone git://github.com/badges/poser.git
+cd poser
+```
+
+- Install vendors:
+
+``` bash
+composer install
+```
+
+- Run specs:
+
+``` bash
+./bin/phpspec run --format=pretty
+```
+
+- Then run behat:
+
+``` bash
+./bin/behat run
+```
diff --git a/badge-poser.svg b/badge-poser.svg
new file mode 100644
index 0000000..c2b23f6
--- /dev/null
+++ b/badge-poser.svg
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/bin/poser b/bin/poser
new file mode 100755
index 0000000..421c83a
--- /dev/null
+++ b/bin/poser
@@ -0,0 +1,24 @@
+#!/usr/bin/env php
+run();
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 7f431ec..8f72a94 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
- "name": "pugx/poser",
- "description": "Poser, add badges on your readme, such as downloads number or latest version.",
+ "name": "badges/poser",
+ "description": "Poser, add badges on your readme..",
"keywords": ["composer", "packagist", "badge", "pin"],
"homepage": "https://github.com/PUGX",
"type": "lib",
@@ -20,17 +20,20 @@
}
],
"autoload": {
- "psr-4": { "PUGX\\Badge\\Poser": "src/" }
+ "psr-4": { "PUGX\\Poser\\": "src/" }
},
"require": {
+ "symfony/console": "dev-master"
},
"require-dev": {
- "phpunit/phpunit": "@stable"
+ "phpspec/phpspec": "dev-master",
+ "behat/behat": "dev-master"
},
"config": {
"bin-dir": "bin"
},
- "minimum-stability": "stable",
+ "bin": ["bin/poser"],
+ "minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..a68c619
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,903 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "f8400eae9ffc9327de6718202f9e4c2f",
+ "packages": [
+ {
+ "name": "symfony/console",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/Console",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Console.git",
+ "reference": "9a491e7983209bf320d40917291c03e856eee947"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Console/zipball/9a491e7983209bf320d40917291c03e856eee947",
+ "reference": "9a491e7983209bf320d40917291c03e856eee947",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/event-dispatcher": "~2.1",
+ "symfony/process": "~2.1"
+ },
+ "suggest": {
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/process": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Console\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-06-20 17:41:51"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "behat/behat",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Behat/Behat.git",
+ "reference": "c0409b8a44dd363ea69a39428d131b1ae3581814"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Behat/Behat/zipball/c0409b8a44dd363ea69a39428d131b1ae3581814",
+ "reference": "c0409b8a44dd363ea69a39428d131b1ae3581814",
+ "shasum": ""
+ },
+ "require": {
+ "behat/gherkin": "~4.3",
+ "behat/transliterator": "~1.0",
+ "ext-mbstring": "*",
+ "php": ">=5.3.3",
+ "symfony/class-loader": "~2.1",
+ "symfony/config": "~2.3",
+ "symfony/console": "~2.1",
+ "symfony/dependency-injection": "~2.1",
+ "symfony/event-dispatcher": "~2.1",
+ "symfony/translation": "~2.1",
+ "symfony/yaml": "~2.1"
+ },
+ "require-dev": {
+ "phpspec/prophecy-phpunit": "~1.0",
+ "phpunit/phpunit": "~4.0.7",
+ "symfony/process": "~2.1"
+ },
+ "suggest": {
+ "behat/mink-extension": "for integration with Mink testing framework",
+ "behat/symfony2-extension": "for integration with Symfony2 web framework",
+ "behat/yii-extension": "for integration with Yii web framework"
+ },
+ "bin": [
+ "bin/behat"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Behat\\Behat": "src/",
+ "Behat\\Testwork": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "ever.zet@gmail.com",
+ "homepage": "http://everzet.com"
+ }
+ ],
+ "description": "Scenario-oriented BDD framework for PHP 5.3",
+ "homepage": "http://behat.org/",
+ "keywords": [
+ "Agile",
+ "BDD",
+ "ScenarioBDD",
+ "Scrum",
+ "StoryBDD",
+ "User story",
+ "business",
+ "development",
+ "documentation",
+ "examples",
+ "symfony",
+ "testing"
+ ],
+ "time": "2014-06-20 21:35:01"
+ },
+ {
+ "name": "behat/gherkin",
+ "version": "v4.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Behat/Gherkin.git",
+ "reference": "43777c51058b77bcd84a8775b7a6ad05e986b5db"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Behat/Gherkin/zipball/43777c51058b77bcd84a8775b7a6ad05e986b5db",
+ "reference": "43777c51058b77bcd84a8775b7a6ad05e986b5db",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0",
+ "symfony/yaml": "~2.1"
+ },
+ "suggest": {
+ "symfony/yaml": "If you want to parse features, represented in YAML files"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Behat\\Gherkin": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "ever.zet@gmail.com",
+ "homepage": "http://everzet.com"
+ }
+ ],
+ "description": "Gherkin DSL parser for PHP 5.3",
+ "homepage": "http://behat.org/",
+ "keywords": [
+ "BDD",
+ "Behat",
+ "Cucumber",
+ "DSL",
+ "gherkin",
+ "parser"
+ ],
+ "time": "2014-06-06 01:24:32"
+ },
+ {
+ "name": "behat/transliterator",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Behat/Transliterator.git",
+ "reference": "c93521d3462a554332d1ef5bb0e9b5b8ca4106c4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Behat/Transliterator/zipball/c93521d3462a554332d1ef5bb0e9b5b8ca4106c4",
+ "reference": "c93521d3462a554332d1ef5bb0e9b5b8ca4106c4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Behat\\Transliterator": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Artistic-1.0"
+ ],
+ "description": "String transliterator",
+ "keywords": [
+ "i18n",
+ "slug",
+ "transliterator"
+ ],
+ "time": "2014-05-15 22:08:22"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "07b195e1eee19ee99cd9432983e1fb39adacdde1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/07b195e1eee19ee99cd9432983e1fb39adacdde1",
+ "reference": "07b195e1eee19ee99cd9432983e1fb39adacdde1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*@stable"
+ },
+ "suggest": {
+ "dflydev/markdown": "1.0.*",
+ "erusev/parsedown": "~0.7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "phpDocumentor": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "mike.vanriel@naenius.com"
+ }
+ ],
+ "time": "2014-04-26 10:10:44"
+ },
+ {
+ "name": "phpspec/php-diff",
+ "version": "v1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/php-diff.git",
+ "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a",
+ "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Diff": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Chris Boulton",
+ "homepage": "http://github.com/chrisboulton",
+ "role": "Original developer"
+ }
+ ],
+ "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).",
+ "time": "2013-11-01 13:02:21"
+ },
+ {
+ "name": "phpspec/phpspec",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/phpspec.git",
+ "reference": "a65fb9da78a988b5f26dce56ab58b5f44cc492de"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpspec/phpspec/zipball/a65fb9da78a988b5f26dce56ab58b5f44cc492de",
+ "reference": "a65fb9da78a988b5f26dce56ab58b5f44cc492de",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "phpspec/php-diff": "~1.0.0",
+ "phpspec/prophecy": "~1.1",
+ "symfony/console": "~2.1",
+ "symfony/event-dispatcher": "~2.1",
+ "symfony/finder": "~2.1",
+ "symfony/yaml": "~2.1"
+ },
+ "require-dev": {
+ "behat/behat": "~2.5",
+ "bossa/phpspec2-expect": "dev-master",
+ "symfony/filesystem": "~2.1"
+ },
+ "suggest": {
+ "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters"
+ },
+ "bin": [
+ "bin/phpspec"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "PhpSpec": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "ever.zet@gmail.com",
+ "homepage": "http://everzet.com"
+ },
+ {
+ "name": "Marcello Duarte",
+ "homepage": "http://marcelloduarte.net/"
+ }
+ ],
+ "description": "Specification-oriented BDD framework for PHP 5.3+",
+ "homepage": "http://phpspec.net/",
+ "keywords": [
+ "BDD",
+ "SpecBDD",
+ "TDD",
+ "spec",
+ "specification",
+ "testing",
+ "tests"
+ ],
+ "time": "2014-06-26 14:25:58"
+ },
+ {
+ "name": "phpspec/prophecy",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/prophecy.git",
+ "reference": "c9a80f8c324df415fea36ab1148a44ed6b456210"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9a80f8c324df415fea36ab1148a44ed6b456210",
+ "reference": "c9a80f8c324df415fea36ab1148a44ed6b456210",
+ "shasum": ""
+ },
+ "require": {
+ "phpdocumentor/reflection-docblock": "~2.0"
+ },
+ "require-dev": {
+ "phpspec/phpspec": "2.0.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Prophecy\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "ever.zet@gmail.com",
+ "homepage": "http://everzet.com"
+ },
+ {
+ "name": "Marcello Duarte",
+ "email": "marcello.duarte@gmail.com"
+ }
+ ],
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
+ "homepage": "http://phpspec.org",
+ "keywords": [
+ "Double",
+ "Dummy",
+ "fake",
+ "mock",
+ "spy",
+ "stub"
+ ],
+ "time": "2014-06-14 19:28:44"
+ },
+ {
+ "name": "symfony/class-loader",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/ClassLoader",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/ClassLoader.git",
+ "reference": "9872f5b7a9547b3c4c7474cb4d5d4eb4cad3b4a5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/9872f5b7a9547b3c4c7474cb4d5d4eb4cad3b4a5",
+ "reference": "9872f5b7a9547b3c4c7474cb4d5d4eb4cad3b4a5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/finder": "~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\ClassLoader\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony ClassLoader Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-05-23 14:36:49"
+ },
+ {
+ "name": "symfony/config",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/Config",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Config.git",
+ "reference": "32018f35de323afd1bffb601f9e760ff3fb6ba05"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Config/zipball/32018f35de323afd1bffb601f9e760ff3fb6ba05",
+ "reference": "32018f35de323afd1bffb601f9e760ff3fb6ba05",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/filesystem": "~2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Config\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Config Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-05-23 14:36:49"
+ },
+ {
+ "name": "symfony/dependency-injection",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/DependencyInjection",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/DependencyInjection.git",
+ "reference": "4040578469625dc4d3c3c70f583bb995c764c434"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/4040578469625dc4d3c3c70f583bb995c764c434",
+ "reference": "4040578469625dc4d3c3c70f583bb995c764c434",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/config": "~2.2",
+ "symfony/expression-language": "~2.4",
+ "symfony/yaml": "~2.0"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\DependencyInjection\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony DependencyInjection Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-05-23 14:36:49"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/EventDispatcher",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/EventDispatcher.git",
+ "reference": "7a4f4b42886f8c2e35acb1071f157a0b8eb1bd39"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/7a4f4b42886f8c2e35acb1071f157a0b8eb1bd39",
+ "reference": "7a4f4b42886f8c2e35acb1071f157a0b8eb1bd39",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.0",
+ "symfony/dependency-injection": "~2.0",
+ "symfony/stopwatch": "~2.2"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-05-23 14:36:49"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/Filesystem",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Filesystem.git",
+ "reference": "c5535943b0d48e5cc54f5bc8088bfc0aefda7f39"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Filesystem/zipball/c5535943b0d48e5cc54f5bc8088bfc0aefda7f39",
+ "reference": "c5535943b0d48e5cc54f5bc8088bfc0aefda7f39",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Filesystem\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Filesystem Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-06-20 17:41:51"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/Finder",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Finder.git",
+ "reference": "bed12a8b775813b252daf137b64f79113fbc5da5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Finder/zipball/bed12a8b775813b252daf137b64f79113fbc5da5",
+ "reference": "bed12a8b775813b252daf137b64f79113fbc5da5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Finder\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Finder Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-05-23 14:36:49"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/Translation",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Translation.git",
+ "reference": "648fe60e8921358aadb0d50b74339c52691a1763"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Translation/zipball/648fe60e8921358aadb0d50b74339c52691a1763",
+ "reference": "648fe60e8921358aadb0d50b74339c52691a1763",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/config": "~2.0",
+ "symfony/yaml": "~2.2"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Translation\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Translation Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-06-17 05:29:56"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "dev-master",
+ "target-dir": "Symfony/Component/Yaml",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Yaml.git",
+ "reference": "b01d366060f33e18fd98b0008c41a01b0d25c95c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Yaml/zipball/b01d366060f33e18fd98b0008c41a01b0d25c95c",
+ "reference": "b01d366060f33e18fd98b0008c41a01b0d25c95c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Yaml\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Yaml Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-06-04 06:43:44"
+ }
+ ],
+ "aliases": [
+
+ ],
+ "minimum-stability": "dev",
+ "stability-flags": {
+ "symfony/console": 20,
+ "phpspec/phpspec": 20,
+ "behat/behat": 20
+ },
+ "platform": [
+
+ ],
+ "platform-dev": [
+
+ ]
+}
diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php
new file mode 100644
index 0000000..cc265eb
--- /dev/null
+++ b/features/bootstrap/FeatureContext.php
@@ -0,0 +1,80 @@
+binFolder = __DIR__ . '/../../bin/';
+ $this->output = '';
+ }
+
+ /**
+ * @When I run :command
+ */
+ public function iRun($command)
+ {
+ $poser = $this->binFolder . $command;
+ $this->return = -1;
+ ob_start();
+ passthru("cd {$this->binFolder};php $command", $this->return);
+ $this->output = ob_get_clean();
+ }
+
+ /**
+ * @Then the same output should be like the content of :filePath
+ */
+ public function theSameOutputShouldBeLikeTheContentOf($filePath)
+ {
+ $filePath = __DIR__.'/../'.$filePath;
+ $content = file_get_contents($filePath);
+
+ $this->assertEquals($content, $this->output);
+ }
+ /**
+ * @Then it should pass
+ */
+ public function itShouldPass()
+ {
+ if (0 != $this->return) {
+ throw new \Exception('Error executing '.$this->return);
+ }
+ }
+
+ /**
+ * @Then the content of :given should be equal to :expected
+ */
+ public function theContentOfShouldBeEqualTo($given, $expected)
+ {
+ $givenPath = $given;
+ $given = file_get_contents($givenPath);
+
+ $expectedPath = __DIR__.'/../'.$expected;
+ $expected = file_get_contents($expectedPath);
+ unlink($givenPath);
+
+ $this->assertEquals($given, $expected);
+ }
+
+ private function assertEquals($given, $expected)
+ {
+ $expected = preg_replace('/\s+/', '', $expected);
+ $given = preg_replace('/\s+/', '', $given);
+
+ if ($expected != $given) {
+ throw new \Exception('Expected:'.$expected.'\n given:'.$given);
+ }
+ }
+}
diff --git a/features/bootstrap/fixtures/license-MIT-blue.svg b/features/bootstrap/fixtures/license-MIT-blue.svg
new file mode 100644
index 0000000..5d9d856
--- /dev/null
+++ b/features/bootstrap/fixtures/license-MIT-blue.svg
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/features/ui_command_creating_image_file.feature b/features/ui_command_creating_image_file.feature
new file mode 100644
index 0000000..1b50c3a
--- /dev/null
+++ b/features/ui_command_creating_image_file.feature
@@ -0,0 +1,10 @@
+@ui
+Feature: Generation of an image
+ In order to create image by command line
+ As a visitor
+ I want to use the poser script
+
+ Scenario: Create the image running a script
+ When I run "poser license MIT blue -p /tmp/img.svg"
+ Then it should pass
+ And the content of "/tmp/img.svg" should be equal to "bootstrap/fixtures/license-MIT-blue.svg"
\ No newline at end of file
diff --git a/features/ui_command_echo_image.feature b/features/ui_command_echo_image.feature
new file mode 100644
index 0000000..f27df3b
--- /dev/null
+++ b/features/ui_command_echo_image.feature
@@ -0,0 +1,10 @@
+@ui
+Feature: Generation of an image by echo-ing the content
+ In order to create image by command line
+ As a visitor
+ I want to use the poser script
+
+ Scenario: Echo the image running a script
+ When I run "poser license MIT blue"
+ Then it should pass
+ And the same output should be like the content of "bootstrap/fixtures/license-MIT-blue.svg"
\ No newline at end of file
diff --git a/i_m-badge.svg b/i_m-badge.svg
new file mode 100644
index 0000000..b7e984d
--- /dev/null
+++ b/i_m-badge.svg
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/spec/Fixtures/license.svg b/spec/Fixtures/license.svg
new file mode 100644
index 0000000..df4ea43
--- /dev/null
+++ b/spec/Fixtures/license.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/spec/PUGX/Poser/BadgeSpec.php b/spec/PUGX/Poser/BadgeSpec.php
new file mode 100644
index 0000000..8a48662
--- /dev/null
+++ b/spec/PUGX/Poser/BadgeSpec.php
@@ -0,0 +1,63 @@
+beConstructedWith('a','b','97CA00', 'svg');
+ $this->shouldHaveType('Pugx\Poser\Badge');
+ }
+
+ function it_should_be_constructed_by_fromURI_factory_method()
+ {
+ $this->beConstructedWith('a','b','97CA00', 'svg');
+ $assert = 'version-stable-97CA00.svg';
+ $it = \PUGX\Poser\Badge::fromURI($assert);
+
+ if ((string) $it !== $assert) {
+ throw new Exception(sprintf("from[%s] having[%s]\n", $assert, (string) $it));
+ }
+ }
+
+ function it_should_be_constructed_by_fromURI_factory_method_escaping_correctly_underscores()
+ {
+ $this->beConstructedWith('a','b','97CA00', 'svg');
+ $input = 'I__m__liugg__io-b-97CA00.svg';
+ $assertInput = 'I_m_liugg_io-b-97CA00.svg';
+ $it = \PUGX\Poser\Badge::fromURI($input);
+
+ if ((string) $it !== $assertInput) {
+ throw new Exception(sprintf("from[%s] wants[%s] having[%s]\n", $input, $assertInput, (string) $it));
+ }
+ }
+
+ function it_should_be_constructed_by_fromURI_factory_method_escaping_correctly_with_single_underscore()
+ {
+ $this->beConstructedWith('a','b','97CA00', 'svg');
+ $input = 'I_m_liuggio-b-97CA00.svg';
+ $assertInput = 'I m liuggio-b-97CA00.svg';
+ $it = \PUGX\Poser\Badge::fromURI($input);
+
+ if ((string) $it !== $assertInput) {
+ throw new Exception(sprintf("from[%s] wants[%s] having[%s]\n", $input, $assertInput, (string) $it));
+ }
+ }
+
+ function it_should_be_constructed_by_fromURI_factory_method_escaping_correctly_with_dashes()
+ {
+ $this->beConstructedWith('a','b','97CA00', 'svg');
+ $input = 'I--m--liuggio-b-97CA00.svg';
+ $assertInput = 'I-m-liuggio-b-97CA00.svg';
+ $it = \PUGX\Poser\Badge::fromURI($input);
+
+ if ((string) $it !== $assertInput) {
+ throw new Exception(sprintf("from[%s] wants[%s] having[%s]\n", $input, $assertInput, (string) $it));
+ }
+ }
+}
diff --git a/spec/PUGX/Poser/PoserSpec.php b/spec/PUGX/Poser/PoserSpec.php
new file mode 100644
index 0000000..d578933
--- /dev/null
+++ b/spec/PUGX/Poser/PoserSpec.php
@@ -0,0 +1,59 @@
+beConstructedWith(array('svg' => $render));
+ }
+
+ function it_is_initializable()
+ {
+ $this->shouldHaveType('PUGX\Poser\Poser');
+ }
+
+ function it_should_be_able_to_generate_an_svg_image()
+ {
+ $subject = 'stable';
+ $status = 'v2.0';
+ $color = '97CA00';
+ $format = 'svg';
+
+ $this->generate($subject, $status, $color, $format)->shouldBeAValidSVGImageContaining($subject, $status);
+ }
+
+ function it_should_be_able_to_generate_an_svg_image_from_URI()
+ {
+ $subject = 'stable-v2.0-97CA00.svg';
+
+ $this->generateFromURI($subject)->shouldBeAValidSVGImageContaining('stable', 'v2.0');
+ }
+
+
+ public function getMatchers()
+ {
+ return [
+ 'beAValidSVGImage' => function($subject) {
+
+ $regex = '/^$/';
+ $matches = array();
+
+ return preg_match($regex, $subject, $matches, PREG_OFFSET_CAPTURE, 0);
+ },
+ 'beAValidSVGImageContaining' => function($object, $subject, $status) {
+
+ $regex = '/^$/';
+ $matches = array();
+
+ return preg_match($regex, $object, $matches, PREG_OFFSET_CAPTURE, 0);
+ },
+ ];
+ }
+}
diff --git a/spec/PUGX/Poser/Render/SvgRenderSpec.php b/spec/PUGX/Poser/Render/SvgRenderSpec.php
new file mode 100644
index 0000000..f7f9999
--- /dev/null
+++ b/spec/PUGX/Poser/Render/SvgRenderSpec.php
@@ -0,0 +1,44 @@
+calculateWidth(Argument::any())->willReturn(20);
+ $this->beConstructedWith($calculator);
+ }
+
+ function it_should_render_a_svg()
+ {
+ $badge = Badge::fromURI('version-stable-97CA00.svg');
+ $this->render($badge)->shouldBeAValidSVGImage();
+ }
+
+ public function getMatchers()
+ {
+ return [
+ 'beAValidSVGImage' => function($subject) {
+
+ $regex = '/^$/';
+ $matches = array();
+
+ return preg_match($regex, $subject, $matches, PREG_OFFSET_CAPTURE, 0);
+ },
+ 'beAValidSVGImageContaining' => function($object, $subject, $status) {
+
+ $regex = '/^$/';
+ $matches = array();
+
+ return preg_match($regex, $object, $matches, PREG_OFFSET_CAPTURE, 0);
+ },
+ ];
+ }
+}
\ No newline at end of file
diff --git a/src/Badge.php b/src/Badge.php
new file mode 100644
index 0000000..8c502bd
--- /dev/null
+++ b/src/Badge.php
@@ -0,0 +1,150 @@
+ "4c1",
+ "green" => "97CA00",
+ "yellow" => "dfb317",
+ "yellowgreen" => "a4a61d",
+ "orange" => "fe7d37",
+ "red" => "e05d44",
+ "blue" => "007ec6",
+ "grey" => "555",
+ "lightgray" => "9f9f9f"
+ );
+
+ private $subject;
+ private $status;
+ private $color;
+ private $format;
+
+ public function __construct($subject, $status, $color, $format = self::DEFAULT_FORMAT)
+ {
+ $this->subject = $this->escapeValue($subject);
+ $this->status = $this->escapeValue($status);
+ $this->format = $this->escapeValue($format);
+ $this->color = $this->getColorHex($color);
+
+ if (!$this->isValidColorHex($this->color)) {
+ throw new \InvalidArgumentException(sprintf('Color not valid %s', $this->color));
+ }
+ }
+
+ /**
+ * An array of the color names available.
+ *
+ * @return array
+ */
+ public static function getColorNamesAvailable()
+ {
+ return array_keys(self::$colorScheme);
+ }
+
+ /**
+ * Factory method the creates a Badge from an URI
+ * eg. I_m-liuggio-yellow.svg
+ *
+ * @param string $URI
+ *
+ * @return Badge
+ * @throws \InvalidArgumentException
+ */
+ public static function fromURI($URI)
+ {
+ $regex = '/^(([^-]|--)+)-(([^-]|--)+)-(([^-]|--)+)\.(svg|png|gif|jpg)$/';
+ $match = array();
+
+ if (1 != preg_match($regex, $URI, $match) && (7 != count($match))) {
+ throw new \InvalidArgumentException('The URI given is not a valid URI'.$URI);
+ }
+
+ $subject = $match[1];
+ $status = $match[3];
+ $color = $match[5];
+ $format = $match[7];
+
+ return new self($subject, $status, $color, $format);
+ }
+
+ /**
+ * @return string the Hexadecimal #FFFFFF.
+ */
+ public function getHexColor()
+ {
+ return '#'.$this->color;
+ }
+
+ /**
+ * @return string the format of the image eg. `svg`.
+ */
+ public function getFormat()
+ {
+ return $this->format;
+ }
+
+ /**
+ * @return string
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSubject()
+ {
+ return $this->subject;
+ }
+
+ public function __toString()
+ {
+ return sprintf("%s-%s-%s.%s",
+ $this->subject,
+ $this->status,
+ $this->color,
+ $this->format
+ );
+ }
+
+ private function escapeValue($value)
+ {
+ $pattern = array(
+ // '/([^_])_([^_])/g', // damn it global doesn't work in PHP
+ '/([^_])_$/',
+ '/^_([^_])/',
+ '/__/',
+ '/--+/',
+ );
+ $replacement = array(
+ //'$1 $2',
+ '$1 ',
+ ' $1',
+ '°§*¼',
+ '-',
+ );
+ $ret = preg_replace($pattern, $replacement, $value);
+ $ret = str_replace('_', ' ', $ret); // this fix the php pgrep_replace is not global :(
+ $ret = str_replace('°§*¼', '_', $ret); // this fix the php pgrep_replace is not global :(
+
+ return $ret;
+ }
+
+ private function getColorHex($color)
+ {
+ return array_key_exists($color, self::$colorScheme) ? self::$colorScheme[$color] : $color;
+ }
+
+ private function isValidColorHex($color)
+ {
+ $color = ltrim($color, "#");
+ $regex = '/^[0-9a-fA-F]{6}$/';
+
+ return preg_match($regex, $color);
+ }
+}
diff --git a/src/Calculator/Font/DejaVuSans.ttf b/src/Calculator/Font/DejaVuSans.ttf
new file mode 100755
index 0000000..2db9bde
Binary files /dev/null and b/src/Calculator/Font/DejaVuSans.ttf differ
diff --git a/src/Calculator/GDTextSizeCalculator.php b/src/Calculator/GDTextSizeCalculator.php
new file mode 100644
index 0000000..84adb47
--- /dev/null
+++ b/src/Calculator/GDTextSizeCalculator.php
@@ -0,0 +1,42 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PUGX\Poser\Calculator;
+
+class GDTextSizeCalculator implements TextSizeCalculatorInterface
+{
+ const TEXT_FONT = '/Font/DejaVuSans.ttf';
+
+ public function __construct()
+ {
+ $this->fontPath = __DIR__ . self::TEXT_FONT;
+ }
+
+ /**
+ * Calculate the width of the text box.
+ *
+ * @param string $text
+ * @param int $size
+ *
+ * @return float
+ */
+ public function calculateWidth($text, $size = self::TEXT_SIZE)
+ {
+ $size = $this->convertToPt($size);
+ $box = imagettfbbox($size, 0, $this->fontPath, $text);
+
+ return round(abs($box[2] - $box[0]) + self::SHIELD_PADDING_EXTERNAL + self::SHIELD_PADDING_INTERNAL, 1);
+ }
+
+ private function convertToPt($pixels)
+ {
+ return round($pixels * 0.75, 1);
+ }
+}
diff --git a/src/Calculator/TextSizeCalculatorInterface.php b/src/Calculator/TextSizeCalculatorInterface.php
new file mode 100644
index 0000000..ae79caa
--- /dev/null
+++ b/src/Calculator/TextSizeCalculatorInterface.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace PUGX\Poser\Calculator;
+
+interface TextSizeCalculatorInterface
+{
+ const TEXT_SIZE = 11;
+ const SHIELD_PADDING_EXTERNAL = 6;
+ const SHIELD_PADDING_INTERNAL = 4;
+
+ /**
+ * Calculate the width of the text box.
+ *
+ * @param string $text
+ * @param int $size
+ *
+ * @return float
+ */
+ public function calculateWidth($text, $size = self::TEXT_SIZE);
+}
diff --git a/src/Poser.php b/src/Poser.php
new file mode 100644
index 0000000..de4261c
--- /dev/null
+++ b/src/Poser.php
@@ -0,0 +1,79 @@
+renders = array();
+
+ foreach ($renders as $format => $render) {
+ $this->addFormatRender($format, $render);
+ }
+ }
+
+ /**
+ * Generate and Render a badge according to the format.
+ *
+ * @param $subject
+ * @param $status
+ * @param $color
+ * @param $format
+ *
+ * @return string
+ */
+ public function generate($subject, $status, $color, $format)
+ {
+ $badge = new Badge($subject, $status, $color, $format);
+
+ return $this->getRenderFor($badge->getFormat())->render($badge);
+ }
+
+ /**
+ * Generate and Render a badge according to the format from an URI,
+ * eg license-MIT-blue.svg or I_m-liuggio-yellow.svg.
+ *
+ * @param $string
+ * @return mixed
+ */
+ public function generateFromURI($string)
+ {
+ $badge = Badge::fromURI($string);
+
+ return $this->getRenderFor($badge->getFormat())->render($badge);
+ }
+
+ /**
+ * All the formats available.
+ *
+ * @return array
+ */
+ public function validFormats()
+ {
+ return array_keys($this->renders);
+ }
+
+ private function addFormatRender($format, RenderInterface $render)
+ {
+ $this->renders[$format] = $render;
+ }
+
+ private function getRenderFor($format)
+ {
+ if (!isset($this->renders[$format])) {
+ throw new \InvalidArgumentException(sprintf('No render founds for this format [%s]', $format));
+ }
+
+ return $this->renders[$format];
+ }
+}
diff --git a/src/Render/RenderInterface.php b/src/Render/RenderInterface.php
new file mode 100644
index 0000000..65f18d2
--- /dev/null
+++ b/src/Render/RenderInterface.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace PUGX\Poser\Render;
+
+use PUGX\Poser\Badge;
+
+interface RenderInterface
+{
+ public function render(Badge $badge);
+}
diff --git a/src/Render/SvgRender.php b/src/Render/SvgRender.php
new file mode 100644
index 0000000..2407ecc
--- /dev/null
+++ b/src/Render/SvgRender.php
@@ -0,0 +1,97 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace PUGX\Poser\Render;
+
+use PUGX\Poser\Badge;
+use PUGX\Poser\Calculator\TextSizeCalculatorInterface;
+use PUGX\Poser\Calculator\GDTextSizeCalculator;
+
+/**
+ * Class SvgGenerator
+ *
+ * @author Claudio D'Alicandro
+ * @author Giulio De Donato
+ */
+class SvgRender implements RenderInterface
+{
+ const VENDOR_COLOR = '#555';
+
+ private $textSizeCalculator;
+ private static $template = '';
+
+ /**
+ * Constructor.
+ *
+ * @param TextSizeCalculatorInterface $textSizeCalculator
+ */
+ public function __construct(TextSizeCalculatorInterface $textSizeCalculator = null)
+ {
+ $this->textSizeCalculator = $textSizeCalculator;
+
+ if (null === $this->textSizeCalculator) {
+ $this->textSizeCalculator = new GDTextSizeCalculator();
+ }
+ }
+
+ /**
+ * @param Badge $badge
+ *
+ * @return mixed
+ */
+ public function render(Badge $badge)
+ {
+ $parameters = array();
+
+ $parameters['vendorWidth'] = $this->stringWidth($badge->getSubject());
+ $parameters['valueWidth'] = $this->stringWidth($badge->getStatus());
+ $parameters['totalWidth'] = $parameters['valueWidth'] + $parameters['vendorWidth'];
+ $parameters['vendorColor'] = self::VENDOR_COLOR;
+ $parameters['valueColor'] = $badge->getHexColor();
+ $parameters['vendor'] = $badge->getSubject();
+ $parameters['value'] = $badge->getStatus();
+ $parameters['vendorStartPosition'] = round($parameters['vendorWidth'] / 2, 1) + 1;
+ $parameters['valueStartPosition'] = $parameters['vendorWidth'] + round($parameters['valueWidth'] / 2, 1) - 1;
+
+ return $this->renderSvg(self::$template, $parameters);
+ }
+
+ private function stringWidth($text)
+ {
+ return $this->textSizeCalculator->calculateWidth($text);
+ }
+
+ private function renderSvg($render, $parameters)
+ {
+ foreach ($parameters as $key => $variable) {
+ $render = str_replace(sprintf('{{ %s }}', $key), $variable, $render);
+ }
+
+ return $render;
+ }
+}
diff --git a/src/UI/Command.php b/src/UI/Command.php
new file mode 100644
index 0000000..e2fd60a
--- /dev/null
+++ b/src/UI/Command.php
@@ -0,0 +1,128 @@
+ |_ _ _| _ _ _ _ _ _ _ |
+ |_)(_|(_|(_|(/_ |_)(_)_\(/_| |
+ _| _|______________|
+
+ http://poser.pug.org
+";
+
+ private $poser;
+
+ private function init()
+ {
+ $this->poser = new Poser(array('svg' => new SvgRender()));
+ $this->format = 'svg';
+ $this->header = self::HEADER;
+ }
+
+ protected function configure()
+ {
+ $this->init();
+
+ $this
+ ->setName('generate')
+ ->setDescription('Create a badge you are a Poser.')
+ ->addArgument(
+ 'subject',
+ InputArgument::OPTIONAL,
+ 'The subject eg. `license`'
+ )
+ ->addArgument(
+ 'status',
+ InputArgument::OPTIONAL,
+ 'The status example `MIT`'
+ )
+ ->addArgument(
+ 'color',
+ InputArgument::OPTIONAL,
+ 'The hexadecimal color eg. `97CA00` or the name ['.join(', ', Badge::getColorNamesAvailable()).']'
+ )
+ ->addOption(
+ 'format',
+ 'f',
+ InputOption::VALUE_REQUIRED,
+ 'The format of the image eg. `svg`, formats available ['.join(', ', $this->poser->validFormats()).']'
+ )
+ ->addOption(
+ 'path',
+ 'p',
+ InputOption::VALUE_REQUIRED,
+ 'The path of the file to save the create eg. `/tmp/license.svg`'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+
+ $subject = $input->getArgument('subject');
+ $status = $input->getArgument('status');
+ $color = $input->getArgument('color');
+
+ if ($input->getOption('format')) {
+ $this->format = $input->getOption('format');
+ }
+
+ try {
+ $imageContent = $this->poser->generate($subject, $status, $color, $this->format);
+
+ if ($input->getOption('path')) {
+ $this->storeImage($input, $output, $input->getOption('path'), $imageContent);
+ } else {
+ $this->flushImage($input, $output, $imageContent);
+ }
+
+ } catch (\Exception $e) {
+ $this->printHeaderOnce($output);
+ throw $e;
+ }
+ }
+
+ protected function flushImage(InputInterface $input, OutputInterface $output, $imageContent)
+ {
+ $output->write($imageContent);
+ $this->header = '';
+ }
+
+ protected function storeImage(InputInterface $input, OutputInterface $output, $path, $imageContent)
+ {
+ $this->printHeaderOnce($output);
+ $fp = fopen($path,"x"); // if file already exists warning is raised
+
+ if (false == $fp) {
+ throw new \Exception("Error on creating the file maybe file [$path] already exists?");
+ }
+ $written = @fwrite($fp, $imageContent);
+ if ($written <1 || $written != strlen($imageContent)) {
+ throw new \Exception('Error on writing to file.');
+ }
+ fclose($fp);
+
+ $output->write(sprintf('Image created at %s', $path));
+ }
+
+ protected function printHeaderOnce(OutputInterface $output)
+ {
+ if (!empty($this->header)) {
+ $output->write($this->header);
+ }
+
+ $this->header = '';
+ }
+
+}
diff --git a/src/UI/SingleCommandApplication.php b/src/UI/SingleCommandApplication.php
new file mode 100644
index 0000000..545977f
--- /dev/null
+++ b/src/UI/SingleCommandApplication.php
@@ -0,0 +1,87 @@
+run();
+ *
+ * @author Stefaan Lippens
+ */
+class SingleCommandApplication extends Application
+{
+ /**
+ * Name of the single accessible command of this application
+ * @var string
+ */
+ private $commandName;
+
+ /**
+ * Constructor to build a "single command" application, given a command.
+ *
+ * The application will adopt the same name as the command.
+ *
+ * @param Command $command The single (accessible) command for this application
+ * @param string $version The version of the application
+ */
+ public function __construct(Command $command, $version = 'UNKNOWN')
+ {
+ parent::__construct($command->getName(), $version);
+
+ // Add the given command as single (accessible) command.
+ $this->add($command);
+ $this->commandName = $command->getName();
+
+ // Override the Application's definition so that it does not
+ // require a command name as first argument.
+ $this->getDefinition()->setArguments();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getCommandName(InputInterface $input)
+ {
+ return $this->commandName;
+ }
+
+ /**
+ * Adds a command object.
+ *
+ * This function overrides (public) Application::add()
+ * but should should only be used internally.
+ * Will raise \LogicException when called
+ * after the single accessible command is set up
+ * (from the constructor).
+ *
+ * @param Command $command A Command object
+ *
+ * @return Command The registered command
+ *
+ * @throws \LogicException
+ */
+ public function add(Command $command)
+ {
+ // Fail if we already set up the single accessible command.
+ if ($this->commandName) {
+ throw new \LogicException("You should not add additional commands to a SingleCommandApplication instance.");
+ }
+
+ return parent::add($command);
+ }
+}
diff --git a/today-dark.svg b/today-dark.svg
new file mode 100644
index 0000000..0ca6d85
--- /dev/null
+++ b/today-dark.svg
@@ -0,0 +1,18 @@
+
\ No newline at end of file