Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 66d1891

Browse filesBrowse files
committed
Add the DSN component
1 parent 55a7691 commit 66d1891
Copy full SHA for 66d1891

13 files changed

+727
-0
lines changed

‎src/Symfony/Component/Dsn/.gitignore

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
composer.lock
2+
phpunit.xml
3+
vendor/
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CHANGELOG
2+
=========
3+
4+
3.4.0
5+
-----
6+
7+
* added the component
+67Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Dsn;
13+
14+
use Symfony\Component\Dsn\Exception\InvalidArgumentException;
15+
use Symfony\Component\Dsn\Factory\MemcachedConnectionFactory;
16+
use Symfony\Component\Dsn\Factory\PdoDsnFactory;
17+
use Symfony\Component\Dsn\Factory\RedisConnectionFactory;
18+
19+
/**
20+
* Factory for undetermined Dsn.
21+
*
22+
* @author Jérémy Derussé <jeremy@derusse.com>
23+
*/
24+
class ConnectionFactory
25+
{
26+
const TYPE_REDIS = 1;
27+
const TYPE_MEMCACHED = 2;
28+
29+
/**
30+
* @param string $dsn
31+
*
32+
* @return int
33+
*/
34+
public static function getType($dsn)
35+
{
36+
if (!is_string($dsn)) {
37+
throw new InvalidArgumentException(sprintf('The %s() method expect argument #1 to be string, %s given.', __METHOD__, gettype($dsn)));
38+
}
39+
if (0 === strpos($dsn, 'redis://')) {
40+
return static::TYPE_REDIS;
41+
}
42+
if (0 === strpos($dsn, 'memcached://')) {
43+
return static::TYPE_MEMCACHED;
44+
}
45+
46+
throw new InvalidArgumentException(sprintf('Unsupported Dsn: %s.', $dsn));
47+
}
48+
/**
49+
* Create a connection for a redis Dsn
50+
*
51+
* @param string $dsn
52+
* @param array $options
53+
*
54+
* @return mixed
55+
*/
56+
public static function createConnection($dsn, array $options = array())
57+
{
58+
switch (static::getType($dsn)) {
59+
case static::TYPE_REDIS:
60+
return RedisConnectionFactory::createConnection($dsn, $options);
61+
case static::TYPE_MEMCACHED:
62+
return MemcachedConnectionFactory::createConnection($dsn, $options);
63+
default:
64+
throw new InvalidArgumentException(sprintf('Unsupported Dsn: %s.', $dsn));
65+
}
66+
}
67+
}
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Dsn\Exception;
13+
14+
/**
15+
* Interface for exceptions.
16+
*
17+
* @author Jérémy Derussé <jeremy@derusse.com>
18+
*/
19+
interface ExceptionInterface
20+
{
21+
}
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Dsn\Exception;
13+
14+
/**
15+
* Base InvalidArgumentException for the Dsn component.
16+
*
17+
* @author Jérémy Derussé <jeremy@derusse.com>
18+
*/
19+
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
20+
{
21+
}
+158Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Dsn\Factory;
13+
14+
use Symfony\Component\Dsn\Exception\InvalidArgumentException;
15+
16+
/**
17+
* Factory for Memcached connections
18+
*
19+
* @author Jérémy Derussé <jeremy@derusse.com>
20+
*/
21+
class MemcachedConnectionFactory
22+
{
23+
private static $defaultClientOptions = [
24+
'persistent_id' => null,
25+
'username' => null,
26+
'password' => null,
27+
'serializer' => 'php',
28+
];
29+
30+
/**
31+
* Creates a Memcached instance.
32+
*
33+
* By default, the binary protocol, no block, and libketama compatible options are enabled.
34+
*
35+
* Examples for servers:
36+
* - 'memcached://user:pass@localhost?weight=33'
37+
* - array(array('localhost', 11211, 33))
38+
*
39+
* @param array[]|string|string[] An array of servers, a DSN, or an array of DSNs
40+
* @param array An array of options
41+
*
42+
* @return \Memcached
43+
*
44+
* @throws \ErrorException When invalid options or servers are provided
45+
*/
46+
public static function createConnection($servers, array $options = [])
47+
{
48+
if (is_string($servers)) {
49+
$servers = array($servers);
50+
} elseif (!is_array($servers)) {
51+
throw new InvalidArgumentException(sprintf('MemcachedDsnFactory::createClient() expects array or string as first argument, %s given.', gettype($servers)));
52+
}
53+
set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); });
54+
try {
55+
$options += static::$defaultClientOptions;
56+
$client = new \Memcached($options['persistent_id']);
57+
$username = $options['username'];
58+
$password = $options['password'];
59+
60+
// parse any DSN in $servers
61+
foreach ($servers as $i => $dsn) {
62+
if (is_array($dsn)) {
63+
continue;
64+
}
65+
if (0 !== strpos($dsn, 'memcached://')) {
66+
throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached://"', $dsn));
67+
}
68+
$params = preg_replace_callback('#^memcached://(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) {
69+
if (!empty($m[1])) {
70+
list($username, $password) = explode(':', $m[1], 2) + array(1 => null);
71+
}
72+
73+
return 'file://';
74+
}, $dsn);
75+
if (false === $params = parse_url($params)) {
76+
throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn));
77+
}
78+
if (!isset($params['host']) && !isset($params['path'])) {
79+
throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn));
80+
}
81+
if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) {
82+
$params['weight'] = $m[1];
83+
$params['path'] = substr($params['path'], 0, -strlen($m[0]));
84+
}
85+
$params += array(
86+
'host' => isset($params['host']) ? $params['host'] : $params['path'],
87+
'port' => isset($params['host']) ? 11211 : null,
88+
'weight' => 0,
89+
);
90+
if (isset($params['query'])) {
91+
parse_str($params['query'], $query);
92+
$params += $query;
93+
$options = $query + $options;
94+
}
95+
96+
$servers[$i] = array($params['host'], $params['port'], $params['weight']);
97+
}
98+
99+
// set client's options
100+
unset($options['persistent_id'], $options['username'], $options['password'], $options['weight']);
101+
$options = array_change_key_case($options, CASE_UPPER);
102+
$client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
103+
$client->setOption(\Memcached::OPT_NO_BLOCK, true);
104+
if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) {
105+
$client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
106+
}
107+
foreach ($options as $name => $value) {
108+
if (is_int($name)) {
109+
continue;
110+
}
111+
if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) {
112+
$value = constant('Memcached::'.$name.'_'.strtoupper($value));
113+
}
114+
$opt = constant('Memcached::OPT_'.$name);
115+
116+
unset($options[$name]);
117+
$options[$opt] = $value;
118+
}
119+
$client->setOptions($options);
120+
121+
// set client's servers, taking care of persistent connections
122+
if (!$client->isPristine()) {
123+
$oldServers = array();
124+
foreach ($client->getServerList() as $server) {
125+
$oldServers[] = array($server['host'], $server['port']);
126+
}
127+
128+
$newServers = array();
129+
foreach ($servers as $server) {
130+
if (1 < count($server)) {
131+
$server = array_values($server);
132+
unset($server[2]);
133+
$server[1] = (int) $server[1];
134+
}
135+
$newServers[] = $server;
136+
}
137+
138+
if ($oldServers !== $newServers) {
139+
// before resetting, ensure $servers is valid
140+
$client->addServers($servers);
141+
$client->resetServerList();
142+
}
143+
}
144+
$client->addServers($servers);
145+
146+
if (null !== $username || null !== $password) {
147+
if (!method_exists($client, 'setSaslAuthData')) {
148+
trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.');
149+
}
150+
$client->setSaslAuthData($username, $password);
151+
}
152+
153+
return $client;
154+
} finally {
155+
restore_error_handler();
156+
}
157+
}
158+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.