composer update

This commit is contained in:
2019-07-08 14:50:37 +02:00
parent 8706d63867
commit 1a3955a605
969 changed files with 27252 additions and 13915 deletions
+1
View File
@@ -1 +1,2 @@
conf/nginx.conf
/vendor/
+1 -2
View File
@@ -23,7 +23,7 @@
},
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.4.*",
"symfony/symfony": "^3.4",
"doctrine/orm": "^2.6.2",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
@@ -55,7 +55,6 @@
"fairlane/cookie-consent-bundle": "^1.0",
"jms/serializer-bundle": "^2.4",
"friendsofsymfony/rest-bundle": "^2.4",
"symfony/twig-bundle": "^4.1",
"white-october/pagerfanta-bundle": "^1.2",
"willdurand/hateoas-bundle": "^1.4",
"lexik/jwt-authentication-bundle": "^2.5",
+491 -320
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
/vendor
composer.lock
@@ -0,0 +1,12 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
before_script:
- composer install
@@ -0,0 +1,18 @@
# CHANGLOG
## 1.1.0 (12/07/2016)
* [feature] Add methods hasEdge/getEdge on graph (Alexandre Salomé)
* [feature] Add methods getAttribute on node and edge (Alexandre Salomé)
* [feature] Add method get($id) on graph to get a subgraph or a node (Alexandre Salomé)
* [feature] Disable label escaping (Alexandre Salomé)
## 1.0.1 (21/05/2014)
* [bug] Remove semicolon at the end of output (Clemens Tolboom)
## 1.0.0 (10/05/2013)
* [feature] Initial release (Alexandre Salomé)
* [bug] Enable escaping for hyphens (Aurélien Fredouelle)
* [bug] Coding standards and tests (George Petsagourakis)
@@ -0,0 +1,18 @@
# Contributors
## By order of appearance
* Alexandre Salomé
* George Petsagourakis
* Aurélien Fredouelle
* Olivier Dolbeau
* Clemens Tolboom
* Oskar Stark
## Command used to generate:
```
git log --reverse --format="%aN" \
| sed "s/alexandresalome/Alexandre Salomé/g" \
| perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'
```
@@ -1,11 +1,11 @@
Copyright (C) 2016 Composer
Copyright (c) Alexandre Salomé
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.
@@ -15,5 +15,5 @@ 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.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,127 @@
# Graphviz
![Build status](https://travis-ci.org/alexandresalome/graphviz.png?branch=master) [![Latest Stable Version](https://poser.pugx.org/alom/graphviz/v/stable)](https://packagist.org/packages/alom/graphviz) [![Total Downloads](https://poser.pugx.org/alom/graphviz/downloads)](https://packagist.org/packages/alom/graphviz) [![License](https://poser.pugx.org/alom/graphviz/license)](https://packagist.org/packages/alom/graphviz) [![Monthly Downloads](https://poser.pugx.org/alom/graphviz/d/monthly)](https://packagist.org/packages/alom/graphviz) [![Daily Downloads](https://poser.pugx.org/alom/graphviz/d/daily)](https://packagist.org/packages/alom/graphviz)
Graphviz generation for PHP
* [View CHANGELOG](CHANGELOG.md)
* [View CONTRIBUTORS](CONTRIBUTORS.md)
[![Build Status](https://secure.travis-ci.org/alexandresalome/graphviz.png?branch=master)](http://travis-ci.org/alexandresalome/graphviz)
## Installation
Install the latest version with:
```bash
composer require alom/graphviz
```
## Usage
This library allow you to create Dot Graph with a PHP fluid interface:
```php
$graph = new Alom\Graphviz\Digraph('G');
$graph
->subgraph('cluster_1')
->attr('node', array('style' => 'filled', 'fillcolor' => 'blue'))
->node('A')
->node('B')
->edge(array('b0', 'b1', 'b2', 'b3'))
->end()
->edge(array('A', 'B', 'C'))
;
echo $graph->render();
```
### Escaping of labels
By default, labels will be escaped, so that your PHP string is represented "as it is" in the graph. If you don't want the label to be escaped, add set the special **_escaped** attribute to false:
```php
$graph = new Alom\Graphviz\Digraph('G');
$graph
->node('my_table', array(
'label' => '<<table>...</table>>',
'_escaped' => false
))
```
### Browsing the graph
When you have created lot of subgraphs and nodes, it might be useful to be able to browse it using identifiers. For example, if you have the following graph:
```php
$graph = new Alom\Graphviz\Digraph('G');
$graph
->subgraph('cluster_1')
->node('A')
->node('B')
->end()
->subgraph('cluster_2')
->node('C')
->node('D')
->end()
->edge(array('C', 'D'))
;
```
You can do the following to access the nodes in the existing graph:
```php
$cluster = $graph->get('cluster_1');
$node = $graph->get('cluster_2')->get('D');
```
When you have a node or an edge, you can manipulate its attributes:
```php
# read a value
echo $node->getAttribute('label', 'no label'); # second argument is default value
# write a value
$node->attribute('label', 'new label');
```
On a graph, you can access or verify edge existence:
```
$graph->hasEdge(array('A', 'B'));
$graph->getEdge(array('C', 'D'));
```
### Using cluster and record IDs
If you create an edge from/to an ID inside a record, use an array instead of a string:
```php
$graph = new Alom\Graphviz\Digraph('G');
$graph
->node('A', array('shape' => 'record', 'label' => '{ <1> Part 1 | <2> Part 2}'))
->node('B')
->edge(array('B', array('A', '1')))
;
```
As you can see in the example above, the edge is composed of two parts:
* ``'B'``: a regular node
* ``array('A', '1')``: targets the cell "1" inside the A node
This method also work for **getEdge**, **hasEdge** and every edge-related method.
## Samples
Take a look at examples located in **samples** folder:
* [00-readme.php](samples/00-readme.php): Example from graphviz README
* [01-basic.php](samples/01-basic.php): Basic styling of nodes
* [02-table.php](samples/02-table.php): An example for HTML table escaping
You can generate any of those graph by using the following commands:
```bash
php samples/00-readme.php | dot -Tpdf -oout.pdf
xdg-open out.pdf
```
@@ -0,0 +1,26 @@
{
"name": "alom/graphviz",
"description": "Graphviz generation for PHP",
"keywords": ["dot", "graphviz"],
"homepage": "http://github.com/alexandresalome/graphviz",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Alexandre Salomé",
"email": "alexandre.salome@gmail.com",
"homepage": "http://alexandre-salome.fr"
}
],
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"autoload": {
"psr-0": {
"Alom": "src/"
}
}
}
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Alom Graphviz Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
</whitelist>
</filter>
</phpunit>
@@ -0,0 +1,23 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require_once __DIR__ . '/../vendor/autoload.php';
$graph = new Alom\Graphviz\Digraph('G');
$graph
->subgraph('cluster_1')
->attr('node', array('style' => 'filled', 'fillcolor' => 'blue'))
->node('A')
->node('B')
->end()
->edge(array('A', 'B', 'C'))
;
echo $graph->render();
@@ -0,0 +1,36 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require_once __DIR__ . '/../vendor/autoload.php';
$graph = new Alom\Graphviz\Digraph('G');
$graph
->subgraph('cluster_0')
->set('style', 'filled')
->set('color', 'lightgrey')
->attr('node', array('style' => 'filled', 'color' => 'white'))
->edge(array('a0', 'a1', 'a2', 'a3'))
->set('label', 'process #1')
->end()
->subgraph('cluster_1')
->attr('node', array('style' => 'filled'))
->edge(array('b0', 'b1', 'b2', 'b3'))
->set('label', 'process #2')
->set('color', 'blue')
->end()
->edge(array('start', 'a0'))
->edge(array('start', 'b0'))
->edge(array('a1', 'b3'))
->edge(array('b2', 'a3'))
->edge(array('a3', 'a0'))
->edge(array('a3', 'end'))
->edge(array('b3', 'end'))
;
echo $graph->render();
@@ -0,0 +1,27 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require_once __DIR__ . '/../vendor/autoload.php';
$graph = new Alom\Graphviz\Digraph('G');
$graph
->node('escaped', array(
'label' => '<<table><tr><td>Should be escaped</td></tr></table>>',
))
->node('unescaped', array(
'label' => '<<table><tr><td>Should not be escaped</td></tr></table>>',
'_escaped' => false,
))
->edge(array('escaped', 'unescaped'), array(
'label' => '<<table><tr><td>label</td></tr></table>>',
'_escaped' => false,
))
;
echo $graph->render();
@@ -0,0 +1,78 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Graph attribute assignment.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class Assign extends BaseInstruction
{
/** @var string Name of the attribute */
protected $name;
/** @var string Value of the assignment */
protected $value;
/**
* Creates a new assignment
*
* @param string $name Name of the attribute to set
* @param string $value Value of the attribute
*/
public function __construct($name, $value = NULL)
{
$this->name = $name;
$this->value = $value;
}
/**
* Returns the name of assignment.
*
* @return string The assignment name
*/
public function getName()
{
return $this->name;
}
/**
* Returns the value of assignment.
*
* @return string the assignment value
*/
public function getValue()
{
return $this->value;
}
/**
* Changes the value of assignment.
*
* @param string $value The new value to set
*
* @return Assign Fluid interface
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* @inheritdoc
*/
public function render($indent = 0, $spaces = self::DEFAULT_INDENT)
{
return str_repeat($spaces, $indent) . $this->renderInlineAssignment($this->name, $this->value) . ";\n";
}
}
@@ -0,0 +1,99 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Attribute holder for nodes and edges.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class AttributeBag extends BaseInstruction
{
/** @var array Associative array of attributes. The key is the name. */
protected $attributes;
/**
* Creates a new attribute bag.
*
* @param array $attributes An associative array of attributes values
*/
public function __construct(array $attributes = array())
{
if (isset($attributes['_escaped'])) {
$escaped = $attributes['_escaped'];
unset($attributes['_escaped']);
} else {
$escaped = true;
}
if (!$escaped && isset($attributes['label'])) {
$attributes['label'] = new RawText($attributes['label']);
}
$this->attributes = $attributes;
}
/**
* Changes the value of an attribute.
*
* @param string $name The name for the attribute
* @param string $value Value to set
*
* @return AttributeBag Fluid interface
*/
public function set($name, $value)
{
$this->attributes[$name] = $value;
return $this;
}
/**
* Returns the value of an attribute.
*
* @param string $name The name for the attribute
* @param string $default Default value if attribute is not set.
*
* @return string|mixed The attribute value
*/
public function get($name, $default = null)
{
return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
}
/**
* Tests if the bag has an attribute.
*
* @param string $name The attribute name to check
*
* @return boolean Result of the test
*/
public function has($name)
{
return isset($this->attributes[$name]);
}
/**
* @inheritdoc
*/
public function render($indent = 0, $spaces = self::DEFAULT_INDENT)
{
if (0 == count($this->attributes)) {
return '';
}
$exp = array();
foreach ($this->attributes as $name => $value) {
$exp[] = $this->renderInlineAssignment($name, $value);
}
return '[' . implode(', ', $exp) . ']';
}
}
@@ -0,0 +1,66 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Attributes bag for node/edge/graph
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class AttributeSet extends BaseInstruction
{
/** @var string Name of shape to set attributes */
protected $name;
/** @var AttributeBag Attribute bag */
protected $attributes;
/**
* Creates a new attribute set
*
* @param string $name Name of the attribute set
* @param array $attributes
*
* @throws \InvalidArgumentException
*/
public function __construct($name, array $attributes = array())
{
if (!in_array($name, array('node', 'edge', 'graph'))) {
throw new \InvalidArgumentException(sprintf('Name invalid for attribute set : %s', $name));
}
$this->name = $name;
$this->attributes = new AttributeBag($attributes);
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return AttributeBag
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* @inheritdoc
*/
public function render($indent = 0, $spaces = self::DEFAULT_INDENT)
{
return str_repeat($spaces, $indent) . $this->name . ' ' . $this->attributes->render() . ";\n";
}
}
@@ -0,0 +1,73 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Base class for Graphviz instructions.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
abstract class BaseInstruction implements InstructionInterface
{
/**
* Renders an inline assignment (without indent or end return line).
*
* It will handle escaping, according to the value.
*
* @param string $name A name
* @param string $value A value
*
* @return string
*/
protected function renderInlineAssignment($name, $value)
{
if ($value instanceof RawText) {
$value = $value->getText();
} else {
$value = $this->escape($value);
}
return $this->escape($name).'='.$value;
}
/**
* Escapes a value if needed.
*
* @param string $value The value to set
*
* @return string The escaped string
*/
protected function escape($value)
{
return ($this->needsEscaping($value)) ? '"' . str_replace('"', '""', str_replace('\\', '\\\\', $value)) . '"' : $value;
}
protected function escapePath(array $path)
{
$list = array();
foreach ($path as $element) {
$list[] = $this->escape($element);
}
return implode(':', $list);
}
/**
* Tests if a string needs escaping.
*
* @param string $value
*
* @return boolean Result of test
*/
protected function needsEscaping($value)
{
return preg_match('/[{} "#-:\\\\\\/\\.,]/', $value) || in_array($value, array('graph', 'node', 'edge')) || empty($value);
}
}
@@ -0,0 +1,34 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Directed graph
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class Digraph extends Graph
{
/**
* @inheritdoc
*/
protected function createEdge($list, array $attributes = array(), BaseInstruction $parent = null)
{
return new DirectedEdge($list, $attributes, $parent);
}
/**
* @inheritdoc
*/
protected function getHeader($id)
{
return 'digraph ' . $id;
}
}
@@ -0,0 +1,26 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Directed edge
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class DirectedEdge extends Edge
{
/**
* @inheritdoc
*/
protected function getOperator()
{
return ' -> ';
}
}
@@ -0,0 +1,125 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Base edge class
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
abstract class Edge extends BaseInstruction
{
/** @var array List of elements */
protected $list;
/** @var AttributeBag Attributes of the edge */
protected $attributes;
/** @var BaseInstruction Parent instruction */
protected $parent;
/**
* Returns operator for associating elements
*
* @return string The operator
*/
abstract protected function getOperator();
/**
* Creates an edge.
*
* @param array $list List of edges
* @param array $attributes Associative array of attributes
* @param BaseInstruction $parent Parent instruction
*/
public function __construct(array $list, array $attributes = array(), BaseInstruction $parent = NULL)
{
$this->list = $list;
$this->attributes = new AttributeBag($attributes);
$this->parent = $parent;
}
/**
* Returns list of elements composing the edge.
*
* @return array
*/
public function getList()
{
return $this->list;
}
/**
* Returns the value of an attribute of the edge.
*
* @param string $name name of the attribute
* @param mixed $default default value if the attribute does not exist
*/
public function getAttribute($name, $default = null)
{
return $this->attributes->get($name, $default);
}
/**
* Sets an attribute.
*
* @param string $name Name of the attribute to set
* @param string $value Value of the attribute to set
*
* @return Edge Fluid-interface
*/
public function attribute($name, $value)
{
$this->attributes->set($name, $value);
return $this;
}
/**
* Returns list of attributes.
*
* @return AttributeBag
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* @inheritdoc
*/
public function render($indent = 0, $spaces = self::DEFAULT_INDENT)
{
$edges = array();
foreach ($this->list as $edge) {
if (is_array($edge)) {
$edges[] = $this->escapePath($edge);
} else {
$edges[] = $this->escape($edge);
}
}
$edge = implode($this->getOperator(), $edges);
$attributes = $this->attributes->render($indent + 1);
return str_repeat($spaces, $indent) . $edge . ($attributes ? ' ' . $attributes : $attributes) . ";\n";
}
/**
* End function for fluid-interface.
*
* @return BaseInstruction|null The parent or null
*/
public function end()
{
return $this->parent;
}
}
@@ -0,0 +1,298 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Base graph instruction.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
abstract class Graph extends BaseInstruction
{
/** @var BaseInstruction Parent node */
protected $parent;
/** @var string Graph identifier */
protected $id;
/** @var string Name of the graph */
protected $name;
/** @var BaseInstruction[] Instructions list */
protected $instructions = array();
/**
* Creates a new edge for the graph.
*
* @param array $list List of elements of the edge
* @param array $attributes Associative array of attributes
* @param BaseInstruction $parent Parent element
*
* @return Edge The created edge
*/
abstract protected function createEdge($list, array $attributes = array(), BaseInstruction $parent = null);
/**
* Returns the graph header (digraph G as example).
*
* @param string $id Identifier of graph
*
* @return string The graph header
*/
abstract protected function getHeader($id);
/**
* Creates a new graph.
*
* @param string $id Identifier of the graph
* @param BaseInstruction $parent Parent element
*/
public function __construct($id, $parent = null)
{
$this->parent = $parent;
$this->id = $id;
}
/**
* Returns identifier of graph.
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Adds a new instruction to graph.
*
* @param InstructionInterface $instruction Instruction to add
*
* @return Graph Fluid-interface
*/
public function append(InstructionInterface $instruction)
{
$this->instructions[] = $instruction;
return $this;
}
/**
* Returns list of instructions.
*
* @return array
*/
public function getInstructions()
{
return $this->instructions;
}
/**
* Returns a node or a subgraph, given his id.
*
* @param string $id the identifier of the node/graph to fetch
*
* @return Node|Graph
*
* @throws InvalidArgumentException node or graph not found
*/
public function get($id)
{
foreach ($this->instructions as $instruction) {
if (!$instruction instanceof Node && !$instruction instanceof Subgraph) {
continue;
}
if ($instruction->getId() == $id) {
return $instruction;
}
}
throw new \InvalidArgumentException(sprintf('Found no node or graph with id "%s" in "%s".', $id, $this->id));
}
/**
* Tests if the graph has an edge.
*
* @param (string|string[])[] a path
*
* @return boolean
*/
public function hasEdge(array $edge)
{
try {
$this->getEdge($edge);
return true;
} catch (\InvalidArgumentException $e) {
return false;
}
}
/**
* Returns an edge by its path.
*
* @param (string|string[])[] a path
*
* @return Edge
*
* @throws InvalidArgumentException path not found
*/
public function getEdge(array $edge)
{
foreach ($this->instructions as $instruction) {
if (!$instruction instanceof Edge) {
continue;
}
if ($instruction->getList() == $edge) {
return $instruction;
}
}
$label = implode(' -> ', array_map(function ($edge) {
if (is_string($edge)) {
return $edge;
}
return implode(':', $edge);
}, $edge));
throw new \InvalidArgumentException(sprintf('Found no edge "%s".', $label));
}
/**
* Adds an assignment instruction.
*
* @param string $name Name of the value to assign
* @param string $value Value to assign
*
* @throws \InvalidArgumentException
* @return Graph Fluid-interface
*/
public function set($name, $value)
{
if (in_array($name, array('graph', 'node', 'edge'))) {
throw new \InvalidArgumentException(sprintf('Use method attr for setting %s', $name));
}
$this->instructions[] = new Assign($name, $value);
return $this;
}
/**
* Define attributes for node/edge/graph.
*
* @param string $name Name of type
* @param array $attributes Attributes of the type
*
* @return \Alom\Graphviz\Graph
*/
public function attr($name, array $attributes)
{
$this->instructions[] = new AttributeSet($name, $attributes);
return $this;
}
/**
* Starts a subgraph.
*
* @param string $id Identifier of subgraph
*
* @return Subgraph
*/
public function subgraph($id)
{
return $this->instructions[] = new Subgraph($id, $this);
}
/**
* Created a new node on graph.
*
* @param string $id Identifier of node
* @param array $attributes Attributes to set on node
*
* @return Graph Fluid-interface
*/
public function node($id, array $attributes = array())
{
$this->instructions[] = new Node($id, $attributes, $this);
return $this;
}
/**
* Created a new node on graph.
*
* @param string $id Identifier of node
* @param array $attributes Attributes to set on node
*
* @return Node
*/
public function beginNode($id, array $attributes = array())
{
return $this->instructions[] = new Node($id, $attributes, $this);
}
/**
* Created a new edge on graph.
*
* @param array $list List of edges
* @param array $attributes Attributes to set on edge
*
* @return Graph Fluid-interface
*/
public function edge($list, array $attributes = array())
{
$this->instructions[] = $this->createEdge($list, $attributes, $this);
return $this;
}
/**
* Created a new edge on graph.
*
* @param array $list List of edges
* @param array $attributes Attributes to set on edge
*
* @return Edge
*/
public function beginEdge($list, array $attributes = array())
{
return $this->instructions[] = $this->createEdge($list, $attributes, $this);
}
/**
* Fluid-interface to access parent.
*
* @return Graph
*/
public function end()
{
return $this->parent;
}
/**
* @inheritdoc
*/
public function render($indent = 0, $spaces = self::DEFAULT_INDENT)
{
$margin = str_repeat($spaces, $indent);
$result = $margin . $this->getHeader($this->id) . ' {' . "\n";
foreach ($this->instructions as $instruction) {
$result .= $instruction->render($indent + 1, $spaces);
}
$result .= $margin . '}' . "\n";
return $result;
}
}
@@ -0,0 +1,30 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Interface of Graphviz instructions.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
interface InstructionInterface
{
const DEFAULT_INDENT = ' ';
/**
* Renders the assign statement.
*
* @param int $indent Current level of indentation
* @param string $spaces
*
* @return string The rendered line
*/
function render($indent = 0, $spaces = self::DEFAULT_INDENT);
}
@@ -0,0 +1,107 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Node instruction.
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class Node extends BaseInstruction
{
/** @var Graph Parent instruction. */
protected $parent;
/** @var string Identifier of the node. */
protected $id;
/** @var AttributeBag Attributes of the node. */
protected $attributes;
/**
* Creates a new node.
*
* @param string $id Identifier of the node
* @param array $attributes Attributes to set on node
* @param Graph $parent Parent instruction
*/
public function __construct($id, array $attributes = array(), $parent = null)
{
$this->parent = $parent;
$this->id = $id;
$this->attributes = new AttributeBag($attributes);
}
/**
* Returns identifier of the node.
*
* @return string Identifier of the node
*/
public function getId()
{
return $this->id;
}
/**
* Returns attributes of the graph.
*
* @return AttributeBag
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Returns the value of an attribute of the node.
*
* @param string $name name of the attribute
* @param mixed $default default value if the attribute does not exist
*/
public function getAttribute($name, $default = null)
{
return $this->attributes->get($name, $default);
}
/**
* Sets an attribute of node.
*
* @param string $name Name of the attribute to set
* @param string $value Value to set
*
* @return \Alom\Graphviz\Node
*/
public function attribute($name, $value)
{
$this->attributes->set($name, $value);
return $this;
}
/**
* Fluid interface method.
*
* @return Graph
*/
public function end()
{
return $this->parent;
}
/**
* @inheritdoc
*/
public function render($indent = 0, $spaces = self::DEFAULT_INDENT)
{
$attributes = $this->attributes->render($indent + 1, $spaces);
return str_repeat($spaces, $indent) . $this->escape($this->id) . ($attributes ? ' ' . $attributes : '') . ";\n";
}
}
@@ -0,0 +1,18 @@
<?php
namespace Alom\Graphviz;
class RawText
{
private $text;
public function __construct($text)
{
$this->text = $text;
}
public function getText()
{
return $this->text;
}
}
@@ -0,0 +1,43 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz;
/**
* Subgraph
*
* @author Alexandre Salomé <alexandre.salome@gmail.com>
*/
class Subgraph extends Graph
{
/**
* @inheritdoc
*/
protected function createEdge($list, array $attributes = array(), BaseInstruction $parent = null)
{
$currentParent = $parent;
while ($currentParent !== null) {
if ($currentParent instanceof Digraph) {
return new DirectedEdge($list, $attributes, $parent);
}
$currentParent = $parent->end();
}
throw new \LogicException('Unable to find edge type');
}
/**
* @inheritdoc
*/
protected function getHeader($id)
{
return 'subgraph ' . $id;
}
}
@@ -0,0 +1,49 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz\Tests;
use Alom\Graphviz\Assign;
class AssignTest extends \PHPUnit_Framework_TestCase
{
public function testValue()
{
$assign = new Assign('foo');
$this->assertEquals(null, $assign->getValue(), "Default value");
$return = $assign->setValue('bar');
$this->assertEquals('bar', $assign->getValue(), "Value getter is correct");
$this->assertSame($return, $assign);
}
public function testName()
{
$assign = new Assign('foo');
$this->assertEquals('foo', $assign->getName(), "name getter");
}
public function testRender()
{
$assign = new Assign('foo', '');
$this->assertEquals("foo=\"\";\n", $assign->render(), "Empty string");
$assign = new Assign('foo', '#bar');
$this->assertEquals("foo=\"#bar\";\n", $assign->render(), "Escaping");
$assign = new Assign('foo', 'a-b');
$this->assertEquals("foo=\"a-b\";\n", $assign->render(), "Escaping hyphens");
$assign = new Assign('foo', 'bar');
$this->assertEquals("foo=bar;\n", $assign->render(), "Render method with simple strings");
$this->assertEquals(" foo=bar;\n", $assign->render(1), "Render method with indent");
$this->assertEquals(" foo=bar;\n", $assign->render(1, " "), "Render method with indent and spaces");
}
}
@@ -0,0 +1,42 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz\Tests;
use Alom\Graphviz\AttributeBag;
class AttributeBagTest extends \PHPUnit_Framework_TestCase
{
public function testGetterSetterHasser()
{
$bag = new AttributeBag(array('foo' => 'bar', 'bar' => 'baz'));
$this->assertEquals('bar', $bag->get('foo'), "Get existing");
$this->assertTrue($bag->has('foo'), "has() with existing");
$this->assertFalse($bag->has('baz'), "has() with inexisting");
$this->assertNull($bag->get('baz'), "Inexisting");
$this->assertFalse($bag->get('baz', false), "Default value");
$bag->set('name', 'alice');
$this->assertEquals('alice', $bag->get('name'));
}
public function testRender()
{
$bag = new AttributeBag();
$this->assertEquals('', $bag->render(), "Empty attribute bag");
$bag->set('foo', 'bar');
$this->assertEquals('[foo=bar]', $bag->render(), "Render with one simple string");
$bag->set('bar', 'foo bar');
$this->assertEquals('[foo=bar, bar="foo bar"]', $bag->render(), "Render with multiple attributes");
}
}
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz\Tests;
use Alom\Graphviz\AttributeSet;
class AttributeSetTest extends \PHPUnit_Framework_TestCase
{
public function testGetters()
{
$set = new AttributeSet('node', array('foo' => 'bar'));
$this->assertEquals('node', $set->getName(), "getName");
$this->assertEquals('bar', $set->getAttributes()->get('foo'), "Attributes");
}
public function testRender()
{
$set = new AttributeSet('node', array('foo' => 'bar'));
$this->assertEquals("node [foo=bar];\n", $set->render(), "Simple render");
$this->assertEquals(" node [foo=bar];\n", $set->render(1), "Render with indent");
$this->assertEquals(" node [foo=bar];\n", $set->render(1, " "), "Render with indent and spaces");
}
/**
* @dataProvider provideIncorrectElement
*/
public function testElement($element, $isCorrect)
{
if (!$isCorrect) {
$this->setExpectedException('InvalidArgumentException');
}
$set = new AttributeSet($element);
}
public function provideIncorrectElement()
{
return array(
array('node', true),
array('edge', true),
array('graph', true),
array('foo', false)
);
}
}
@@ -0,0 +1,204 @@
<?php
/*
* This file is part of Alom Graphviz.
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alom\Graphviz\Tests;
use Alom\Graphviz\Assign;
use Alom\Graphviz\AttributeSet;
use Alom\Graphviz\Digraph;
use Alom\Graphviz\DirectedEdge;
use Alom\Graphviz\Node;
use Alom\Graphviz\Subgraph;
class DigraphTest extends \PHPUnit_Framework_TestCase
{
public function testGet()
{
$graph = new Digraph('G');
$graph->subgraph('foo')
->node('bar', array('label' => 'baz'))
;
$this->assertEquals('baz', $graph->get('foo')->get('bar')->getAttribute('label'));
}
public function testGet_NotExisting()
{
$graph = new Digraph('G');
$graph->node('foo');
try {
$graph->get('bar');
$this->fail();
} catch (\InvalidArgumentException $e) {
// ok
}
}
public function testGetEdge()
{
$graph = new Digraph('G');
$graph->edge(array('A', 'B'));
$graph->edge(array('B', array('C', '1')));
$edge = $graph->getEdge(array('A', 'B'));
$this->assertEquals(array('A', 'B'), $edge->getList());
$edge = $graph->getEdge(array('B', array('C', '1')));
$this->assertEquals(array('B', array('C', 1)), $edge->getList());
}
public function testGetEdge_notExisting()
{
$graph = new Digraph('G');
$graph->edge(array('A', 'B'));
$graph->edge(array('B', array('C', '1')));
try {
$edge = $graph->getEdge(array('A', 'C'));
$this->fail();
} catch (\InvalidArgumentException $e) {
$this->assertEquals('Found no edge "A -> C".', $e->getMessage());
}
try {
$edge = $graph->getEdge(array('A', array('C', '2')));
$this->fail();
} catch (\InvalidArgumentException $e) {
$this->assertEquals('Found no edge "A -> C:2".', $e->getMessage());
}
}
public function testRawText()
{
$graph = new Digraph('G');
$node = $graph->beginNode('foo', array(
'label' => '<bar<BR>baz>',
'_escaped' => false
));
$this->assertInstanceOf('Alom\Graphviz\RawText', $node->getAttributes()->get('label'));
$this->assertEquals("digraph G {\n foo [label=<bar<BR>baz>];\n}\n", $graph->render());
}
public function testRender()
{
$graph = new Digraph('G');
$this->assertEquals("digraph G {\n}\n", $graph->render(), "Render empty graph");
$this->assertEquals(" digraph G {\n }\n", $graph->render(1), "Render empty graph with indent");
$this->assertEquals(" digraph G {\n }\n", $graph->render(1, " "), "Render empty graph with indent and spaces");
$mock = $this->getMock('Alom\Graphviz\InstructionInterface', array('render'));
$mock
->expects($this->once())
->method('render')
->with(2, " ")
->will($this->returnValue(" foobarbaz;\n"))
;
$graph->append($mock);
$this->assertEquals(" digraph G {\n foobarbaz;\n }\n", $graph->render(1, " "), "Render with statements");
}
public function testFluidInterfaceShort()
{
$graph = new Digraph('G');
$graph
->set('rankdir', 'LR')
->node('A')
->node('B')
->edge(array('A', 'B'))
;
$this->assertCount(4, $instructions = $graph->getInstructions(), "3 instructions");
$this->assertTrue($instructions[0] instanceof Assign, "First instruction is assignment");
$this->assertEquals('rankdir', $instructions[0]->getName(), "First instruction name");
$this->assertEquals('LR', $instructions[0]->getValue(), "First instruction value");
$this->assertTrue($instructions[1] instanceof Node, "Second instruction is a node");
$this->assertEquals("A", $instructions[1]->getId(), "Id of first node");
$this->assertTrue($instructions[2] instanceof Node, "Third instruction is a node");
$this->assertEquals("B", $instructions[2]->getId(), "Id of second node");
$this->assertTrue($instructions[3] instanceof DirectedEdge, "Fourth instruction is an edge");
}
public function testFluidInterfaceVerbose()
{
$graph = new Digraph('G');
$graph
->beginNode('A')
->attribute('color', 'red')
->end()
->beginEdge(array('A', 'B'))
->attribute('color', 'blue')
->end()
;
$this->assertCount(2, $instructions = $graph->getInstructions(), "2 instructions");
$this->assertTrue($instructions[0] instanceof Node, "First instructions is a node");
$this->assertEquals('A', $instructions[0]->getId(), "Node identifier");
$this->assertEquals('red', $instructions[0]->getAttributes()->get('color'), "Node attribute");
$this->assertTrue($instructions[1] instanceof DirectedEdge, "Second instructions is a node");
$this->assertEquals('blue', $instructions[1]->getAttributes()->get('color'), "Edge attribute");
}
public function testAttr()
{
$graph = new Digraph('G');
$graph->attr('node', array('color' => 'blue'));
$this->assertCount(1, $instructions = $graph->getInstructions(), "Instruction count");
$this->assertTrue($instructions[0] instanceof AttributeSet, "Instruction is an attribute set");
$this->assertEquals("node", $instructions[0]->getName(), "Name is correct");
$this->assertEquals("blue", $instructions[0]->getAttributes()->get('color'), "Attribute is correct");
}
/**
* @expectedException InvalidArgumentException
* @dataProvider provideIncorrectSetUsage
*/
public function testIncorrectSetUsage($name)
{
$graph = new Digraph('G');
$graph->set($name, 'foo');
}
public function provideIncorrectSetUsage()
{
return array(
array('graph'),
array('edge'),
array('node'),
);
}
public function testSubGraph()
{
$graph = new Digraph('G');
$subgraph = $graph->subgraph('foo');
$subgraph->edge(array('A', 'B'));
$this->assertCount(1, $graph->getInstructions(), "Count of instructions");
$this->assertTrue($subgraph instanceof Subgraph, "Subgraph return");
$this->assertSame('foo', $subgraph->getId(), "Subgraph identifier");
$this->assertSame($graph, $subgraph->end(), "Subgraph end");
$this->assertEquals("subgraph foo {\n A -> B;\n}\n", $subgraph->render(), "Subgraph rendering");
}
}
+1 -1
View File
@@ -279,7 +279,7 @@ class ClassLoader
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
@@ -14,6 +14,7 @@ return array(
'DivisionByZeroError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php',
'Error' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/Error.php',
'IntlDateFormatter' => $vendorDir . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/IntlDateFormatter.php',
'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'Locale' => $vendorDir . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/Locale.php',
'NumberFormatter' => $vendorDir . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/NumberFormatter.php',
'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
+4 -1
View File
@@ -9,10 +9,10 @@ return array(
'3a37ebac017bc098e9a86b35401e7a68' => $vendorDir . '/mongodb/mongodb/src/functions.php',
'06dd8487319ccd8403765f5b8c9f2d61' => $vendorDir . '/alcaeus/mongo-php-adapter/lib/Mongo/functions.php',
'92c8763cd6170fce6fcfe7e26b4e8c10' => $vendorDir . '/symfony/phpunit-bridge/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'9c67151ae59aff4788964ce8eb2a0f43' => $vendorDir . '/clue/stream-filter/src/functions_include.php',
@@ -21,8 +21,11 @@ return array(
'a4ecaeafb8cfb009ad0e052c90355e98' => $vendorDir . '/beberlei/assert/lib/Assert/functions.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php',
'6a47392539ca2329373e0d33e1dba053' => $vendorDir . '/symfony/polyfill-intl-icu/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'ce89ac35a6c330c55f4710717db9ff78' => $vendorDir . '/kriswallsmith/assetic/src/functions.php',
);
+6 -3
View File
@@ -14,13 +14,18 @@ return array(
'Twig\\' => array($vendorDir . '/twig/twig/src'),
'Tests\\' => array($baseDir . '/tests'),
'Symfony\\Polyfill\\Util\\' => array($vendorDir . '/symfony/polyfill-util'),
'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'),
'Symfony\\Polyfill\\Php56\\' => array($vendorDir . '/symfony/polyfill-php56'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Polyfill\\Apcu\\' => array($vendorDir . '/symfony/polyfill-apcu'),
'Symfony\\Contracts\\HttpClient\\' => array($vendorDir . '/symfony/http-client-contracts'),
'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'),
'Symfony\\Component\\HttpClient\\' => array($vendorDir . '/symfony/http-client'),
'Symfony\\Component\\' => array($vendorDir . '/symfony/symfony/src/Symfony/Component'),
'Symfony\\Bundle\\TwigBundle\\' => array($vendorDir . '/symfony/twig-bundle'),
'Symfony\\Bundle\\SwiftmailerBundle\\' => array($vendorDir . '/symfony/swiftmailer-bundle'),
'Symfony\\Bundle\\MonologBundle\\' => array($vendorDir . '/symfony/monolog-bundle'),
'Symfony\\Bundle\\AsseticBundle\\' => array($vendorDir . '/symfony/assetic-bundle'),
@@ -38,7 +43,6 @@ return array(
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Link\\' => array($vendorDir . '/psr/link/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
'Pagerfanta\\' => array($vendorDir . '/pagerfanta/pagerfanta/src/Pagerfanta'),
@@ -94,7 +98,6 @@ return array(
'Doctrine\\Bundle\\MigrationsBundle\\' => array($vendorDir . '/doctrine/doctrine-migrations-bundle'),
'Doctrine\\Bundle\\DoctrineCacheBundle\\' => array($vendorDir . '/doctrine/doctrine-cache-bundle'),
'Doctrine\\Bundle\\DoctrineBundle\\' => array($vendorDir . '/doctrine/doctrine-bundle'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Clue\\StreamFilter\\' => array($vendorDir . '/clue/stream-filter/src'),
'BenTools\\WebPushBundle\\' => array($vendorDir . '/bentools/webpush-bundle/src'),
'Bazinga\\Bundle\\HateoasBundle\\' => array($vendorDir . '/willdurand/hateoas-bundle'),
+35 -16
View File
@@ -10,10 +10,10 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
'3a37ebac017bc098e9a86b35401e7a68' => __DIR__ . '/..' . '/mongodb/mongodb/src/functions.php',
'06dd8487319ccd8403765f5b8c9f2d61' => __DIR__ . '/..' . '/alcaeus/mongo-php-adapter/lib/Mongo/functions.php',
'92c8763cd6170fce6fcfe7e26b4e8c10' => __DIR__ . '/..' . '/symfony/phpunit-bridge/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'9c67151ae59aff4788964ce8eb2a0f43' => __DIR__ . '/..' . '/clue/stream-filter/src/functions_include.php',
@@ -22,9 +22,12 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
'a4ecaeafb8cfb009ad0e052c90355e98' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/functions.php',
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php',
'6a47392539ca2329373e0d33e1dba053' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'ce89ac35a6c330c55f4710717db9ff78' => __DIR__ . '/..' . '/kriswallsmith/assetic/src/functions.php',
);
@@ -51,13 +54,18 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
'S' =>
array (
'Symfony\\Polyfill\\Util\\' => 22,
'Symfony\\Polyfill\\Php73\\' => 23,
'Symfony\\Polyfill\\Php72\\' => 23,
'Symfony\\Polyfill\\Php70\\' => 23,
'Symfony\\Polyfill\\Php56\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Polyfill\\Apcu\\' => 22,
'Symfony\\Contracts\\HttpClient\\' => 29,
'Symfony\\Component\\Mime\\' => 23,
'Symfony\\Component\\HttpClient\\' => 29,
'Symfony\\Component\\' => 18,
'Symfony\\Bundle\\TwigBundle\\' => 26,
'Symfony\\Bundle\\SwiftmailerBundle\\' => 33,
'Symfony\\Bundle\\MonologBundle\\' => 29,
'Symfony\\Bundle\\AsseticBundle\\' => 29,
@@ -78,7 +86,6 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
'Psr\\Log\\' => 8,
'Psr\\Link\\' => 9,
'Psr\\Http\\Message\\' => 17,
'Psr\\Http\\Client\\' => 16,
'Psr\\Container\\' => 14,
'Psr\\Cache\\' => 10,
'Pagerfanta\\' => 11,
@@ -167,7 +174,6 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
),
'C' =>
array (
'Composer\\CaBundle\\' => 18,
'Clue\\StreamFilter\\' => 18,
),
'B' =>
@@ -218,6 +224,14 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-util',
),
'Symfony\\Polyfill\\Php73\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php73',
),
'Symfony\\Polyfill\\Php72\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
),
'Symfony\\Polyfill\\Php70\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php70',
@@ -230,6 +244,10 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
),
'Symfony\\Polyfill\\Intl\\Idn\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
),
'Symfony\\Polyfill\\Ctype\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
@@ -238,14 +256,22 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-apcu',
),
'Symfony\\Contracts\\HttpClient\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/http-client-contracts',
),
'Symfony\\Component\\Mime\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/mime',
),
'Symfony\\Component\\HttpClient\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/http-client',
),
'Symfony\\Component\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/symfony/src/Symfony/Component',
),
'Symfony\\Bundle\\TwigBundle\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/twig-bundle',
),
'Symfony\\Bundle\\SwiftmailerBundle\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/swiftmailer-bundle',
@@ -314,10 +340,6 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
array (
0 => __DIR__ . '/..' . '/psr/http-message/src',
),
'Psr\\Http\\Client\\' =>
array (
0 => __DIR__ . '/..' . '/psr/http-client/src',
),
'Psr\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/psr/container/src',
@@ -543,10 +565,6 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
array (
0 => __DIR__ . '/..' . '/doctrine/doctrine-bundle',
),
'Composer\\CaBundle\\' =>
array (
0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
),
'Clue\\StreamFilter\\' =>
array (
0 => __DIR__ . '/..' . '/clue/stream-filter/src',
@@ -721,6 +739,7 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
'DivisionByZeroError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php',
'Error' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/Error.php',
'IntlDateFormatter' => __DIR__ . '/..' . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/IntlDateFormatter.php',
'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'Locale' => __DIR__ . '/..' . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/Locale.php',
'NumberFormatter' => __DIR__ . '/..' . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/NumberFormatter.php',
'ParseError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
@@ -1,85 +0,0 @@
composer/ca-bundle
==================
Small utility library that lets you find a path to the system CA bundle,
and includes a fallback to the Mozilla CA bundle.
Originally written as part of [composer/composer](https://github.com/composer/composer),
now extracted and made available as a stand-alone library.
Installation
------------
Install the latest version with:
```bash
$ composer require composer/ca-bundle
```
Requirements
------------
* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.
Basic usage
-----------
# `Composer\CaBundle\CaBundle`
- `CaBundle::getSystemCaRootBundlePath()`: Returns the system CA bundle path, or a path to the bundled one as fallback
- `CaBundle::getBundledCaBundlePath()`: Returns the path to the bundled CA file
- `CaBundle::validateCaFile($filename)`: Validates a CA file using opensl_x509_parse only if it is safe to use
- `CaBundle::isOpensslParseSafe()`: Test if it is safe to use the PHP function openssl_x509_parse()
- `CaBundle::reset()`: Resets the static caches
## To use with curl
```php
$curl = curl_init("https://example.org/");
$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
if (is_dir($caPathOrFile) || (is_link($caPathOrFile) && is_dir(readlink($caPathOrFile)))) {
curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile);
} else {
curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile);
}
$result = curl_exec($curl);
```
## To use with php streams
```php
$opts = array(
'http' => array(
'method' => "GET"
)
);
$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
if (is_dir($caPathOrFile) || (is_link($caPathOrFile) && is_dir(readlink($caPathOrFile)))) {
$opts['ssl']['capath'] = $caPathOrFile;
} else {
$opts['ssl']['cafile'] = $caPathOrFile;
}
$context = stream_context_create($opts);
$result = file_get_contents('https://example.com', false, $context);
```
## To use with Guzzle
```php
$client = new \GuzzleHttp\Client([
\GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
]);
```
License
-------
composer/ca-bundle is licensed under the MIT License, see the LICENSE file for details.
@@ -1,54 +0,0 @@
{
"name": "composer/ca-bundle",
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
"type": "library",
"license": "MIT",
"keywords": [
"cabundle",
"cacert",
"certificate",
"ssl",
"tls"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues"
},
"require": {
"ext-openssl": "*",
"ext-pcre": "*",
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
"psr/log": "^1.0",
"symfony/process": "^2.5 || ^3.0 || ^4.0"
},
"autoload": {
"psr-4": {
"Composer\\CaBundle\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Composer\\CaBundle\\": "tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"config": {
"platform": {
"php": "5.3.9"
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,308 +0,0 @@
<?php
/*
* This file is part of composer/ca-bundle.
*
* (c) Composer <https://github.com/composer>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Composer\CaBundle;
use Psr\Log\LoggerInterface;
use Symfony\Component\Process\PhpProcess;
/**
* @author Chris Smith <chris@cs278.org>
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class CaBundle
{
private static $caPath;
private static $caFileValidity = array();
private static $useOpensslParse;
/**
* Returns the system CA bundle path, or a path to the bundled one
*
* This method was adapted from Sslurp.
* https://github.com/EvanDotPro/Sslurp
*
* (c) Evan Coury <me@evancoury.com>
*
* For the full copyright and license information, please see below:
*
* Copyright (c) 2013, Evan Coury
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
* @return string path to a CA bundle file or directory
*/
public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
{
if (self::$caPath !== null) {
return self::$caPath;
}
// If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
$envCertFile = getenv('SSL_CERT_FILE');
if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
return self::$caPath = $envCertFile;
}
// If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
// This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
$envCertDir = getenv('SSL_CERT_DIR');
if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
return self::$caPath = $envCertDir;
}
$configured = ini_get('openssl.cafile');
if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
return self::$caPath = $configured;
}
$configured = ini_get('openssl.capath');
if ($configured && is_dir($configured) && is_readable($configured)) {
return self::$caPath = $configured;
}
$caBundlePaths = array(
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
'/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
'/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
'/usr/ssl/certs/ca-bundle.crt', // Cygwin
'/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
'/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
'/etc/ssl/cert.pem', // OpenBSD
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
'/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package
);
foreach ($caBundlePaths as $caBundle) {
if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
return self::$caPath = $caBundle;
}
}
foreach ($caBundlePaths as $caBundle) {
$caBundle = dirname($caBundle);
if (@is_dir($caBundle) && glob($caBundle.'/*')) {
return self::$caPath = $caBundle;
}
}
return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort
}
/**
* Returns the path to the bundled CA file
*
* In case you don't want to trust the user or the system, you can use this directly
*
* @return string path to a CA bundle file
*/
public static function getBundledCaBundlePath()
{
$caBundleFile = __DIR__.'/../res/cacert.pem';
// cURL does not understand 'phar://' paths
// see https://github.com/composer/ca-bundle/issues/10
if (0 === strpos($caBundleFile, 'phar://')) {
file_put_contents(
$tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
file_get_contents($caBundleFile)
);
register_shutdown_function(function() use ($tempCaBundleFile) {
@unlink($tempCaBundleFile);
});
$caBundleFile = $tempCaBundleFile;
}
return $caBundleFile;
}
/**
* Validates a CA file using opensl_x509_parse only if it is safe to use
*
* @param string $filename
* @param LoggerInterface $logger optional logger for information about which CA files were loaded
*
* @return bool
*/
public static function validateCaFile($filename, LoggerInterface $logger = null)
{
static $warned = false;
if (isset(self::$caFileValidity[$filename])) {
return self::$caFileValidity[$filename];
}
$contents = file_get_contents($filename);
// assume the CA is valid if php is vulnerable to
// https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
if (!static::isOpensslParseSafe()) {
if (!$warned && $logger) {
$logger->warning(sprintf(
'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
PHP_VERSION
));
$warned = true;
}
$isValid = !empty($contents);
} else {
$isValid = (bool) openssl_x509_parse($contents);
}
if ($logger) {
$logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
}
return self::$caFileValidity[$filename] = $isValid;
}
/**
* Test if it is safe to use the PHP function openssl_x509_parse().
*
* This checks if OpenSSL extensions is vulnerable to remote code execution
* via the exploit documented as CVE-2013-6420.
*
* @return bool
*/
public static function isOpensslParseSafe()
{
if (null !== self::$useOpensslParse) {
return self::$useOpensslParse;
}
if (PHP_VERSION_ID >= 50600) {
return self::$useOpensslParse = true;
}
// Vulnerable:
// PHP 5.3.0 - PHP 5.3.27
// PHP 5.4.0 - PHP 5.4.22
// PHP 5.5.0 - PHP 5.5.6
if (
(PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
|| (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
|| (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
) {
// This version of PHP has the fix for CVE-2013-6420 applied.
return self::$useOpensslParse = true;
}
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
// Windows is probably insecure in this case.
return self::$useOpensslParse = false;
}
$compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
$regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
if (preg_match($regex, PHP_VERSION, $m)) {
return ((int) $m[1]) >= $fixedVersion;
}
return false;
};
// Hard coded list of PHP distributions with the fix backported.
if (
$compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze)
|| $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy)
|| $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise)
) {
return self::$useOpensslParse = true;
}
// Symfony Process component is missing so we assume it is unsafe at this point
if (!class_exists('Symfony\Component\Process\PhpProcess')) {
return self::$useOpensslParse = false;
}
// This is where things get crazy, because distros backport security
// fixes the chances are on NIX systems the fix has been applied but
// it's not possible to verify that from the PHP version.
//
// To verify exec a new PHP process and run the issue testcase with
// known safe input that replicates the bug.
// Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415
// changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593
$cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
$script = <<<'EOT'
error_reporting(-1);
$info = openssl_x509_parse(base64_decode('%s'));
var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
EOT;
$script = '<'."?php\n".sprintf($script, $cert);
try {
$process = new PhpProcess($script);
$process->mustRun();
} catch (\Exception $e) {
// In the case of any exceptions just accept it is not possible to
// determine the safety of openssl_x509_parse and bail out.
return self::$useOpensslParse = false;
}
$output = preg_split('{\r?\n}', trim($process->getOutput()));
$errorOutput = trim($process->getErrorOutput());
if (
count($output) === 3
&& $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
&& $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
&& $output[2] === 'int(-1)'
&& preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
) {
// This PHP has the fix backported probably by a distro security team.
return self::$useOpensslParse = true;
}
return self::$useOpensslParse = false;
}
/**
* Resets the static caches
*/
public static function reset()
{
self::$caFileValidity = array();
self::$caPath = null;
self::$useOpensslParse = null;
}
}
File diff suppressed because it is too large Load Diff
@@ -198,9 +198,6 @@ $foo = $entityManager->find(Foo::class, $foo->getId());
var_dump($foo->misc); // Same as what we set earlier
```
You can execute complex queries using [native queries](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/native-sql.html).
Checkout [the PostgreSQL documentation](http://www.postgresql.org/docs/current/static/datatype-json.html) or [the MySQL](https://dev.mysql.com/doc/refman/en/json.html)
one to learn how to query the stored JSON document.
### Limitations when updating nested properties
@@ -235,6 +232,13 @@ Then, you need to set an option of in the column mapping:
Yes.
**Can I use the native [PostgreSQL](http://www.postgresql.org/docs/current/static/datatype-json.html) and [MySQL](https://dev.mysql.com/doc/refman/en/json.html) /JSON functions?**
Yes! You can execute complex queries using [native queries](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/native-sql.html).
Alternatively, install [scienta/doctrine-json-functions](https://github.com/ScientaNL/DoctrineJsonFunctions) to be able to use run JSON functions in DQL and query builders.
.
**How can I add additional normalizers?**
The Symfony Serializer is easily extensible. This bundle registers and uses a service with ID `dunglas_doctrine_json_odm.serializer` as the serializer for the JSON type. This means we can easily override it in our `services.yaml` to use additional normalizers.
@@ -26,7 +26,8 @@
"symfony/phpunit-bridge": "^3.3 || ^4.0"
},
"suggest": {
"symfony/framework-bundle": "To use the provided bundle."
"symfony/framework-bundle": "To use the provided bundle.",
"scienta/doctrine-json-functions": "To add support for JSON functions in DQL."
},
"autoload": {
"psr-4": { "Dunglas\\DoctrineJsonOdm\\": "src/" }
@@ -1,9 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
+22 -1
View File
@@ -10,6 +10,26 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
## [1.6.0]
### Added
- Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244)
- Added MIME type for WEBP image format (#246)
- Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272)
### Changed
- Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262)
- Accept port number 0 to be valid (#270)
### Fixed
- Fixed subsequent reads from `php://input` in ServerRequest (#247)
- Fixed readable/writable detection for certain stream modes (#248)
- Fixed encoding of special characters in the `userInfo` component of an URI (#253)
## [1.5.2] - 2018-12-04
### Fixed
@@ -209,7 +229,8 @@ Currently unsupported:
[Unreleased]: https://github.com/guzzle/psr7/compare/1.5.2...HEAD
[Unreleased]: https://github.com/guzzle/psr7/compare/1.6.0...HEAD
[1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0
[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2
[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1
[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0
@@ -18,14 +18,18 @@
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5"
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"require-dev": {
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8",
"ext-zlib": "*"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
@@ -39,7 +43,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.5-dev"
"dev-master": "1.6-dev"
}
}
}
@@ -72,7 +72,7 @@ class LimitStream implements StreamInterface
{
if ($whence !== SEEK_SET || $offset < 0) {
throw new \RuntimeException(sprintf(
'Cannot seek to offset % with whence %s',
'Cannot seek to offset %s with whence %s',
$offset,
$whence
));
@@ -66,11 +66,8 @@ trait MessageTrait
public function withHeader($header, $value)
{
if (!is_array($value)) {
$value = [$value];
}
$value = $this->trimHeaderValues($value);
$this->assertHeader($header);
$value = $this->normalizeHeaderValue($value);
$normalized = strtolower($header);
$new = clone $this;
@@ -85,11 +82,8 @@ trait MessageTrait
public function withAddedHeader($header, $value)
{
if (!is_array($value)) {
$value = [$value];
}
$value = $this->trimHeaderValues($value);
$this->assertHeader($header);
$value = $this->normalizeHeaderValue($value);
$normalized = strtolower($header);
$new = clone $this;
@@ -144,11 +138,13 @@ trait MessageTrait
{
$this->headerNames = $this->headers = [];
foreach ($headers as $header => $value) {
if (!is_array($value)) {
$value = [$value];
if (is_int($header)) {
// Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec
// and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass.
$header = (string) $header;
}
$value = $this->trimHeaderValues($value);
$this->assertHeader($header);
$value = $this->normalizeHeaderValue($value);
$normalized = strtolower($header);
if (isset($this->headerNames[$normalized])) {
$header = $this->headerNames[$normalized];
@@ -160,6 +156,19 @@ trait MessageTrait
}
}
private function normalizeHeaderValue($value)
{
if (!is_array($value)) {
return $this->trimHeaderValues([$value]);
}
if (count($value) === 0) {
throw new \InvalidArgumentException('Header value can not be an empty array.');
}
return $this->trimHeaderValues($value);
}
/**
* Trims whitespace from the header values.
*
@@ -177,7 +186,28 @@ trait MessageTrait
private function trimHeaderValues(array $values)
{
return array_map(function ($value) {
return trim($value, " \t");
if (!is_scalar($value) && null !== $value) {
throw new \InvalidArgumentException(sprintf(
'Header value must be scalar or null but %s provided.',
is_object($value) ? get_class($value) : gettype($value)
));
}
return trim((string) $value, " \t");
}, $values);
}
private function assertHeader($header)
{
if (!is_string($header)) {
throw new \InvalidArgumentException(sprintf(
'Header name must be a string but %s provided.',
is_object($header) ? get_class($header) : gettype($header)
));
}
if ($header === '') {
throw new \InvalidArgumentException('Header name can not be empty.');
}
}
}
@@ -36,6 +36,7 @@ class Request implements RequestInterface
$body = null,
$version = '1.1'
) {
$this->assertMethod($method);
if (!($uri instanceof UriInterface)) {
$uri = new Uri($uri);
}
@@ -91,6 +92,7 @@ class Request implements RequestInterface
public function withMethod($method)
{
$this->assertMethod($method);
$new = clone $this;
$new->method = strtoupper($method);
return $new;
@@ -139,4 +141,11 @@ class Request implements RequestInterface
// See: http://tools.ietf.org/html/rfc7230#section-5.4
$this->headers = [$header => [$host]] + $this->headers;
}
private function assertMethod($method)
{
if (!is_string($method) || $method === '') {
throw new \InvalidArgumentException('Method must be a non-empty string.');
}
}
}
@@ -93,11 +93,11 @@ class Response implements ResponseInterface
$version = '1.1',
$reason = null
) {
if (filter_var($status, FILTER_VALIDATE_INT) === false) {
throw new \InvalidArgumentException('Status code must be an integer value.');
}
$this->assertStatusCodeIsInteger($status);
$status = (int) $status;
$this->assertStatusCodeRange($status);
$this->statusCode = (int) $status;
$this->statusCode = $status;
if ($body !== '' && $body !== null) {
$this->stream = stream_for($body);
@@ -125,12 +125,30 @@ class Response implements ResponseInterface
public function withStatus($code, $reasonPhrase = '')
{
$this->assertStatusCodeIsInteger($code);
$code = (int) $code;
$this->assertStatusCodeRange($code);
$new = clone $this;
$new->statusCode = (int) $code;
$new->statusCode = $code;
if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) {
$reasonPhrase = self::$phrases[$new->statusCode];
}
$new->reasonPhrase = $reasonPhrase;
return $new;
}
private function assertStatusCodeIsInteger($statusCode)
{
if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) {
throw new \InvalidArgumentException('Status code must be an integer value.');
}
}
private function assertStatusCodeRange($statusCode)
{
if ($statusCode < 100 || $statusCode >= 600) {
throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.');
}
}
}
@@ -168,7 +168,7 @@ class ServerRequest extends Request implements ServerRequestInterface
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
$headers = getallheaders();
$uri = self::getUriFromGlobals();
$body = new LazyOpenStream('php://input', 'r+');
$body = new CachingStream(new LazyOpenStream('php://input', 'r+'));
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1';
$serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
+15 -18
View File
@@ -10,6 +10,17 @@ use Psr\Http\Message\StreamInterface;
*/
class Stream implements StreamInterface
{
/**
* Resource modes.
*
* @var string
*
* @see http://php.net/manual/function.fopen.php
* @see http://php.net/manual/en/function.gzopen.php
*/
const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/';
const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/';
private $stream;
private $size;
private $seekable;
@@ -18,22 +29,6 @@ class Stream implements StreamInterface
private $uri;
private $customMetadata;
/** @var array Hash of readable and writable stream types */
private static $readWriteHash = [
'read' => [
'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
'x+t' => true, 'c+t' => true, 'a+' => true, 'rb+' => true,
],
'write' => [
'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, 'rb+' => true,
'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
]
];
/**
* This constructor accepts an associative array of options.
*
@@ -65,8 +60,8 @@ class Stream implements StreamInterface
$this->stream = $stream;
$meta = stream_get_meta_data($this->stream);
$this->seekable = $meta['seekable'];
$this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
$this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
$this->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']);
$this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta['mode']);
$this->uri = $this->getMetadata('uri');
}
@@ -197,6 +192,8 @@ class Stream implements StreamInterface
public function seek($offset, $whence = SEEK_SET)
{
$whence = (int) $whence;
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
+29 -7
View File
@@ -437,9 +437,9 @@ class Uri implements UriInterface
public function withUserInfo($user, $password = null)
{
$info = $user;
if ($password != '') {
$info .= ':' . $password;
$info = $this->filterUserInfoComponent($user);
if ($password !== null) {
$info .= ':' . $this->filterUserInfoComponent($password);
}
if ($this->userInfo === $info) {
@@ -537,7 +537,9 @@ class Uri implements UriInterface
$this->scheme = isset($parts['scheme'])
? $this->filterScheme($parts['scheme'])
: '';
$this->userInfo = isset($parts['user']) ? $parts['user'] : '';
$this->userInfo = isset($parts['user'])
? $this->filterUserInfoComponent($parts['user'])
: '';
$this->host = isset($parts['host'])
? $this->filterHost($parts['host'])
: '';
@@ -554,7 +556,7 @@ class Uri implements UriInterface
? $this->filterQueryAndFragment($parts['fragment'])
: '';
if (isset($parts['pass'])) {
$this->userInfo .= ':' . $parts['pass'];
$this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']);
}
$this->removeDefaultPort();
@@ -576,6 +578,26 @@ class Uri implements UriInterface
return strtolower($scheme);
}
/**
* @param string $component
*
* @return string
*
* @throws \InvalidArgumentException If the user info is invalid.
*/
private function filterUserInfoComponent($component)
{
if (!is_string($component)) {
throw new \InvalidArgumentException('User info must be a string');
}
return preg_replace_callback(
'/(?:[^%' . self::$charUnreserved . self::$charSubDelims . ']+|%(?![A-Fa-f0-9]{2}))/',
[$this, 'rawurlencodeMatchZero'],
$component
);
}
/**
* @param string $host
*
@@ -606,9 +628,9 @@ class Uri implements UriInterface
}
$port = (int) $port;
if (1 > $port || 0xffff < $port) {
if (0 > $port || 0xffff < $port) {
throw new \InvalidArgumentException(
sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
sprintf('Invalid port: %d. Must be between 0 and 65535', $port)
);
}
@@ -724,6 +724,7 @@ function mimetype_from_extension($extension)
'txt' => 'text/plain',
'wav' => 'audio/x-wav',
'webm' => 'video/webm',
'webp' => 'image/webp',
'wma' => 'audio/x-ms-wma',
'wmv' => 'video/x-ms-wmv',
'woff' => 'application/x-font-woff',
+2 -12
View File
@@ -13,19 +13,9 @@ return PhpCsFixer\Config::create()
->setRules(array(
'@Symfony' => true,
'@Symfony:risky' => true,
'@PHP71Migration' => true,
'@PHPUnit60Migration:risky' => true,
'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,
'heredoc_to_nowdoc' => false,
'header_comment' => ['header' => $header],
'no_unreachable_default_argument_value' => false,
'ordered_class_elements' => true,
'ordered_imports' => true,
'php_unit_method_casing' => ['case' => 'camel_case'],
'php_unit_set_up_tear_down_visibility' => true,
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced'],
'array_syntax' => ['syntax' => 'short'],
'heredoc_to_nowdoc' => false,
'header_comment' => array('header' => $header),
))
->setRiskyAllowed(true)
->setFinder(
+18 -3
View File
@@ -1,9 +1,13 @@
language: php
sudo: false
php:
- 7.3
- 7.2
- 7.1
- 7.0
- 5.6
- nightly
cache:
directories:
@@ -16,10 +20,20 @@ env:
matrix:
fast_finish: true
include:
- php: 7.1
- php: 5.6
env: COMPOSER_FLAGS="--prefer-lowest"
- php: 5.6
env: FOSUSERBUNDLE_VERSION=1.3.*
- php: 7.0
env: SYMFONY_VERSION=2.8.*
- php: 7.0
env: SYMFONY_VERSION=3.4.*
- php: 7.3
- php: 7.0
env: FOSUSERBUNDLE_VERSION=2.0.*
- php: 7.1
env: TARGET=csfixer_dry_run
allow_failures:
- php: nightly
before_install:
- phpenv config-rm xdebug.ini || echo "xdebug not available";
@@ -27,6 +41,7 @@ before_install:
before_script:
- if [ "$SYMFONY_VERSION" != "" ]; then composer require "symfony/symfony:${SYMFONY_VERSION}" --dev --no-update; fi;
- if [ "$FOSUSERBUNDLE_VERSION" != "" ]; then composer require "friendsofsymfony/user-bundle:${FOSUSERBUNDLE_VERSION}" --dev --no-update; fi;
- if [ "$COMPOSER_FLAGS" != "" ]; then travis_wait composer update --prefer-dist --no-interaction --no-scripts $COMPOSER_FLAGS; fi;
- composer install --prefer-dist --no-interaction --no-scripts
@@ -1,34 +1,5 @@
Changelog
=========
## 1.0.0 (2019-xx-xx)
* Dropped support for PHP 5.6 and 7.0,
* Dropped support for FOSUserBundle 1.3,
* Dropped support for PHPUnit 5,
* Dropped support for Symfony 2.8,
* Minimum Symfony 3 requirement is 3.4,
* Minimum Symfony 4 requirement is 4.2,
* Fixed: WindowsLive Resource Owner token request,
* Fixed: Update Facebook API to v3.1,
* Fixed: Update Linkedin API to v2,
* Fixed: YahooResourceOwner::doGetUserInformationRequest uses wrong arguments,
* Fixed: Symfony 4.2 deprecation warning in `symfony/config`,
* Fixed: SensioConnect now uses new API URLs,
* Fixed: Do not add Authorization header if no client_secret is present,
* Added: Genius.com resource owner,
* Added: HTTPlug 2.0 support,
* Added: Keycloak resource owner,
* Added: The controller is now available as a service,
* Added: Allow to use HTTP Basic auth for token request,
* [BC break] Class `Configuration` has been marked final,
* [BC break] Class `ConnectController` has been marked final,
* [BC break] Class `HWIOAuthExtension` has been marked final,
* [BC break] Class `OAuthExtension` has been marked final,
* [BC break] Class `SetResourceOwnerServiceNameCompilerPass` has been marked final,
* [BC break] Class `ConnectController` extends `AbstractController` instead of `Controller`,
* [BC break] Service `hwi_oauth.http_client` has been marked private,
* [BC break] Service `hwi_oauth.security.oauth_utils` has been marked private,
* [BC break] Several service class parameters have been removed,
## 0.6.3 (2018-07-31)
* Fixed: Vkontakte profile picture & nickname path,
* Fixed: `Content-Length` header must be a string,
@@ -19,8 +19,7 @@ use HWI\Bundle\OAuthBundle\OAuth\ResourceOwnerInterface;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use HWI\Bundle\OAuthBundle\Security\OAuthUtils;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -39,21 +38,8 @@ use Symfony\Component\Security\Http\SecurityEvents;
/**
* @author Alexander <iam.asm89@gmail.com>
*/
final class ConnectController extends AbstractController
class ConnectController extends Controller
{
/**
* @var OAuthUtils
*/
private $oauthUtils;
/**
* @param OAuthUtils $oauthUtils
*/
public function __construct(OAuthUtils $oauthUtils)
{
$this->oauthUtils = $oauthUtils;
}
/**
* Action that handles the login 'form'. If connecting is enabled the
* user will be redirected to the appropriate login urls or registration forms.
@@ -81,7 +67,7 @@ final class ConnectController extends AbstractController
$session->set('_hwi_oauth.registration_error.'.$key, $error);
return $this->redirectToRoute('hwi_oauth_connect_registration', ['key' => $key]);
return $this->redirectToRoute('hwi_oauth_connect_registration', array('key' => $key));
}
if ($error) {
@@ -92,9 +78,9 @@ final class ConnectController extends AbstractController
}
}
return $this->render('@HWIOAuth/Connect/login.html.twig', [
return $this->render('@HWIOAuth/Connect/login.html.twig', array(
'error' => $error,
]);
));
}
/**
@@ -141,7 +127,12 @@ final class ConnectController extends AbstractController
/* @var $form FormInterface */
if ($this->container->getParameter('hwi_oauth.fosub_enabled')) {
$form = $this->container->get('hwi_oauth.registration.form.factory')->createForm();
// enable compatibility with FOSUserBundle 1.3.x and 2.x
if (interface_exists('FOS\UserBundle\Form\Factory\FactoryInterface')) {
$form = $this->container->get('hwi_oauth.registration.form.factory')->createForm();
} else {
$form = $this->container->get('hwi_oauth.registration.form');
}
} else {
$form = $this->container->get('hwi_oauth.registration.form');
}
@@ -160,9 +151,9 @@ final class ConnectController extends AbstractController
if ($targetPath = $this->getTargetPath($session)) {
$response = $this->redirect($targetPath);
} else {
$response = $this->render('@HWIOAuth/Connect/registration_success.html.twig', [
$response = $this->render('@HWIOAuth/Connect/registration_success.html.twig', array(
'userInformation' => $userInformation,
]);
));
}
}
@@ -182,11 +173,11 @@ final class ConnectController extends AbstractController
return $response;
}
return $this->render('@HWIOAuth/Connect/registration.html.twig', [
return $this->render('@HWIOAuth/Connect/registration.html.twig', array(
'key' => $key,
'form' => $form->createView(),
'userInformation' => $userInformation,
]);
));
}
/**
@@ -227,7 +218,7 @@ final class ConnectController extends AbstractController
if ($resourceOwner->handles($request)) {
$accessToken = $resourceOwner->getAccessToken(
$request,
$this->oauthUtils->getServiceAuthUrl($request, $resourceOwner)
$this->container->get('hwi_oauth.security.oauth_utils')->getServiceAuthUrl($request, $resourceOwner)
);
// save in session
@@ -250,9 +241,11 @@ final class ConnectController extends AbstractController
return $this->getConfirmationResponse($request, $accessToken, $service);
}
// Symfony <3.0 BC
/** @var $form FormInterface */
$form = $this->createForm(FormType::class);
$form = method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? $this->createForm(FormType::class)
: $this->createForm('form');
// Handle the form
$form->handleRequest($request);
@@ -267,12 +260,12 @@ final class ConnectController extends AbstractController
return $response;
}
return $this->render('@HWIOAuth/Connect/connect_confirm.html.twig', [
return $this->render('@HWIOAuth/Connect/connect_confirm.html.twig', array(
'key' => $key,
'service' => $service,
'form' => $form->createView(),
'userInformation' => $resourceOwner->getUserInformation($accessToken),
]);
));
}
/**
@@ -286,7 +279,7 @@ final class ConnectController extends AbstractController
public function redirectToServiceAction(Request $request, $service)
{
try {
$authorizationUrl = $this->oauthUtils->getAuthorizationUrl($request, $service);
$authorizationUrl = $this->container->get('hwi_oauth.security.oauth_utils')->getAuthorizationUrl($request, $service);
} catch (\RuntimeException $e) {
throw new NotFoundHttpException($e->getMessage(), $e);
}
@@ -374,6 +367,24 @@ final class ConnectController extends AbstractController
throw new NotFoundHttpException(sprintf("No resource owner with name '%s'.", $name));
}
/**
* Generates a route.
*
* @deprecated since version 0.4. Will be removed in 1.0.
*
* @param string $route Route name
* @param array $params Route parameters
* @param bool $absolute absolute url or note
*
* @return string
*/
protected function generate($route, array $params = array(), $absolute = false)
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 0.4 and will be removed in 1.0. Use Symfony\Bundle\FrameworkBundle\Controller\Controller::generateUrl instead.', E_USER_DEPRECATED);
return $this->container->get('router')->generate($route, $params, $absolute);
}
/**
* Authenticate a user with Symfony Security.
*
@@ -455,7 +466,7 @@ final class ConnectController extends AbstractController
if ($currentToken instanceof OAuthToken) {
// Update user token with new details
$newToken =
\is_array($accessToken) &&
is_array($accessToken) &&
(isset($accessToken['access_token']) || isset($accessToken['oauth_token'])) ?
$accessToken : $currentToken->getRawToken();
@@ -466,10 +477,10 @@ final class ConnectController extends AbstractController
if ($targetPath = $this->getTargetPath($request->getSession())) {
$response = $this->redirect($targetPath);
} else {
$response = $this->render('@HWIOAuth/Connect/connect_success.html.twig', [
$response = $this->render('@HWIOAuth/Connect/connect_success.html.twig', array(
'userInformation' => $userInformation,
'service' => $service,
]);
));
}
}
@@ -19,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*
* @author Tomas Pecserke <tomas.pecserke@gmail.com>
*/
final class SetResourceOwnerServiceNameCompilerPass implements CompilerPassInterface
class SetResourceOwnerServiceNameCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
@@ -33,7 +33,7 @@ final class SetResourceOwnerServiceNameCompilerPass implements CompilerPassInter
$aliasIdParts = explode('.', $alias);
$resourceOwnerDefinition = $container->findDefinition($alias);
$resourceOwnerDefinition->addMethodCall('setName', [end($aliasIdParts)]);
$resourceOwnerDefinition->addMethodCall('setName', array(end($aliasIdParts)));
}
}
}
@@ -20,7 +20,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
*
* @author Alexander <iam.asm89@gmail.com>
*/
final class Configuration implements ConfigurationInterface
class Configuration implements ConfigurationInterface
{
/**
* Array of supported resource owners, indentation is intentional to easily notice
@@ -28,8 +28,8 @@ final class Configuration implements ConfigurationInterface
*
* @var array
*/
private static $resourceOwners = [
'oauth2' => [
private static $resourceOwners = array(
'oauth2' => array(
'amazon',
'asana',
'auth0',
@@ -48,7 +48,6 @@ final class Configuration implements ConfigurationInterface
'facebook',
'fiware',
'foursquare',
'genius',
'github',
'gitlab',
'google',
@@ -82,8 +81,8 @@ final class Configuration implements ConfigurationInterface
'yandex',
'37signals',
'itembase',
],
'oauth1' => [
),
'oauth1' => array(
'bitbucket',
'discogs',
'dropbox',
@@ -94,8 +93,8 @@ final class Configuration implements ConfigurationInterface
'twitter',
'xing',
'yahoo',
],
];
),
);
/**
* Return the type (OAuth1 or OAuth2) of given resource owner.
@@ -111,7 +110,7 @@ final class Configuration implements ConfigurationInterface
return $resourceOwner;
}
if (\in_array($resourceOwner, static::$resourceOwners['oauth1'], true)) {
if (in_array($resourceOwner, static::$resourceOwners['oauth1'], true)) {
return 'oauth1';
}
@@ -132,11 +131,11 @@ final class Configuration implements ConfigurationInterface
return true;
}
if (\in_array($resourceOwner, static::$resourceOwners['oauth1'], true)) {
if (in_array($resourceOwner, static::$resourceOwners['oauth1'], true)) {
return true;
}
return \in_array($resourceOwner, static::$resourceOwners['oauth2'], true);
return in_array($resourceOwner, static::$resourceOwners['oauth2'], true);
}
/**
@@ -146,15 +145,9 @@ final class Configuration implements ConfigurationInterface
*/
public function getConfigTreeBuilder()
{
$builder = new TreeBuilder('hwi_oauth');
if (method_exists($builder, 'getRootNode')) {
$rootNode = $builder->getRootNode();
} else {
// BC layer for symfony/config 4.1 and older
$rootNode = $builder->root('hwi_oauth');
}
$builder = new TreeBuilder();
$rootNode = $builder->root('hwi_oauth');
$rootNode
->fixXmlConfig('firewall_name')
->children()
@@ -284,7 +277,7 @@ final class Configuration implements ConfigurationInterface
->scalarNode('type')
->validate()
->ifTrue(function ($type) {
return !self::isResourceOwnerSupported($type);
return !Configuration::isResourceOwnerSupported($type);
})
->thenInvalid('Unknown resource owner type "%s".')
->end()
@@ -304,11 +297,11 @@ final class Configuration implements ConfigurationInterface
return true;
}
if (\is_array($v)) {
return 0 === \count($v);
if (is_array($v)) {
return 0 === count($v);
}
if (\is_string($v)) {
if (is_string($v)) {
return empty($v);
}
@@ -331,7 +324,7 @@ final class Configuration implements ConfigurationInterface
}
// for each type at least these have to be set
foreach (['type', 'client_id', 'client_secret'] as $child) {
foreach (array('type', 'client_id', 'client_secret') as $child) {
if (!isset($c[$child])) {
return true;
}
@@ -353,7 +346,7 @@ final class Configuration implements ConfigurationInterface
return false;
}
$children = ['authorization_url', 'access_token_url', 'request_token_url', 'infos_url'];
$children = array('authorization_url', 'access_token_url', 'request_token_url', 'infos_url');
foreach ($children as $child) {
// This option exists only for OAuth1.0a
if ('request_token_url' === $child && 'oauth2' === $c['type']) {
@@ -382,11 +375,11 @@ final class Configuration implements ConfigurationInterface
}
// one of this two options must be set
if (0 === \count($c['paths'])) {
if (0 === count($c['paths'])) {
return !isset($c['user_response_class']);
}
foreach (['identifier', 'nickname', 'realname'] as $child) {
foreach (array('identifier', 'nickname', 'realname') as $child) {
if (!isset($c['paths'][$child])) {
return true;
}
@@ -400,7 +393,7 @@ final class Configuration implements ConfigurationInterface
->ifTrue(function ($c) {
if (isset($c['service'])) {
// ignore paths & options if none were set
return 0 !== \count($c['paths']) || 0 !== \count($c['options']) || 3 < \count($c);
return 0 !== count($c['paths']) || 0 !== count($c['options']) || 3 < count($c);
}
return false;
@@ -28,7 +28,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension;
* @author Alexander <iam.asm89@gmail.com>
* @author Joseph Bielawski <stloyd@gmail.com>
*/
final class HWIOAuthExtension extends Extension
class HWIOAuthExtension extends Extension
{
/**
* {@inheritdoc}
@@ -76,7 +76,7 @@ final class HWIOAuthExtension extends Extension
$container->setParameter('hwi_oauth.grant_rule', $config['grant_rule']);
// setup services for all configured resource owners
$resourceOwners = [];
$resourceOwners = array();
foreach ($config['resource_owners'] as $name => $options) {
$resourceOwners[$name] = $name;
$this->createResourceOwnerService($container, $name, $options);
@@ -85,7 +85,7 @@ final class HWIOAuthExtension extends Extension
$oauthUtils = $container->getDefinition('hwi_oauth.security.oauth_utils');
foreach ($config['firewall_names'] as $firewallName) {
$oauthUtils->addMethodCall('addResourceOwnerMap', [new Reference('hwi_oauth.resource_ownermap.'.$firewallName)]);
$oauthUtils->addMethodCall('addResourceOwnerMap', array(new Reference('hwi_oauth.resource_ownermap.'.$firewallName)));
}
$this->createConnectIntegration($container, $config);
@@ -148,31 +148,6 @@ final class HWIOAuthExtension extends Extension
return 'hwi_oauth';
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
protected function createHttplugClient(ContainerBuilder $container, array $config)
{
$httpClientId = $config['http']['client'];
$httpMessageFactoryId = $config['http']['message_factory'];
$bundles = $container->getParameter('kernel.bundles');
if ('httplug.client.default' === $httpClientId && !isset($bundles['HttplugBundle'])) {
throw new InvalidConfigurationException(
'You must setup php-http/httplug-bundle to use the default http client service.'
);
}
if ('httplug.message_factory.default' === $httpMessageFactoryId && !isset($bundles['HttplugBundle'])) {
throw new InvalidConfigurationException(
'You must setup php-http/httplug-bundle to use the default http message factory service.'
);
}
$container->setAlias('hwi_oauth.http.client', new Alias($config['http']['client'], true));
$container->setAlias('hwi_oauth.http.message_factory', new Alias($config['http']['message_factory'], true));
}
/**
* Check of the connect controllers etc should be enabled.
*
@@ -202,7 +177,16 @@ final class HWIOAuthExtension extends Extension
$definition->addArgument($config['fosub']['username_iterations']);
$container->setAlias('hwi_oauth.registration.form.handler', new Alias('hwi_oauth.registration.form.handler.fosub_bridge', true));
$container->setAlias('hwi_oauth.registration.form.factory', new Alias('fos_user.registration.form.factory', true));
// enable compatibility with FOSUserBundle 1.3.x and 2.x
if (interface_exists('FOS\UserBundle\Form\Factory\FactoryInterface')) {
$container->setAlias('hwi_oauth.registration.form.factory', new Alias('fos_user.registration.form.factory', true));
} else {
// FOSUser 1.3 BC. To be removed.
$definition->setScope('request');
$container->setAlias('hwi_oauth.registration.form', new Alias('fos_user.registration.form', true));
}
} else {
$container->setParameter('hwi_oauth.fosub_enabled', false);
}
@@ -222,6 +206,31 @@ final class HWIOAuthExtension extends Extension
}
}
/**
* @param ContainerBuilder $container
* @param array $config
*/
protected function createHttplugClient(ContainerBuilder $container, array $config)
{
$httpClientId = $config['http']['client'];
$httpMessageFactoryId = $config['http']['message_factory'];
$bundles = $container->getParameter('kernel.bundles');
if ('httplug.client.default' === $httpClientId && !isset($bundles['HttplugBundle'])) {
throw new InvalidConfigurationException(
'You must setup php-http/httplug-bundle to use the default http client service.'
);
}
if ('httplug.message_factory.default' === $httpMessageFactoryId && !isset($bundles['HttplugBundle'])) {
throw new InvalidConfigurationException(
'You must setup php-http/httplug-bundle to use the default http message factory service.'
);
}
$container->setAlias('hwi_oauth.http.client', new Alias($config['http']['client'], true));
$container->setAlias('hwi_oauth.http.message_factory', new Alias($config['http']['message_factory'], true));
}
/**
* @return string
*/
@@ -70,7 +70,7 @@ class OAuthFactory extends AbstractFactory
{
$definitionClassname = $this->getDefinitionClassname();
$resourceOwnersMap = [];
$resourceOwnersMap = array();
foreach ($config['resource_owners'] as $name => $checkPath) {
$resourceOwnersMap[$name] = $checkPath;
}
@@ -169,15 +169,15 @@ class OAuthFactory extends AbstractFactory
{
$listenerId = parent::createListener($container, $id, $config, $userProvider);
$checkPaths = [];
$checkPaths = array();
foreach ($config['resource_owners'] as $checkPath) {
$checkPaths[] = $checkPath;
}
$container
->getDefinition($listenerId)
->addMethodCall('setResourceOwnerMap', [$this->getResourceOwnerMapReference($id)])
->addMethodCall('setCheckPaths', [$checkPaths])
->addMethodCall('setResourceOwnerMap', array($this->getResourceOwnerMapReference($id)))
->addMethodCall('setCheckPaths', array($checkPaths))
;
return $listenerId;
@@ -225,7 +225,7 @@ class OAuthFactory extends AbstractFactory
->end()
->validate()
->ifTrue(function ($c) {
return 1 !== \count($c) || !\in_array(key($c), ['fosub', 'oauth', 'orm', 'service'], true);
return 1 !== count($c) || !in_array(key($c), array('fosub', 'oauth', 'orm', 'service'), true);
})
->thenInvalid("You should configure (only) one of: 'fosub', 'oauth', 'orm', 'service'.")
->end()
@@ -244,9 +244,9 @@ class OAuthFactory extends AbstractFactory
->end()
->validate()
->ifTrue(function ($c) {
$checkPaths = [];
$checkPaths = array();
foreach ($c as $checkPath) {
if (\in_array($checkPath, $checkPaths, true)) {
if (in_array($checkPath, $checkPaths, true)) {
return true;
}
@@ -11,6 +11,7 @@
namespace HWI\Bundle\OAuthBundle\Form;
use FOS\UserBundle\Form\Handler\RegistrationFormHandler;
use FOS\UserBundle\Mailer\MailerInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Util\TokenGenerator;
@@ -35,6 +36,11 @@ class FOSUBRegistrationFormHandler implements RegistrationFormHandlerInterface
*/
protected $mailer;
/**
* @var RegistrationFormHandler
*/
protected $registrationFormHandler;
/**
* @var TokenGenerator
*/
@@ -64,6 +70,20 @@ class FOSUBRegistrationFormHandler implements RegistrationFormHandlerInterface
*/
public function process(Request $request, Form $form, UserResponseInterface $userInformation)
{
if (null !== $this->registrationFormHandler) {
$formHandler = $this->reconstructFormHandler($request, $form);
// make FOSUB process the form already
$processed = $formHandler->process();
// if the form is not posted we'll try to set some properties
if (!$request->isMethod('POST')) {
$form->setData($this->setUserInformation($form->getData(), $userInformation));
}
return $processed;
}
$user = $this->userManager->createUser();
$user->setEnabled(true);
@@ -78,6 +98,16 @@ class FOSUBRegistrationFormHandler implements RegistrationFormHandlerInterface
return false;
}
/**
* Set registration form handler.
*
* @param null|RegistrationFormHandler $registrationFormHandler FOSUB registration form handler
*/
public function setFormHandler(RegistrationFormHandler $registrationFormHandler = null)
{
$this->registrationFormHandler = $registrationFormHandler;
}
/**
* Attempts to get a unique username for the user.
*
@@ -97,6 +127,21 @@ class FOSUBRegistrationFormHandler implements RegistrationFormHandlerInterface
return null !== $user ? '' : $testName;
}
/**
* Reconstructs the form handler in order to inject the right form.
*
* @param Request $request Active request
* @param Form $form Form to process
*
* @return RegistrationFormHandler
*/
protected function reconstructFormHandler(Request $request, Form $form)
{
$handlerClass = get_class($this->registrationFormHandler);
return new $handlerClass($form, $request, $this->userManager, $this->mailer, $this->tokenGenerator);
}
/**
* Set user information from form.
*
@@ -19,30 +19,30 @@ final class HWIOAuthEvents
/**
* @Event("HWI\Bundle\OAuthBundle\Event\GetResponseUserEvent")
*/
public const REGISTRATION_INITIALIZE = 'hwi_oauth.registration.initialize';
const REGISTRATION_INITIALIZE = 'hwi_oauth.registration.initialize';
/**
* @Event("HWI\Bundle\OAuthBundle\Event\FormEvent")
*/
public const REGISTRATION_SUCCESS = 'hwi_oauth.registration.success';
const REGISTRATION_SUCCESS = 'hwi_oauth.registration.success';
/**
* @Event("HWI\Bundle\OAuthBundle\Event\GetResponseUserEvent")
*/
public const REGISTRATION_COMPLETED = 'hwi_oauth.registration.completed';
const REGISTRATION_COMPLETED = 'hwi_oauth.registration.completed';
/**
* @Event("HWI\Bundle\OAuthBundle\Event\GetResponseUserEvent")
*/
public const CONNECT_INITIALIZE = 'hwi_oauth.connect.initialize';
const CONNECT_INITIALIZE = 'hwi_oauth.connect.initialize';
/**
* @Event("HWI\Bundle\OAuthBundle\Event\GetResponseUserEvent")
*/
public const CONNECT_CONFIRMED = 'hwi_oauth.connect.confirmed';
const CONNECT_CONFIRMED = 'hwi_oauth.connect.confirmed';
/**
* @Event("HWI\Bundle\OAuthBundle\Event\FilterUserResponseEvent")
*/
public const CONNECT_COMPLETED = 'hwi_oauth.connect.completed';
const CONNECT_COMPLETED = 'hwi_oauth.connect.completed';
}
@@ -59,13 +59,13 @@ class SessionStorage implements RequestDataStorageInterface
public function save(ResourceOwnerInterface $resourceOwner, $value, $type = 'token')
{
if ('token' === $type) {
if (!\is_array($value) || !isset($value['oauth_token'])) {
if (!is_array($value) || !isset($value['oauth_token'])) {
throw new \InvalidArgumentException('Invalid request token.');
}
$key = $this->generateKey($resourceOwner, $value['oauth_token'], 'token');
} else {
$key = $this->generateKey($resourceOwner, \is_array($value) ? reset($value) : $value, $type);
$key = $this->generateKey($resourceOwner, is_array($value) ? reset($value) : $value, $type);
}
$this->session->set($key, $value);
@@ -135,7 +135,7 @@ abstract class AbstractResourceOwner implements ResourceOwnerInterface
*/
public function getOption($name)
{
if (!\array_key_exists($name, $this->options)) {
if (!array_key_exists($name, $this->options)) {
throw new \InvalidArgumentException(sprintf('Unknown option "%s"', $name));
}
@@ -248,10 +248,10 @@ abstract class AbstractResourceOwner implements ResourceOwnerInterface
$method = null === $content || '' === $content ? 'GET' : 'POST';
}
$headers += ['User-Agent' => 'HWIOAuthBundle (https://github.com/hwi/HWIOAuthBundle)'];
if (\is_string($content)) {
$headers += ['Content-Length' => (string) \strlen($content)];
} elseif (\is_array($content)) {
$headers += array('User-Agent' => 'HWIOAuthBundle (https://github.com/hwi/HWIOAuthBundle)');
if (is_string($content)) {
$headers += array('Content-Length' => (string) strlen($content));
} elseif (is_array($content)) {
$content = http_build_query($content, '', '&');
}
@@ -279,7 +279,7 @@ abstract class AbstractResourceOwner implements ResourceOwnerInterface
// First check that content in response exists, due too bug: https://bugs.php.net/bug.php?id=54484
$content = (string) $rawResponse->getBody();
if (!$content) {
return [];
return array();
}
$response = json_decode($content, true);
@@ -23,12 +23,12 @@ class AmazonResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'user_id',
'nickname' => 'name',
'realname' => 'name',
'email' => 'email',
];
);
/**
* {@inheritdoc}
@@ -37,12 +37,12 @@ class AmazonResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://www.amazon.com/ap/oa',
'access_token_url' => 'https://api.amazon.com/auth/o2/token',
'infos_url' => 'https://api.amazon.com/user/profile',
'scope' => 'profile',
]);
));
}
}
@@ -23,12 +23,12 @@ class AsanaResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'data.id',
'nickname' => 'data.name',
'realname' => 'data.name',
'email' => 'data.email',
];
);
/**
* {@inheritdoc}
@@ -37,10 +37,10 @@ class AsanaResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://app.asana.com/-/oauth_authorize',
'access_token_url' => 'https://app.asana.com/-/oauth_token',
'infos_url' => 'https://app.asana.com/api/1.0/users/me',
]);
));
}
}
@@ -24,18 +24,18 @@ class Auth0ResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'user_id',
'nickname' => 'nickname',
'realname' => 'name',
'email' => 'email',
'profilepicture' => 'picture',
];
);
/**
* {@inheritdoc}
*/
protected function doGetTokenRequest($url, array $parameters = [])
protected function doGetTokenRequest($url, array $parameters = array())
{
return $this->httpRequest(
$url,
@@ -48,7 +48,7 @@ class Auth0ResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = [])
protected function doGetUserInformationRequest($url, array $parameters = array())
{
return $this->httpRequest(
$url,
@@ -64,25 +64,25 @@ class Auth0ResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$auth0Client = base64_encode(json_encode([
$auth0Client = base64_encode(json_encode(array(
'name' => 'HWIOAuthBundle',
'version' => 'unknown',
'environment' => [
'environment' => array(
'name' => 'PHP',
'version' => \PHP_VERSION,
],
]));
),
)));
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => '{base_url}/authorize?auth0Client='.$auth0Client,
'access_token_url' => '{base_url}/oauth/token',
'infos_url' => '{base_url}/userinfo',
'auth0_client' => $auth0Client,
]);
));
$resolver->setRequired([
$resolver->setRequired(array(
'base_url',
]);
));
$normalizer = function (Options $options, $value) {
return str_replace('{base_url}', $options['base_url'], $value);
@@ -98,7 +98,7 @@ class Auth0ResourceOwner extends GenericOAuth2ResourceOwner
*
* @return array
*/
private function getRequestHeaders(array $headers = [])
private function getRequestHeaders(array $headers = array())
{
if (isset($this->options['auth0_client'])) {
$headers['Auth0-Client'] = $this->options['auth0_client'];
@@ -23,13 +23,13 @@ class AzureResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'sub',
'nickname' => 'unique_name',
'realname' => ['given_name', 'family_name'],
'email' => ['upn', 'email'],
'realname' => array('given_name', 'family_name'),
'email' => array('upn', 'email'),
'profilepicture' => null,
];
);
/**
* {@inheritdoc}
@@ -43,17 +43,17 @@ class AzureResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
return parent::getAuthorizationUrl($redirectUri, $extraParameters + ['resource' => $this->options['resource']]);
return parent::getAuthorizationUrl($redirectUri, $extraParameters + array('resource' => $this->options['resource']));
}
/**
* {@inheritdoc}
*/
public function refreshAccessToken($refreshToken, array $extraParameters = [])
public function refreshAccessToken($refreshToken, array $extraParameters = array())
{
return parent::refreshAccessToken($refreshToken, $extraParameters + ['resource' => $this->options['resource']]);
return parent::refreshAccessToken($refreshToken, $extraParameters + array('resource' => $this->options['resource']));
}
/**
@@ -61,16 +61,16 @@ class AzureResourceOwner extends GenericOAuth2ResourceOwner
*
* @throws \InvalidArgumentException
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
// from http://stackoverflow.com/a/28748285/624544
list(, $jwt) = explode('.', $accessToken['id_token'], 3);
// if the token was urlencoded, do some fixes to ensure that it is valid base64 encoded
$jwt = str_replace(['-', '_'], ['+', '/'], $jwt);
$jwt = str_replace(array('-', '_'), array('+', '/'), $jwt);
// complete token if needed
switch (\strlen($jwt) % 4) {
switch (strlen($jwt) % 4) {
case 0:
break;
@@ -96,9 +96,9 @@ class AzureResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setRequired(['resource']);
$resolver->setRequired(array('resource'));
$resolver->setDefaults([
$resolver->setDefaults(array(
'infos_url' => 'https://graph.microsoft.com/v1.0/me',
'authorization_url' => 'https://login.windows.net/%s/oauth2/authorize',
'access_token_url' => 'https://login.windows.net/%s/oauth2/token',
@@ -106,6 +106,6 @@ class AzureResourceOwner extends GenericOAuth2ResourceOwner
'application' => 'common',
'api_version' => 'v1.0',
'csrf' => true,
]);
));
}
}
@@ -23,25 +23,25 @@ class Bitbucket2ResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'uuid',
'nickname' => 'username',
'email' => 'email',
'realname' => 'display_name',
'profilepicture' => 'links.avatar.href',
];
);
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
$response = parent::getUserInformation($accessToken, $extraParameters);
$responseData = $response->getData();
// fetch the email addresses linked to the account
if (empty($responseData['email'])) {
$content = $this->httpRequest($this->normalizeUrl($this->options['emails_url']), null, ['Authorization' => 'Bearer '.$accessToken['access_token']]);
$content = $this->httpRequest($this->normalizeUrl($this->options['emails_url']), null, array('Authorization' => 'Bearer '.$accessToken['access_token']));
foreach ($this->getResponseContent($content)['values'] as $email) {
// we only need the primary email address
if (true === $email['is_primary']) {
@@ -62,11 +62,11 @@ class Bitbucket2ResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://bitbucket.org/site/oauth2/authorize',
'access_token_url' => 'https://bitbucket.org/site/oauth2/access_token',
'infos_url' => 'https://api.bitbucket.org/2.0/user',
'emails_url' => 'https://api.bitbucket.org/2.0/user/emails',
]);
));
}
}
@@ -23,12 +23,12 @@ class BitbucketResourceOwner extends GenericOAuth1ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'user.username',
'nickname' => 'user.username',
'realname' => 'user.display_name',
'profilepicture' => 'user.avatar',
];
);
/**
* {@inheritdoc}
@@ -37,11 +37,11 @@ class BitbucketResourceOwner extends GenericOAuth1ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://bitbucket.org/api/1.0/oauth/authenticate',
'request_token_url' => 'https://bitbucket.org/api/1.0/oauth/request_token',
'access_token_url' => 'https://bitbucket.org/api/1.0/oauth/access_token',
'infos_url' => 'https://bitbucket.org/api/1.0/user',
]);
));
}
}
@@ -23,12 +23,12 @@ class BitlyResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'data.login',
'nickname' => 'data.display_name',
'realname' => 'data.full_name',
'profilepicture' => 'data.profile_image',
];
);
/**
* {@inheritdoc}
@@ -37,11 +37,11 @@ class BitlyResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'use_bearer_authorization' => false,
'authorization_url' => 'https://bitly.com/oauth/authorize',
'access_token_url' => 'https://api-ssl.bitly.com/oauth/access_token',
'infos_url' => 'https://api-ssl.bitly.com/v3/user/info?format=json',
]);
));
}
}
@@ -23,26 +23,26 @@ class BoxResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'name',
'realname' => 'name',
'email' => 'login',
'profilepicture' => 'avatar_url',
];
);
/**
* {@inheritdoc}
*/
public function revokeToken($token)
{
$parameters = [
$parameters = array(
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
'token' => $token,
];
);
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url']), $parameters, [], 'POST');
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url']), $parameters, array(), 'POST');
return 200 === $response->getStatusCode();
}
@@ -54,11 +54,11 @@ class BoxResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://www.box.com/api/oauth2/authorize',
'access_token_url' => 'https://www.box.com/api/oauth2/token',
'revoke_token_url' => 'https://www.box.com/api/oauth2/revoke',
'infos_url' => 'https://api.box.com/2.0/users/me',
]);
));
}
}
@@ -23,11 +23,11 @@ class BufferAppResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'id',
'realname' => 'id',
];
);
/**
* {@inheritdoc}
@@ -36,10 +36,10 @@ class BufferAppResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://bufferapp.com/oauth2/authorize',
'access_token_url' => 'https://api.bufferapp.com/1/oauth2/token.json',
'infos_url' => 'https://api.bufferapp.com/1/user.json',
]);
));
}
}
@@ -23,17 +23,17 @@ class CleverResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'data.id',
'email' => 'data.email',
'firstname' => 'data.name.first',
'lastname' => 'data.name.last',
'realname' => [
'realname' => array(
'data.name.first',
'data.name.middle',
'data.name.last',
],
];
),
);
/**
* {@inheritdoc}
@@ -42,17 +42,17 @@ class CleverResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://clever.com/oauth/authorize',
'access_token_url' => 'https://clever.com/oauth/tokens',
'infos_url' => 'https://api.clever.com/me',
]);
));
}
/**
* {@inheritdoc}
*/
protected function doGetTokenRequest($url, array $parameters = [])
protected function doGetTokenRequest($url, array $parameters = array())
{
$authPreHash = $this->options['client_id'].':'.$this->options['client_secret'];
$authHeader = 'Authorization: Basic '.base64_encode($authPreHash);
@@ -60,9 +60,9 @@ class CleverResourceOwner extends GenericOAuth2ResourceOwner
return $this->httpRequest(
$url,
http_build_query($parameters, '', '&'),
[
array(
$authHeader,
]
)
);
}
}
@@ -23,20 +23,20 @@ class DailymotionResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'screenname',
'realname' => 'fullname', // requires 'userinfo' scope
'email' => 'email', // requires 'email' scope
'profilepicture' => 'avatar_medium_url',
];
);
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
return parent::getAuthorizationUrl($redirectUri, array_merge(['display' => $this->options['display']], $extraParameters));
return parent::getAuthorizationUrl($redirectUri, array_merge(array('display' => $this->options['display']), $extraParameters));
}
/**
@@ -46,15 +46,15 @@ class DailymotionResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://api.dailymotion.com/oauth/authorize',
'access_token_url' => 'https://api.dailymotion.com/oauth/token',
'infos_url' => 'https://api.dailymotion.com/me',
'display' => null,
]);
));
// @link http://www.dailymotion.com/doc/api/authentication.html#dialog-form-factors
$resolver->setAllowedValues('display', ['page', 'popup', 'mobile', null]);
$resolver->setAllowedValues('display', array('page', 'popup', 'mobile', null));
}
}
@@ -21,7 +21,7 @@ class DeezerResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'name',
'realname' => 'firstname',
@@ -30,7 +30,7 @@ class DeezerResourceOwner extends GenericOAuth2ResourceOwner
'lastname' => 'lastname',
'profilepicture' => 'picture',
'gender' => 'gender',
];
);
/**
* {@inheritdoc}
@@ -39,11 +39,11 @@ class DeezerResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://connect.deezer.com/oauth/auth.php',
'access_token_url' => 'https://connect.deezer.com/oauth/access_token.php',
'infos_url' => 'https://api.deezer.com/user/me',
'use_bearer_authorization' => false,
]);
));
}
}
@@ -23,11 +23,11 @@ class DeviantartResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'username',
'nickname' => 'username',
'profilepicture' => 'usericonurl',
];
);
/**
* {@inheritdoc}
@@ -36,10 +36,10 @@ class DeviantartResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://www.deviantart.com/oauth2/draft15/authorize',
'access_token_url' => 'https://www.deviantart.com/oauth2/draft15/token',
'infos_url' => 'https://www.deviantart.com/api/draft15/user/whoami',
]);
));
}
}
@@ -18,10 +18,10 @@ class DiscogsResourceOwner extends GenericOAuth1ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'username',
];
);
/**
* {@inheritdoc}
@@ -30,11 +30,11 @@ class DiscogsResourceOwner extends GenericOAuth1ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://www.discogs.com/oauth/authorize',
'request_token_url' => 'https://api.discogs.com/oauth/request_token',
'access_token_url' => 'https://api.discogs.com/oauth/access_token',
'infos_url' => 'https://api.discogs.com/oauth/identity',
]);
));
}
}
@@ -23,22 +23,22 @@ class DisqusResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'response.id',
'nickname' => 'response.username',
'realname' => 'response.name',
];
);
/**
* {@inheritdoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = [])
protected function doGetUserInformationRequest($url, array $parameters = array())
{
// Disqus requires api key and secret for user information requests
$url = $this->normalizeUrl($url, [
$url = $this->normalizeUrl($url, array(
'api_key' => $this->options['client_id'],
'api_secret' => $this->options['client_secret'],
]);
));
return parent::doGetUserInformationRequest($url, $parameters);
}
@@ -50,7 +50,7 @@ class DisqusResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://disqus.com/api/oauth/2.0/authorize/',
'access_token_url' => 'https://disqus.com/api/oauth/2.0/access_token/',
'infos_url' => 'https://disqus.com/api/3.0/users/details.json',
@@ -58,6 +58,6 @@ class DisqusResourceOwner extends GenericOAuth2ResourceOwner
'scope' => 'read',
'use_commas_in_scope' => true,
]);
));
}
}
@@ -11,8 +11,8 @@
namespace HWI\Bundle\OAuthBundle\OAuth\ResourceOwner;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -26,12 +26,26 @@ class DropboxResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'account_id',
'nickname' => 'email',
'realname' => 'email',
'email' => 'email',
];
);
/**
* {@inheritdoc}
*/
protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
'authorization_url' => 'https://www.dropbox.com/oauth2/authorize',
'access_token_url' => 'https://api.dropbox.com/oauth2/token',
'infos_url' => 'https://api.dropboxapi.com/2/users/get_current_account',
));
}
/**
* Dropbox API v2 requires a POST request to simply get user info!
@@ -42,23 +56,23 @@ class DropboxResourceOwner extends GenericOAuth2ResourceOwner
* @return UserResponseInterface
*/
public function getUserInformation(array $accessToken,
array $extraParameters = []
array $extraParameters = array()
) {
if ($this->options['use_bearer_authorization']) {
$content = $this->httpRequest(
$this->normalizeUrl($this->options['infos_url'],
$extraParameters),
'null',
[
array(
'Authorization' => 'Bearer'.' '.$accessToken['access_token'],
'Accept' => 'application/json',
'Content-Type' => 'application/json; charset=utf-8',
], 'POST');
), 'POST');
} else {
$content = $this->doGetUserInformationRequest(
$this->normalizeUrl(
$this->options['infos_url'],
array_merge([$this->options['attr_name'] => $accessToken['access_token']],
array_merge(array($this->options['attr_name'] => $accessToken['access_token']),
$extraParameters)
)
);
@@ -71,18 +85,4 @@ class DropboxResourceOwner extends GenericOAuth2ResourceOwner
return $response;
}
/**
* {@inheritdoc}
*/
protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'authorization_url' => 'https://www.dropbox.com/oauth2/authorize',
'access_token_url' => 'https://api.dropbox.com/oauth2/token',
'infos_url' => 'https://api.dropboxapi.com/2/users/get_current_account',
]);
}
}
@@ -23,11 +23,11 @@ class EveOnlineResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'CharacterID',
'nickname' => 'CharacterName',
'realname' => 'CharacterName',
];
);
/**
* {@inheritdoc}
@@ -36,11 +36,11 @@ class EveOnlineResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://login.eveonline.com/oauth/authorize',
'access_token_url' => 'https://login.eveonline.com/oauth/token',
'infos_url' => 'https://login.eveonline.com/oauth/verify',
'use_commas_in_scope' => true,
]);
));
}
}
@@ -23,21 +23,21 @@ class EventbriteResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'user.user_id',
'nickname' => 'user.first_name',
'firstname' => 'user.first_name',
'lastname' => 'user.last_name',
'realname' => ['user.first_name', 'user.last_name'],
'realname' => array('user.first_name', 'user.last_name'),
'email' => 'email',
];
);
/**
* {@inheritdoc}
*/
protected function doGetTokenRequest($url, array $parameters = [])
protected function doGetTokenRequest($url, array $parameters = array())
{
return $this->httpRequest($url, http_build_query($parameters, '', '&'), [], 'POST');
return $this->httpRequest($url, http_build_query($parameters, '', '&'), array(), 'POST');
}
/**
@@ -47,12 +47,12 @@ class EventbriteResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://www.eventbrite.com/oauth/authorize',
'access_token_url' => 'https://www.eventbrite.com/oauth/token',
'infos_url' => 'https://www.eventbrite.com/json/user_get',
'use_bearer_authorization' => true,
]);
));
}
}
@@ -24,7 +24,7 @@ class FacebookResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'name',
'firstname' => 'first_name',
@@ -32,12 +32,12 @@ class FacebookResourceOwner extends GenericOAuth2ResourceOwner
'realname' => 'name',
'email' => 'email',
'profilepicture' => 'picture.data.url',
];
);
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
if ($this->options['appsecret_proof']) {
$extraParameters['appsecret_proof'] = hash_hmac('sha256', $accessToken['access_token'], $this->options['client_secret']);
@@ -49,9 +49,9 @@ class FacebookResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
$extraOptions = [];
$extraOptions = array();
if (isset($this->options['display'])) {
$extraOptions['display'] = $this->options['display'];
}
@@ -66,9 +66,9 @@ class FacebookResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
public function getAccessToken(Request $request, $redirectUri, array $extraParameters = [])
public function getAccessToken(Request $request, $redirectUri, array $extraParameters = array())
{
$parameters = [];
$parameters = array();
if ($request->query->has('fb_source')) {
$parameters['fb_source'] = $request->query->get('fb_source');
}
@@ -85,12 +85,12 @@ class FacebookResourceOwner extends GenericOAuth2ResourceOwner
*/
public function revokeToken($token)
{
$parameters = [
$parameters = array(
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
];
);
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url'], ['access_token' => $token]), $parameters, [], 'DELETE');
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url'], array('access_token' => $token)), $parameters, array(), 'DELETE');
return 200 === $response->getStatusCode();
}
@@ -102,20 +102,20 @@ class FacebookResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'authorization_url' => 'https://www.facebook.com/v3.1/dialog/oauth',
'access_token_url' => 'https://graph.facebook.com/v3.1/oauth/access_token',
'revoke_token_url' => 'https://graph.facebook.com/v3.1/me/permissions',
'infos_url' => 'https://graph.facebook.com/v3.1/me?fields=id,first_name,last_name,name,email,picture.type(large)',
$resolver->setDefaults(array(
'authorization_url' => 'https://www.facebook.com/v2.8/dialog/oauth',
'access_token_url' => 'https://graph.facebook.com/v2.8/oauth/access_token',
'revoke_token_url' => 'https://graph.facebook.com/v2.8/me/permissions',
'infos_url' => 'https://graph.facebook.com/v2.8/me?fields=id,first_name,last_name,name,email,picture.type(large)',
'use_commas_in_scope' => true,
'display' => null,
'auth_type' => null,
'appsecret_proof' => false,
]);
));
$resolver
->setAllowedValues('display', ['page', 'popup', 'touch', null]) // @link https://developers.facebook.com/docs/reference/dialogs/#display
->setAllowedValues('auth_type', ['rerequest', null]) // @link https://developers.facebook.com/docs/reference/javascript/FB.login/
->setAllowedValues('display', array('page', 'popup', 'touch', null)) // @link https://developers.facebook.com/docs/reference/dialogs/#display
->setAllowedValues('auth_type', array('rerequest', null)) // @link https://developers.facebook.com/docs/reference/javascript/FB.login/
->setAllowedTypes('appsecret_proof', 'bool') // @link https://developers.facebook.com/docs/graph-api/securing-requests
;
}
@@ -30,27 +30,27 @@ class FiwareResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'nickName',
'realname' => 'displayName',
'email' => 'email',
];
);
/**
* {@inheritdoc}
*/
public function getAccessToken(Request $request, $redirectUri, array $extraParameters = [])
public function getAccessToken(Request $request, $redirectUri, array $extraParameters = array())
{
$parameters = array_merge([
$parameters = array_merge(array(
'code' => $request->query->get('code'),
'grant_type' => 'authorization_code',
'redirect_uri' => $redirectUri,
], $extraParameters);
), $extraParameters);
$headers = [
$headers = array(
'Authorization' => 'Basic '.base64_encode($this->options['client_id'].':'.$this->options['client_secret']),
];
);
$response = $this->httpRequest($this->options['access_token_url'], http_build_query($parameters, '', '&'), $headers, 'POST');
$responseContent = $this->getResponseContent($response);
@@ -63,22 +63,22 @@ class FiwareResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
if ($this->options['use_bearer_authorization']) {
$content = $this->httpRequest(
$this->normalizeUrl(
$this->options['infos_url'],
['access_token' => $accessToken['access_token']]
array('access_token' => $accessToken['access_token'])
),
null,
['Authorization' => 'Bearer']
array('Authorization' => 'Bearer')
);
} else {
$content = $this->doGetUserInformationRequest(
$this->normalizeUrl(
$this->options['infos_url'],
[$this->options['attr_name'] => $accessToken['access_token']]
array($this->options['attr_name'] => $accessToken['access_token'])
)
);
}
@@ -98,16 +98,16 @@ class FiwareResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => '{base_url}/oauth2/authorize',
'access_token_url' => '{base_url}/oauth2/token',
'revoke_token_url' => '{base_url}/oauth2/revoke',
'infos_url' => '{base_url}/user',
]);
));
$resolver->setRequired([
$resolver->setRequired(array(
'base_url',
]);
));
$normalizer = function (Options $options, $value) {
return str_replace('{base_url}', $options['base_url'], $value);
@@ -24,30 +24,30 @@ class FlickrResourceOwner extends GenericOAuth1ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'user_nsid',
'nickname' => 'username',
'realname' => 'fullname',
];
);
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
$token = $this->getRequestToken($redirectUri, $extraParameters);
return $this->normalizeUrl($this->options['authorization_url'], [
return $this->normalizeUrl($this->options['authorization_url'], array(
'oauth_token' => $token['oauth_token'],
'perms' => $this->options['perms'],
'nojsoncallback' => 1,
]);
));
}
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
$response = $this->getUserResponse();
$response->setData($accessToken);
@@ -64,7 +64,7 @@ class FlickrResourceOwner extends GenericOAuth1ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'http://www.flickr.com/services/oauth/authorize',
'request_token_url' => 'http://www.flickr.com/services/oauth/request_token',
'access_token_url' => 'http://www.flickr.com/services/oauth/access_token',
@@ -73,6 +73,6 @@ class FlickrResourceOwner extends GenericOAuth1ResourceOwner
'infos_url' => null,
'perms' => 'read',
]);
));
}
}
@@ -24,15 +24,15 @@ class FoursquareResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'response.user.id',
'firstname' => 'response.user.firstName',
'lastname' => 'response.user.lastName',
'nickname' => 'response.user.firstName',
'realname' => ['response.user.firstName', 'response.user.lastName'],
'realname' => array('response.user.firstName', 'response.user.lastName'),
'email' => 'response.user.contact.email',
'profilepicture' => 'response.user.photo',
];
);
/**
* {@inheritdoc}
@@ -63,12 +63,12 @@ class FoursquareResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = [])
protected function doGetUserInformationRequest($url, array $parameters = array())
{
// Foursquare require to pass the 'v' ('version' = date in format 'YYYYMMDD') parameter when requesting API
$url = $this->normalizeUrl($url, [
$url = $this->normalizeUrl($url, array(
'v' => $this->options['version'],
]);
));
// Foursquare require to pass the OAuth token as 'oauth_token' instead of 'access_token'
$url = str_replace('access_token', 'oauth_token', $url);
@@ -83,7 +83,7 @@ class FoursquareResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://foursquare.com/oauth2/authenticate',
'access_token_url' => 'https://foursquare.com/oauth2/access_token',
'infos_url' => 'https://api.foursquare.com/v2/users/self',
@@ -92,6 +92,6 @@ class FoursquareResourceOwner extends GenericOAuth2ResourceOwner
'version' => '20121206',
'use_bearer_authorization' => false,
]);
));
}
}
@@ -29,7 +29,7 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
$parameters = array_merge([
'oauth_consumer_key' => $this->options['client_id'],
@@ -63,17 +63,17 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
$token = $this->getRequestToken($redirectUri, $extraParameters);
return $this->normalizeUrl($this->options['authorization_url'], ['oauth_token' => $token['oauth_token']]);
return $this->normalizeUrl($this->options['authorization_url'], array('oauth_token' => $token['oauth_token']));
}
/**
* {@inheritdoc}
*/
public function getAccessToken(HttpRequest $request, $redirectUri, array $extraParameters = [])
public function getAccessToken(HttpRequest $request, $redirectUri, array $extraParameters = array())
{
OAuthErrorHandler::handleOAuthError($request);
@@ -85,7 +85,7 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
throw new AuthenticationException('Given token is not valid.');
}
$parameters = array_merge([
$parameters = array_merge(array(
'oauth_consumer_key' => $this->options['client_id'],
'oauth_timestamp' => time(),
'oauth_nonce' => $this->generateNonce(),
@@ -93,7 +93,7 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
'oauth_signature_method' => $this->options['signature_method'],
'oauth_token' => $requestToken['oauth_token'],
'oauth_verifier' => $request->query->get('oauth_verifier'),
], $extraParameters);
), $extraParameters);
$url = $this->options['access_token_url'];
$parameters['oauth_signature'] = OAuthUtils::signRequest(
@@ -139,7 +139,7 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function getRequestToken($redirectUri, array $extraParameters = [])
public function getRequestToken($redirectUri, array $extraParameters = array())
{
$timestamp = time();
@@ -162,7 +162,7 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
$this->options['signature_method']
);
$apiResponse = $this->httpRequest($url, null, [], 'POST', $parameters);
$apiResponse = $this->httpRequest($url, null, array(), 'POST', $parameters);
$response = $this->getResponseContent($apiResponse);
@@ -188,23 +188,23 @@ class GenericOAuth1ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
protected function doGetTokenRequest($url, array $parameters = [])
protected function doGetTokenRequest($url, array $parameters = array())
{
return $this->httpRequest($url, null, [], 'POST', $parameters);
return $this->httpRequest($url, null, array(), 'POST', $parameters);
}
/**
* {@inheritdoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = [])
protected function doGetUserInformationRequest($url, array $parameters = array())
{
return $this->httpRequest($url, null, [], null, $parameters);
return $this->httpRequest($url, null, array(), null, $parameters);
}
/**
* {@inheritdoc}
*/
protected function httpRequest($url, $content = null, array $headers = [], $method = null, array $parameters = [])
protected function httpRequest($url, $content = null, array $headers = array(), $method = null, array $parameters = array())
{
foreach ($parameters as $key => $value) {
$parameters[$key] = $key.'="'.rawurlencode($value).'"';
@@ -28,19 +28,19 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
if ($this->options['use_bearer_authorization']) {
$content = $this->httpRequest(
$this->normalizeUrl($this->options['infos_url'], $extraParameters),
null,
['Authorization' => 'Bearer '.$accessToken['access_token']]
array('Authorization' => 'Bearer '.$accessToken['access_token'])
);
} else {
$content = $this->doGetUserInformationRequest(
$this->normalizeUrl(
$this->options['infos_url'],
array_merge([$this->options['attr_name'] => $accessToken['access_token']], $extraParameters)
array_merge(array($this->options['attr_name'] => $accessToken['access_token']), $extraParameters)
)
);
}
@@ -56,7 +56,7 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
if ($this->options['csrf']) {
if (null === $this->state) {
@@ -66,13 +66,13 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
$this->storage->save($this, $this->state, 'csrf_state');
}
$parameters = array_merge([
$parameters = array_merge(array(
'response_type' => 'code',
'client_id' => $this->options['client_id'],
'scope' => $this->options['scope'],
'state' => $this->state ? urlencode($this->state) : null,
'redirect_uri' => $redirectUri,
], $extraParameters);
), $extraParameters);
return $this->normalizeUrl($this->options['authorization_url'], $parameters);
}
@@ -80,15 +80,17 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function getAccessToken(HttpRequest $request, $redirectUri, array $extraParameters = [])
public function getAccessToken(HttpRequest $request, $redirectUri, array $extraParameters = array())
{
OAuthErrorHandler::handleOAuthError($request);
$parameters = array_merge([
$parameters = array_merge(array(
'code' => $request->query->get('code'),
'grant_type' => 'authorization_code',
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
'redirect_uri' => $redirectUri,
], $extraParameters);
), $extraParameters);
$response = $this->doGetTokenRequest($this->options['access_token_url'], $parameters);
$response = $this->getResponseContent($response);
@@ -101,12 +103,14 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
public function refreshAccessToken($refreshToken, array $extraParameters = [])
public function refreshAccessToken($refreshToken, array $extraParameters = array())
{
$parameters = array_merge([
$parameters = array_merge(array(
'refresh_token' => $refreshToken,
'grant_type' => 'refresh_token',
], $extraParameters);
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
), $extraParameters);
$response = $this->doGetTokenRequest($this->options['access_token_url'], $parameters);
$response = $this->getResponseContent($response);
@@ -130,7 +134,7 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
'client_secret' => $this->options['client_secret'],
];
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url'], ['token' => $token]), $parameters, [], 'DELETE');
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url'], array('token' => $token)), $parameters, array(), 'DELETE');
return 200 === $response->getStatusCode();
}
@@ -163,28 +167,15 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
/**
* {@inheritdoc}
*/
protected function doGetTokenRequest($url, array $parameters = [])
protected function doGetTokenRequest($url, array $parameters = array())
{
$headers = [];
if ($this->options['use_authorization_to_get_token']) {
if ($this->options['client_secret']) {
$headers['Authorization'] = 'Basic '.base64_encode($this->options['client_id'].':'.$this->options['client_secret']);
}
} else {
$parameters['client_id'] = $this->options['client_id'];
$parameters['client_secret'] = $this->options['client_secret'];
}
$query = http_build_query($parameters, '', '&');
return $this->httpRequest($url, $query, $headers);
return $this->httpRequest($url, http_build_query($parameters, '', '&'));
}
/**
* {@inheritdoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = [])
protected function doGetUserInformationRequest($url, array $parameters = array())
{
return $this->httpRequest($url, http_build_query($parameters, '', '&'));
}
@@ -201,7 +192,7 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
}
if (isset($response['error'])) {
throw new AuthenticationException(sprintf('OAuth error: "%s"', $response['error']['message'] ?? $response['error']));
throw new AuthenticationException(sprintf('OAuth error: "%s"', isset($response['error']['message']) ? $response['error']['message'] : $response['error']));
}
if (!isset($response['access_token'])) {
@@ -220,7 +211,6 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
'attr_name' => 'access_token',
'use_commas_in_scope' => false,
'use_bearer_authorization' => true,
'use_authorization_to_get_token' => true,
]);
$resolver->setDefined('revoke_token_url');
@@ -247,7 +237,7 @@ class GenericOAuth2ResourceOwner extends AbstractResourceOwner
*/
protected function httpRequest($url, $content = null, array $headers = [], $method = null)
{
$headers += ['Content-Type' => 'application/x-www-form-urlencoded'];
$headers += array('Content-Type' => 'application/x-www-form-urlencoded');
return parent::httpRequest($url, $content, $headers, $method);
}
@@ -1,48 +0,0 @@
<?php
/*
* This file is part of the HWIOAuthBundle package.
*
* (c) Hardware.Info <opensource@hardware.info>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace HWI\Bundle\OAuthBundle\OAuth\ResourceOwner;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @author Krystian Marcisz <simivar@gmail.com>
*/
class GeniusResourceOwner extends GenericOAuth2ResourceOwner
{
/**
* {@inheritdoc}
*/
protected $paths = [
'identifier' => 'response.user.id',
'nickname' => 'response.user.name',
'realname' => 'response.user.name',
'email' => 'response.user.email',
'profilepicture' => 'response.user.avatar.medium.url',
];
/**
* {@inheritdoc}
*/
protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'authorization_url' => 'https://api.genius.com/oauth/authorize',
'access_token_url' => 'https://api.genius.com/oauth/token',
'infos_url' => 'https://api.genius.com/account',
'use_bearer_authorization' => true,
'use_commas_in_scope' => true,
'scope' => 'me',
]);
}
}
@@ -24,18 +24,18 @@ class GitHubResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'login',
'realname' => 'name',
'email' => 'email',
'profilepicture' => 'avatar_url',
];
);
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
$response = parent::getUserInformation($accessToken, $extraParameters);
@@ -43,7 +43,7 @@ class GitHubResourceOwner extends GenericOAuth2ResourceOwner
if (empty($responseData['email'])) {
// fetch the email addresses linked to the account
$content = $this->httpRequest(
$this->normalizeUrl($this->options['emails_url']), null, ['Authorization' => 'Bearer '.$accessToken['access_token']]
$this->normalizeUrl($this->options['emails_url']), null, array('Authorization' => 'Bearer '.$accessToken['access_token'])
);
foreach ($this->getResponseContent($content) as $email) {
@@ -68,7 +68,7 @@ class GitHubResourceOwner extends GenericOAuth2ResourceOwner
$response = $this->httpRequest(
sprintf($this->options['revoke_token_url'], $this->options['client_id'], $token),
null,
['Authorization' => 'Basic '.base64_encode($this->options['client_id'].':'.$this->options['client_secret'])],
array('Authorization' => 'Basic '.base64_encode($this->options['client_id'].':'.$this->options['client_secret'])),
'DELETE'
);
@@ -82,7 +82,7 @@ class GitHubResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://github.com/login/oauth/authorize',
'access_token_url' => 'https://github.com/login/oauth/access_token',
'revoke_token_url' => 'https://api.github.com/applications/%s/tokens/%s',
@@ -90,6 +90,6 @@ class GitHubResourceOwner extends GenericOAuth2ResourceOwner
'emails_url' => 'https://api.github.com/user/emails',
'use_commas_in_scope' => true,
]);
));
}
}
@@ -23,34 +23,13 @@ class GitLabResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'username',
'realname' => 'name',
'email' => 'email',
'profilepicture' => 'avatar_url',
];
/**
* {@inheritdoc}
*/
public function revokeToken($token)
{
$parameters = [
'token' => $token,
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
];
$response = $this->httpRequest(
$this->options['revoke_token_url'],
$parameters,
[],
'POST'
);
return 200 === $response->getStatusCode();
}
);
/**
* {@inheritdoc}
@@ -59,7 +38,7 @@ class GitLabResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://gitlab.com/oauth/authorize',
'access_token_url' => 'https://gitlab.com/oauth/token',
'revoke_token_url' => 'https://gitlab.com/oauth/revoke',
@@ -68,6 +47,27 @@ class GitLabResourceOwner extends GenericOAuth2ResourceOwner
'scope' => 'read_user',
'use_commas_in_scope' => false,
'use_bearer_authorization' => true,
]);
));
}
/**
* {@inheritdoc}
*/
public function revokeToken($token)
{
$parameters = array(
'token' => $token,
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
);
$response = $this->httpRequest(
$this->options['revoke_token_url'],
$parameters,
array(),
'POST'
);
return 200 === $response->getStatusCode();
}
}
@@ -24,7 +24,7 @@ class GoogleResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'id',
'nickname' => 'name',
'realname' => 'name',
@@ -32,19 +32,19 @@ class GoogleResourceOwner extends GenericOAuth2ResourceOwner
'lastname' => 'family_name',
'email' => 'email',
'profilepicture' => 'picture',
];
);
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
public function getAuthorizationUrl($redirectUri, array $extraParameters = array())
{
$url = parent::getAuthorizationUrl($redirectUri, array_merge([
$url = parent::getAuthorizationUrl($redirectUri, array_merge(array(
'access_type' => $this->options['access_type'],
'approval_prompt' => $this->options['approval_prompt'],
'request_visible_actions' => $this->options['request_visible_actions'],
'prompt' => $this->options['prompt'],
], $extraParameters));
), $extraParameters));
// This parameter have specific value (uses "&" as a separator of domains)
if (null !== $this->options['hd']) {
@@ -59,7 +59,7 @@ class GoogleResourceOwner extends GenericOAuth2ResourceOwner
*/
public function revokeToken($token)
{
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url'], ['token' => $token]));
$response = $this->httpRequest($this->normalizeUrl($this->options['revoke_token_url'], array('token' => $token)));
return 200 === $response->getStatusCode();
}
@@ -71,7 +71,7 @@ class GoogleResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://accounts.google.com/o/oauth2/auth',
'access_token_url' => 'https://accounts.google.com/o/oauth2/token',
'revoke_token_url' => 'https://accounts.google.com/o/oauth2/revoke',
@@ -87,17 +87,17 @@ class GoogleResourceOwner extends GenericOAuth2ResourceOwner
'login_hint' => null,
'prompt' => null,
'request_visible_actions' => null,
]);
));
$resolver
// @link https://developers.google.com/accounts/docs/OAuth2WebServer#offline
->setAllowedValues('access_type', ['online', 'offline', null])
->setAllowedValues('access_type', array('online', 'offline', null))
// sometimes we need to force for approval prompt (e.g. when we lost refresh token)
->setAllowedValues('approval_prompt', ['force', 'auto', null])
->setAllowedValues('approval_prompt', array('force', 'auto', null))
// @link https://developers.google.com/accounts/docs/OAuth2Login#authenticationuriparameters
->setAllowedValues('display', ['page', 'popup', 'touch', 'wap', null])
->setAllowedValues('login_hint', ['email address', 'sub', null])
->setAllowedValues('prompt', ['consent', 'select_account', null])
->setAllowedValues('display', array('page', 'popup', 'touch', 'wap', null))
->setAllowedValues('login_hint', array('email address', 'sub', null))
->setAllowedValues('prompt', array('consent', 'select_account', null))
;
}
}
@@ -23,14 +23,14 @@ class HubicResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'email',
'nickname' => 'email',
'firstname' => 'firstname',
'lastname' => 'lastname',
'realname' => 'firstname',
'email' => 'email',
];
);
/**
* {@inheritdoc}
@@ -39,10 +39,10 @@ class HubicResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://api.hubic.com/oauth/auth/',
'access_token_url' => 'https://api.hubic.com/oauth/token/',
'infos_url' => 'https://api.hubic.com/1.0/account',
]);
));
}
}
@@ -23,19 +23,19 @@ class InstagramResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'data.id',
'nickname' => 'data.username',
'realname' => 'data.full_name',
'profilepicture' => 'data.profile_picture',
];
);
/**
* {@inheritdoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = [])
protected function doGetUserInformationRequest($url, array $parameters = array())
{
return $this->httpRequest($this->normalizeUrl($url, $parameters), null, [], 'GET');
return $this->httpRequest($this->normalizeUrl($url, $parameters), null, array(), 'GET');
}
/**
@@ -45,7 +45,7 @@ class InstagramResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://api.instagram.com/oauth/authorize',
'access_token_url' => 'https://api.instagram.com/oauth/access_token',
'infos_url' => 'https://api.instagram.com/v1/users/self',
@@ -54,6 +54,6 @@ class InstagramResourceOwner extends GenericOAuth2ResourceOwner
'auth_with_one_url' => true,
'use_bearer_authorization' => false,
]);
));
}
}
@@ -20,20 +20,20 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class ItembaseResourceOwner extends GenericOAuth2ResourceOwner
{
public const ITEMBASE_AUTH_URL = 'https://accounts.itembase.com/oauth/v2/auth';
public const ITEMBASE_TOKEN_URL = 'https://accounts.itembase.com/oauth/v2/token';
public const ITEMBASE_INFOS_URL = 'https://users.itembase.com/v1/me';
const ITEMBASE_AUTH_URL = 'https://accounts.itembase.com/oauth/v2/auth';
const ITEMBASE_TOKEN_URL = 'https://accounts.itembase.com/oauth/v2/token';
const ITEMBASE_INFOS_URL = 'https://users.itembase.com/v1/me';
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'uuid',
'nickname' => 'username',
'firstname' => 'first_name',
'lastname' => 'last_name',
'email' => 'email',
];
);
/**
* {@inheritdoc}
@@ -42,10 +42,10 @@ class ItembaseResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => self::ITEMBASE_AUTH_URL,
'access_token_url' => self::ITEMBASE_TOKEN_URL,
'infos_url' => self::ITEMBASE_INFOS_URL,
]);
));
}
}
@@ -23,12 +23,12 @@ class JawboneResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'xid' => 'data.id',
'firstname' => 'data.first',
'lastname' => 'data.last',
'profilepicture' => 'data.image',
];
);
/**
* {@inheritdoc}
@@ -43,14 +43,14 @@ class JawboneResourceOwner extends GenericOAuth2ResourceOwner
/**
* {@inheritdoc}
*/
public function getInformation($accessToken, $type, array $extraParameters = [])
public function getInformation($accessToken, $type, array $extraParameters = array())
{
$url = $this->normalizeUrl($this->options['infos_url'].'/'.$type, $extraParameters);
$headers = [
$headers = array(
'Authorization' => 'Bearer '.$accessToken['access_token'],
'Accept' => 'application/json',
];
);
return $this->httpRequest($url, null, $headers);
}
@@ -62,11 +62,11 @@ class JawboneResourceOwner extends GenericOAuth2ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => 'https://jawbone.com/auth/oauth2/auth',
'access_token_url' => 'https://jawbone.com/auth/oauth2/token',
'infos_url' => 'https://jawbone.com/nudge/api/v.1.0/users/@me',
'use_commas_in_scope' => true,
]);
));
}
}
@@ -27,27 +27,27 @@ class JiraResourceOwner extends GenericOAuth1ResourceOwner
/**
* {@inheritdoc}
*/
protected $paths = [
protected $paths = array(
'identifier' => 'name',
'nickname' => 'name',
'realname' => 'displayName',
'email' => 'emailAddress',
'profilepicture' => 'avatarUrls.48x48',
];
);
/**
* {@inheritdoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = [])
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
$parameters = array_merge([
$parameters = array_merge(array(
'oauth_consumer_key' => $this->options['client_id'],
'oauth_timestamp' => time(),
'oauth_nonce' => $this->generateNonce(),
'oauth_version' => '1.0',
'oauth_signature_method' => $this->options['signature_method'],
'oauth_token' => $accessToken['oauth_token'],
], $extraParameters);
), $extraParameters);
$parameters['oauth_signature'] = OAuthUtils::signRequest(
'GET',
@@ -59,7 +59,7 @@ class JiraResourceOwner extends GenericOAuth1ResourceOwner
);
$content = $this->getResponseContent($this->doGetUserInformationRequest($this->options['infos_session_url'], $parameters));
$url = $this->normalizeUrl($this->options['infos_url'], ['username' => $content['name']]);
$url = $this->normalizeUrl($this->options['infos_url'], array('username' => $content['name']));
// Regenerate nonce & signature as URL was changed
$parameters['oauth_nonce'] = $this->generateNonce();
@@ -89,7 +89,7 @@ class JiraResourceOwner extends GenericOAuth1ResourceOwner
{
parent::configureOptions($resolver);
$resolver->setDefaults([
$resolver->setDefaults(array(
'authorization_url' => '{base_url}/plugins/servlet/oauth/authorize',
'request_token_url' => '{base_url}/plugins/servlet/oauth/request-token',
'access_token_url' => '{base_url}/plugins/servlet/oauth/access-token',
@@ -99,11 +99,11 @@ class JiraResourceOwner extends GenericOAuth1ResourceOwner
'infos_url' => '{base_url}/rest/api/2/user',
'signature_method' => 'RSA-SHA1',
]);
));
$resolver->setRequired([
$resolver->setRequired(array(
'base_url',
]);
));
$normalizer = function (Options $options, $value) {
return str_replace('{base_url}', $options['base_url'], $value);
@@ -1,63 +0,0 @@
<?php
/*
* This file is part of the HWIOAuthBundle package.
*
* (c) Hardware.Info <opensource@hardware.info>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace HWI\Bundle\OAuthBundle\OAuth\ResourceOwner;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* KeycloakResourceOwner.
*
* @author Andrea Quintino <andreaquin1990@gmail.com>
*/
class KeycloakResourceOwner extends GenericOAuth2ResourceOwner
{
public function configure()
{
$this->prepareBaseAuthenticationUrl();
}
public function getAuthorizationUrl($redirectUri, array $extraParameters = [])
{
return parent::getAuthorizationUrl($redirectUri, array_merge([
'approval_prompt' => $this->getOption('approval_prompt'),
], $extraParameters));
}
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver
->setDefined(['protocol', 'response_type', 'approval_prompt'])
->setRequired('realms')
->setDefaults([
'protocol' => 'openid-connect',
'scope' => 'name,email',
'response_type' => 'code',
'approval_prompt' => 'auto',
]);
}
protected function prepareBaseAuthenticationUrl()
{
$baseAuthUrl = trim($this->getOption('authorization_url'), '/');
//check if already configured
if (false !== strpos($baseAuthUrl, '/realms')) {
return;
}
$baseAuthUrl .= '/realms/'.$this->getOption('realms');
$baseAuthUrl .= '/protocol/'.$this->getOption('protocol').'/auth';
$this->options['authorization_url'] = $baseAuthUrl;
}
}

Some files were not shown because too many files have changed in this diff Show More