Initial commit
This commit is contained in:
parent
0a00b0b27f
commit
56f53d15ff
57
config.php
Normal file
57
config.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
// all possible options will be stored
|
||||
$config = array();
|
||||
|
||||
$config['website-name'] = "Web Proxy";
|
||||
$config['access-password'] = "MY_PASSWORD_TO_ACCESS";
|
||||
$config['website-url'] = "MY_FQDN/webproxy";
|
||||
$config['website-description'] = "Web Proxy";
|
||||
|
||||
// a unique key that identifies this application - DO NOT LEAVE THIS EMPTY!
|
||||
$config['app_key'] = 'ADD_HERE_SOME_RANDOM_STRING';
|
||||
|
||||
// a secret key to be used during encryption
|
||||
$config['encryption_key'] = '';
|
||||
|
||||
/*
|
||||
how unique is each URL that is generated by this proxy app?
|
||||
0 - no encoding of any sort. People can link to proxy pages directly: ?q=http://www.yahoo.com
|
||||
1 - Base64 encoding only, people can hotlink to your proxy
|
||||
2 - unique to the IP address that generated it. A person that generated that URL, can bookmark it and visit it and any point
|
||||
3 - unique to that session and IP address - URL no longer valid anywhere when that browser session that generated it ends
|
||||
*/
|
||||
|
||||
$config['url_mode'] = 2;
|
||||
|
||||
// plugins to load - plugins will be loaded in this exact order as in array
|
||||
$config['plugins'] = array(
|
||||
'HeaderRewrite',
|
||||
'Stream',
|
||||
// ^^ do not disable any of the plugins above
|
||||
'Cookie',
|
||||
'Proxify',
|
||||
'UrlForm',
|
||||
// site specific plugins below
|
||||
'Youtube',
|
||||
'DailyMotion',
|
||||
'Twitter'
|
||||
);
|
||||
|
||||
// additional curl options to go with each request
|
||||
$config['curl'] = array(
|
||||
// CURLOPT_PROXY => '',
|
||||
// CURLOPT_CONNECTTIMEOUT => 5
|
||||
);
|
||||
|
||||
//$config['replace_title'] = 'Google Search';
|
||||
|
||||
//$config['error_redirect'] = "https://unblockvideos.com/#error={error_msg}";
|
||||
//$config['index_redirect'] = 'https://unblockvideos.com/';
|
||||
|
||||
// $config['replace_icon'] = 'icon_url';
|
||||
|
||||
// this better be here other Config::load fails
|
||||
return $config;
|
||||
|
||||
?>
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
145
index.php
Normal file
145
index.php
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
require(__DIR__.'/login.php');
|
||||
|
||||
define('PROXY_START', microtime(true));
|
||||
require("vendor/autoload.php");
|
||||
|
||||
use Proxy\Http\Request;
|
||||
use Proxy\Http\Response;
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\FilterEvent;
|
||||
use Proxy\Config;
|
||||
use Proxy\Proxy;
|
||||
|
||||
// start the session
|
||||
session_start();
|
||||
|
||||
// load config...
|
||||
Config::load('./config.php');
|
||||
|
||||
// custom config file to be written to by a bash script or something
|
||||
Config::load('./custom_config.php');
|
||||
|
||||
if (!Config::get('app_key')) {
|
||||
die("app_key inside config.php cannot be empty!");
|
||||
}
|
||||
|
||||
if (!function_exists('curl_version')) {
|
||||
die("cURL extension is not loaded!");
|
||||
}
|
||||
|
||||
// how are our URLs be generated from this point? this must be set here so the proxify_url function below can make use of it
|
||||
if (Config::get('url_mode') == 2) {
|
||||
Config::set('encryption_key', md5(Config::get('app_key') . $_SERVER['REMOTE_ADDR']));
|
||||
} else if (Config::get('url_mode') == 3) {
|
||||
Config::set('encryption_key', md5(Config::get('app_key') . session_id()));
|
||||
}
|
||||
|
||||
// very important!!! otherwise requests are queued while waiting for session file to be unlocked
|
||||
session_write_close();
|
||||
|
||||
// form submit in progress...
|
||||
if (isset($_POST['url'])) {
|
||||
|
||||
$url = $_POST['url'];
|
||||
if (strpos ($url, '.') !== false){
|
||||
$url = add_http($url);
|
||||
header("HTTP/1.1 302 Found");
|
||||
header('Location: '.proxify_url($url));
|
||||
exit;
|
||||
}
|
||||
else {
|
||||
$url = 'http://www.google.com/search?q=' . urlencode($url);
|
||||
$url = add_http($url);
|
||||
header("HTTP/1.1 302 Found");
|
||||
header('Location: '.proxify_url($url));
|
||||
exit;
|
||||
}
|
||||
|
||||
} else if (!isset($_GET['q'])) {
|
||||
|
||||
// must be at homepage - should we redirect somewhere else?
|
||||
if (Config::get('index_redirect')) {
|
||||
|
||||
// redirect to...
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: " . Config::get('index_redirect'));
|
||||
|
||||
} else {
|
||||
if (isset($_GET["tos"]) != "") {
|
||||
echo render_template("./templates/tos.php", array(
|
||||
'version' => Proxy::VERSION
|
||||
));
|
||||
} else {
|
||||
echo render_template("./templates/main.php", array('version' => Proxy::VERSION));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
// decode q parameter to get the real URL
|
||||
$url = url_decrypt($_GET['q']);
|
||||
|
||||
$proxy = new Proxy();
|
||||
|
||||
// load plugins
|
||||
foreach (Config::get('plugins', array()) as $plugin) {
|
||||
|
||||
$plugin_class = $plugin . 'Plugin';
|
||||
|
||||
if (file_exists('./plugins/' . $plugin_class . '.php')) {
|
||||
|
||||
// use user plugin from /plugins/
|
||||
require_once('./plugins/' . $plugin_class . '.php');
|
||||
|
||||
} else if (class_exists('\\Proxy\\Plugin\\' . $plugin_class)) {
|
||||
|
||||
// does the native plugin from php-proxy package with such name exist?
|
||||
$plugin_class = '\\Proxy\\Plugin\\' . $plugin_class;
|
||||
}
|
||||
|
||||
// otherwise plugin_class better be loaded already through composer.json and match namespace exactly \\Vendor\\Plugin\\SuperPlugin
|
||||
$proxy->getEventDispatcher()->addSubscriber(new $plugin_class());
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// request sent to index.php
|
||||
$request = Request::createFromGlobals();
|
||||
|
||||
// remove all GET parameters such as ?q=
|
||||
$request->get->clear();
|
||||
|
||||
// forward it to some other URL
|
||||
$response = $proxy->forward($request, $url);
|
||||
|
||||
// if that was a streaming response, then everything was already sent and script will be killed before it even reaches this line
|
||||
$response->send();
|
||||
|
||||
} catch (Exception $ex) {
|
||||
|
||||
// if the site is on server2.proxy.com then you may wish to redirect it back to proxy.com
|
||||
if (Config::get("error_redirect")) {
|
||||
|
||||
$url = render_string(Config::get("error_redirect"), array(
|
||||
'error_msg' => rawurlencode($ex->getMessage())
|
||||
));
|
||||
|
||||
// Cannot modify header information - headers already sent
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: {$url}");
|
||||
|
||||
} else {
|
||||
|
||||
echo render_template("./templates/main.php", array(
|
||||
'url' => $url,
|
||||
'error_msg' => $ex->getMessage(),
|
||||
'version' => Proxy::VERSION
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
9
language.php
Normal file
9
language.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
$lang["slogan"] = "remove the borders";
|
||||
$lang["wikipedia"] = "Wikipedia";
|
||||
$lang["back"] = "Back";
|
||||
$lang["go"] = "Go";
|
||||
$lang["home"] = "Home";
|
||||
$lang["tos"] = "This is an private Web Proxy - Unauthorized use is strictly prohibited!";
|
||||
$lang["agree"] = "michu-IT";
|
||||
$lang["tos_2"] = "terms of use";
|
25
plugins/TestPlugin.php
Normal file
25
plugins/TestPlugin.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
class TestPlugin extends AbstractPlugin {
|
||||
|
||||
public function onBeforeRequest(ProxyEvent $event){
|
||||
// fired right before a request is being sent to a proxy
|
||||
}
|
||||
|
||||
public function onHeadersReceived(ProxyEvent $event){
|
||||
// fired right after response headers have been fully received - last chance to modify before sending it back to the user
|
||||
}
|
||||
|
||||
public function onCurlWrite(ProxyEvent $event){
|
||||
// fired as the data is being written piece by piece
|
||||
}
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
// fired after the full response=headers+body has been read - will only be called on "non-streaming" responses
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
39
plugins/UrlFormPlugin.php
Normal file
39
plugins/UrlFormPlugin.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
class UrlFormPlugin extends AbstractPlugin {
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
|
||||
$request = $event['request'];
|
||||
$response = $event['response'];
|
||||
|
||||
$url = $request->getUri();
|
||||
|
||||
// we attach url_form only if this is a html response
|
||||
if(!is_html($response->headers->get('content-type'))){
|
||||
return;
|
||||
}
|
||||
|
||||
// this path would be relative to index.php that included it?
|
||||
$url_form = render_template("./templates/url_form.php", array(
|
||||
'url' => $url
|
||||
));
|
||||
|
||||
$output = $response->getContent();
|
||||
|
||||
// does the html page contain <body> tag, if so insert our form right after <body> tag starts
|
||||
$output = preg_replace('@<body.*?>@is', '$0'.PHP_EOL.$url_form, $output, 1, $count);
|
||||
|
||||
// <body> tag was not found, just put the form at the top of the page
|
||||
if($count == 0){
|
||||
$output = $url_form.$output;
|
||||
}
|
||||
|
||||
$response->setContent($output);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
84
templates/main.php
Normal file
84
templates/main.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
require(__DIR__ . "/../language.php");
|
||||
require(__DIR__ . "/../config.php");
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo $config['website-name']; ?></title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<?php echo $config["website-description"]; ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #373737 !important;
|
||||
background-image: url(https://www.blackgate.org/wood.jpg);
|
||||
}
|
||||
.jumbotron {
|
||||
background-color: #e9ecefc9 !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container text-center" style="margin-top:7%;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<?php if (isset($error_msg)) { ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p><?php echo $error_msg; ?></p>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="jumbotron">
|
||||
<h1 class="display-3"><?php echo $config['website-name']; ?></h1>
|
||||
<p class="lead"><?php echo $lang["slogan"]; ?></p>
|
||||
<div class="btn-group" role="group">
|
||||
<a id="twitter" class="btn btn-info" href="#">Twitter</a>
|
||||
<a id="youtube" class="btn btn-danger" href="#">YouTube</a>
|
||||
<a id="facebook" class="btn btn-primary" href="#">Facebook</a>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class="btn-group" role="group">
|
||||
<a id="vikipedi" class="btn btn-secondary" href="#"><?php echo $lang["wikipedia"]; ?></a>
|
||||
<a id="google" class="btn btn-success" href="#">Google</a>
|
||||
</div>
|
||||
<p class="lead">
|
||||
<form class="form-group" action="index.php" method="post">
|
||||
<input id="url" name="url" type="text" class="form-control" autocomplete="on" placeholder="URL or Search"
|
||||
autofocus required/>
|
||||
<br>
|
||||
<input class="btn btn-primary btn-lg" type="submit" value="<?php echo $lang["go"]; ?>"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<p style="font-size:15px; color:white">
|
||||
<small><?php echo $lang["agree"]; ?> <a
|
||||
href="<?php echo $config['website-url']; ?>/?tos"><?php echo $lang["tos_2"]; ?></a>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
|
||||
<script>
|
||||
$('#twitter').click(function () {
|
||||
$('#url').val('https://twitter.com');
|
||||
});
|
||||
$('#youtube').click(function () {
|
||||
$('#url').val('https://youtube.com');
|
||||
});
|
||||
$('#facebook').click(function () {
|
||||
$('#url').val('https://facebook.com');
|
||||
});
|
||||
$('#google').click(function () {
|
||||
$('#url').val('https://google.com');
|
||||
});
|
||||
$('#vikipedi').click(function () {
|
||||
$('#url').val('https://wikipedia.org');
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
templates/proxy.png
Normal file
BIN
templates/proxy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
30
templates/tos.php
Normal file
30
templates/tos.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
require(__DIR__ . "/../language.php");
|
||||
require(__DIR__ . "/../config.php");
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo $config['website-name']; ?></title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<?php echo $config["website-description"]; ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container text-center" style="margin-top:5%;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="jumbotron">
|
||||
<h1 class="display-3"><?php echo $config['website-name']; ?></h1>
|
||||
<p class="lead"><?php echo $lang["slogan"]; ?></p>
|
||||
<p><?php echo $lang["tos"]; ?></p>
|
||||
<a href="<?php echo $config['website-url']; ?>"
|
||||
class="btn btn-primary btn-lg"><?php echo $lang["back"]; ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
80
templates/url_form.php
Normal file
80
templates/url_form.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
require(__DIR__ . "/../language.php");
|
||||
?>
|
||||
<style type="text/css">
|
||||
|
||||
html body {
|
||||
margin-top: 50px !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#top_form {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
|
||||
z-index: 2100000000;
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-o-user-select: none;
|
||||
|
||||
border-bottom: 1px solid #151515;
|
||||
|
||||
background: #CCCCCC;
|
||||
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
}
|
||||
|
||||
#top_form input[name=url] {
|
||||
width: 550px;
|
||||
height: 20px;
|
||||
padding: 5px;
|
||||
font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
border: 0px none;
|
||||
background: none repeat scroll 0% 0% #FFF;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var url_text_selected = false;
|
||||
|
||||
function smart_select(ele) {
|
||||
|
||||
ele.onblur = function () {
|
||||
url_text_selected = false;
|
||||
};
|
||||
|
||||
ele.onclick = function () {
|
||||
if (url_text_selected == false) {
|
||||
this.focus();
|
||||
this.select();
|
||||
url_text_selected = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="top_form">
|
||||
|
||||
<div style="width:800px; margin:0 auto;">
|
||||
|
||||
<form method="post" action="index.php" target="_top" style="margin:0; padding:0;">
|
||||
<input type="button" value="<?php echo $lang["home"]; ?>" onclick=" window.location.href='index.php'">
|
||||
<input type="text" name="url" value="<?php echo $url; ?>" autocomplete="off">
|
||||
<input type="hidden" name="form" value="1">
|
||||
<input type="submit" value="<?php echo $lang["go"]; ?>">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type=" text/javascript">
|
||||
smart_select(document.getElementsByName("url")[0]);
|
||||
</script>
|
1
vendor/athlon1600/php-proxy-plugin-bundle
vendored
Submodule
1
vendor/athlon1600/php-proxy-plugin-bundle
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 172202c9b7913dc397b0a2eeacb68984a73f5c6e
|
3
vendor/athlon1600/php-proxy/.gitignore
vendored
Normal file
3
vendor/athlon1600/php-proxy/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/vendor/*
|
||||
composer.lock
|
||||
.htaccess
|
21
vendor/athlon1600/php-proxy/LICENSE
vendored
Normal file
21
vendor/athlon1600/php-proxy/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
99
vendor/athlon1600/php-proxy/README.md
vendored
Normal file
99
vendor/athlon1600/php-proxy/README.md
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
php-proxy
|
||||
=========
|
||||
|
||||
Proxy script built on PHP, Symfony and cURL.
|
||||
This library borrows ideas from Glype, Jenssegers proxy, and Guzzle.
|
||||
|
||||
PHP-Proxy Web Application
|
||||
-------
|
||||
|
||||
If you're looking for a **project** version of this script that functions as a Web Application similar to Glype, then visit
|
||||
[**php-proxy-app**](https://github.com/Athlon1600/php-proxy-app)
|
||||
|
||||
See this php-proxy in action:
|
||||
<a href="https://unblockvideos.com/" target="_blank">UnblockVideos.com</a>
|
||||
|
||||
Installation
|
||||
-------
|
||||
|
||||
Install it using [Composer](http://getcomposer.org):
|
||||
|
||||
```bash
|
||||
composer require athlon1600/php-proxy
|
||||
```
|
||||
|
||||
Example
|
||||
--------
|
||||
|
||||
```php
|
||||
require('vendor/autoload.php');
|
||||
|
||||
use Proxy\Http\Request;
|
||||
use Proxy\Proxy;
|
||||
|
||||
$request = Request::createFromGlobals();
|
||||
|
||||
$proxy = new Proxy();
|
||||
|
||||
$proxy->getEventDispatcher()->addListener('request.before_send', function($event){
|
||||
|
||||
$event['request']->headers->set('X-Forwarded-For', 'php-proxy');
|
||||
|
||||
});
|
||||
|
||||
$proxy->getEventDispatcher()->addListener('request.sent', function($event){
|
||||
|
||||
if($event['response']->getStatusCode() != 200){
|
||||
die("Bad status code!");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$proxy->getEventDispatcher()->addListener('request.complete', function($event){
|
||||
|
||||
$content = $event['response']->getContent();
|
||||
$content .= '<!-- via php-proxy -->';
|
||||
|
||||
$event['response']->setContent($content);
|
||||
|
||||
});
|
||||
|
||||
$response = $proxy->forward($request, "https://www.yahoo.com");
|
||||
|
||||
// send the response back to the client
|
||||
$response->send();
|
||||
|
||||
```
|
||||
|
||||
Plugin Example
|
||||
--------
|
||||
|
||||
```php
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
use Proxy\Html;
|
||||
|
||||
class MultiSiteMatchPlugin extends AbstractPlugin {
|
||||
|
||||
// Matches multiple domain names (abc.com, abc.de, abc.pl) using regex (you MUST use / character)
|
||||
protected $url_pattern = '/^abc\.(com|de|pl)$/is';
|
||||
// Matches a single domain name
|
||||
//protected $url_pattern = 'abc.com';
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
|
||||
$response = $event['response'];
|
||||
|
||||
$html = $response->getContent();
|
||||
|
||||
// do your stuff here...
|
||||
|
||||
$response->setContent($html);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notice that you must use the **/** character for regexes on ```$url_pattern```
|
21
vendor/athlon1600/php-proxy/composer.json
vendored
Normal file
21
vendor/athlon1600/php-proxy/composer.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "athlon1600/php-proxy",
|
||||
"type": "library",
|
||||
"keywords": ["php proxy", "proxy script", "php web proxy", "web proxy", "php proxy script"],
|
||||
"homepage": "https://www.php-proxy.com/",
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"symfony/event-dispatcher": "~3.2"
|
||||
},
|
||||
"suggest": {
|
||||
"predis/predis": "For caching purposes"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Proxy\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
]
|
||||
}
|
||||
}
|
39
vendor/athlon1600/php-proxy/src/Config.php
vendored
Normal file
39
vendor/athlon1600/php-proxy/src/Config.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy;
|
||||
|
||||
// based off of this:
|
||||
// http://v3.golaravel.com/api/source-class-Laravel.Config.html#3-235
|
||||
|
||||
class Config {
|
||||
|
||||
private static $config = array();
|
||||
|
||||
public static function get($key, $default = null){
|
||||
return self::has($key) ? static::$config[$key] : $default;
|
||||
}
|
||||
|
||||
public static function set($key, $value){
|
||||
self::$config[$key] = $value;
|
||||
}
|
||||
|
||||
public static function has($key){
|
||||
return isset(static::$config[$key]);
|
||||
}
|
||||
|
||||
public static function load($path){
|
||||
|
||||
if(file_exists($path)){
|
||||
|
||||
// Successful includes, unless overridden by the included file, return 1.
|
||||
$data = require($path);
|
||||
|
||||
if(is_array($data)){
|
||||
self::$config = array_merge(self::$config, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
39
vendor/athlon1600/php-proxy/src/Event/ProxyEvent.php
vendored
Normal file
39
vendor/athlon1600/php-proxy/src/Event/ProxyEvent.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Event;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
// http://symfony.com/doc/current/components/event_dispatcher/generic_event.html
|
||||
class ProxyEvent extends Event implements \ArrayAccess {
|
||||
|
||||
private $data;
|
||||
|
||||
public function __construct($data = array()){
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value){
|
||||
|
||||
if(is_null($offset)) {
|
||||
$this->data[] = $value;
|
||||
} else {
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetExists($offset){
|
||||
return isset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset){
|
||||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset){
|
||||
return isset($this->data[$offset]) ? $this->data[$offset] : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
182
vendor/athlon1600/php-proxy/src/Html.php
vendored
Normal file
182
vendor/athlon1600/php-proxy/src/Html.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy;
|
||||
|
||||
class Html {
|
||||
|
||||
public static function remove_scripts($html){
|
||||
$html = preg_replace('/<\s*script[^>]*>(.*?)<\s*\/\s*script\s*>/is', '', $html);
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function remove_styles($html){
|
||||
$html = preg_replace('/<\s*style[^>]*>(.*?)<\s*\/\s*style\s*>/is', '', $html);
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function remove_comments($html){
|
||||
return preg_replace('/<!--(.*?)-->/s', '', $html);
|
||||
}
|
||||
|
||||
private static function find($selector, $html, $start_from = 0){
|
||||
|
||||
$html = substr($html, $start_from);
|
||||
|
||||
$inner_start = 0;
|
||||
$inner_end = 0;
|
||||
|
||||
$pattern = '//';
|
||||
|
||||
if(substr($selector, 0, 1) == '#'){
|
||||
$pattern = '/<(\w+)[^>]+id="'.substr($selector, 1).'"[^>]*>/is';
|
||||
} else if(substr($selector, 0, 1) == '.'){
|
||||
$pattern = '/<(\w+)[^>]+class="'.substr($selector, 1).'"[^>]*>/is';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(preg_match($pattern, $html, $matches, PREG_OFFSET_CAPTURE)){
|
||||
|
||||
$outer_start = $matches[0][1];
|
||||
$inner_start = $matches[0][1] + strlen($matches[0][0]);
|
||||
|
||||
// tag stuff
|
||||
$tag_name = $matches[1][0];
|
||||
$tag_len = strlen($tag_name);
|
||||
|
||||
$run_count = 300;
|
||||
|
||||
// "open" <tag elements we found so far
|
||||
$open_count = 1;
|
||||
$start = $inner_start;
|
||||
|
||||
while($open_count != 0 && $run_count-- > 0){
|
||||
|
||||
$open_tag = strpos($html, "<{$tag_name}", $start);
|
||||
$close_tag = strpos($html, "</{$tag_name}", $start);
|
||||
|
||||
// nothing was found?
|
||||
if($open_tag === false && $close_tag === false){
|
||||
break;
|
||||
}
|
||||
|
||||
//echo "open_tag: {$open_tag}, close_tag {$close_tag}\r\n";
|
||||
|
||||
// found OPEN tag
|
||||
if($close_tag === false || ($open_tag !== false && $open_tag < $close_tag) ){
|
||||
$open_count++;
|
||||
$start = $open_tag + $tag_len + 1;
|
||||
|
||||
//echo "found open tag: ".substr($html, $open_tag, 20)." at {$open_tag} \r\n";
|
||||
|
||||
// found CLOSE tag
|
||||
} else if($open_tag === false || ($close_tag !== false && $close_tag < $open_tag) ){
|
||||
$open_count--;
|
||||
$start = $close_tag + $tag_len + 2;
|
||||
|
||||
//echo "found close tag: ".substr($html, $close_tag, 20)." at {$close_tag} \r\n";
|
||||
}
|
||||
}
|
||||
|
||||
// something went wrong... don't bother returning anything
|
||||
if($open_count != 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$outer_end = $close_tag + $tag_len + 3;
|
||||
$inner_end = $close_tag;
|
||||
|
||||
return array(
|
||||
'outer_start' => $outer_start + $start_from,
|
||||
'inner_start' => $inner_start + $start_from,
|
||||
'inner_end' => $inner_end + $start_from,
|
||||
'outer_end' => $outer_end + $start_from
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function extract_inner($selector, $html){
|
||||
return self::extract($selector, $html, true);
|
||||
}
|
||||
|
||||
public static function extract_outer($selector, $html){
|
||||
return self::extract($selector, $html, false);
|
||||
}
|
||||
|
||||
private static function extract($selector, $html, $inner = false){
|
||||
|
||||
$pos = 0;
|
||||
$limit = 300;
|
||||
|
||||
$result = array();
|
||||
$data = false;
|
||||
|
||||
do {
|
||||
|
||||
$data = self::find($selector, $html, $pos);
|
||||
|
||||
if($data){
|
||||
|
||||
$code = substr($html, $inner ? $data['inner_start'] : $data['outer_start'],
|
||||
$inner ? $data['inner_end'] - $data['inner_start'] : $data['outer_end'] - $data['outer_start']);
|
||||
|
||||
$result[] = $code;
|
||||
$pos = $data['outer_end'];
|
||||
}
|
||||
|
||||
} while ($data && --$limit > 0);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function remove($selector, $html){
|
||||
return self::replace($selector, '', $html, false);
|
||||
}
|
||||
|
||||
public static function replace_outer($selector, $replace, $html, &$matches = NULL){
|
||||
return self::replace($selector, $replace, $html, false, $matches);
|
||||
}
|
||||
|
||||
public static function replace_inner($selector, $replace, $html, &$matches = NULL){
|
||||
return self::replace($selector, $replace, $html, true, $matches);
|
||||
}
|
||||
|
||||
private static function replace($selector, $replace, $html, $replace_inner = false, &$matches = NULL){
|
||||
|
||||
$start_from = 0;
|
||||
$limit = 300;
|
||||
|
||||
$data = false;
|
||||
$replace = (array)$replace;
|
||||
|
||||
do {
|
||||
|
||||
$data = self::find($selector, $html, $start_from);
|
||||
|
||||
if($data){
|
||||
|
||||
$r = array_shift($replace);
|
||||
|
||||
// from where to where will we be replacing?
|
||||
$replace_space = $replace_inner ? $data['inner_end'] - $data['inner_start'] : $data['outer_end'] - $data['outer_start'];
|
||||
$replace_len = strlen($r);
|
||||
|
||||
if($matches !== NULL){
|
||||
$matches[] = substr($html, $replace_inner ? $data['inner_start'] : $data['outer_start'], $replace_space);
|
||||
}
|
||||
|
||||
$html = substr_replace($html, $r, $replace_inner ? $data['inner_start'] : $data['outer_start'], $replace_space);
|
||||
|
||||
// next time we resume search at position right at the end of this element
|
||||
$start_from = $data['outer_end'] + ($replace_len - $replace_space);
|
||||
}
|
||||
|
||||
} while ($data && --$limit > 0);
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
84
vendor/athlon1600/php-proxy/src/Http/ParamStore.php
vendored
Normal file
84
vendor/athlon1600/php-proxy/src/Http/ParamStore.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Http;
|
||||
|
||||
/*
|
||||
|
||||
heavily borrowed from Symfony's ParameterBag and Guzzle Collection
|
||||
|
||||
https://github.com/guzzle/guzzle/blob/v3.5.0/src/Guzzle/Common/Collection.php
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class ParamStore {
|
||||
|
||||
protected $data = array();
|
||||
protected $case_sensitive;
|
||||
|
||||
public function __construct($parameters = array(), $case_sensitive = false){
|
||||
$this->data = $parameters;
|
||||
$this->case_sensitive = $case_sensitive;
|
||||
}
|
||||
|
||||
private function normalizeKey($key){
|
||||
return $this->case_sensitive ? $key : strtolower($key);
|
||||
}
|
||||
|
||||
public function set($key, $value, $replace = true){
|
||||
|
||||
$key = $this->normalizeKey($key);
|
||||
|
||||
// replacing or does not have existing key filled yet
|
||||
if($replace || !$this->has($key)){
|
||||
$this->data[$key] = $value;
|
||||
} else {
|
||||
|
||||
if(is_array($this->data[$key])){
|
||||
$this->data[$key][] = $value;
|
||||
} else {
|
||||
$this->data[$key] = array($this->data[$key], $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function replace(array $data){
|
||||
|
||||
// remove all existing items first
|
||||
$this->clear();
|
||||
|
||||
foreach($data as $key => $value){
|
||||
$this->set($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove($key){
|
||||
unset($this->data[$this->normalizeKey($key)]);
|
||||
}
|
||||
|
||||
public function clear(){
|
||||
$this->data = array();
|
||||
}
|
||||
|
||||
public function has($key){
|
||||
return isset($this->data[$this->normalizeKey($key)]);
|
||||
}
|
||||
|
||||
public function get($key, $default = null){
|
||||
|
||||
$key = $this->normalizeKey($key);
|
||||
|
||||
return $this->has($key) ? $this->data[$key] : $default;
|
||||
}
|
||||
|
||||
// Returns an array of all values currently stored
|
||||
public function all(){
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return json_encode($this->data, true);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
362
vendor/athlon1600/php-proxy/src/Http/Request.php
vendored
Normal file
362
vendor/athlon1600/php-proxy/src/Http/Request.php
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Http;
|
||||
|
||||
use Proxy\Http\ParamStore;
|
||||
|
||||
class Request {
|
||||
|
||||
private $method;
|
||||
private $url;
|
||||
|
||||
private $protocol_version = '1.1';
|
||||
|
||||
// Custom attributes to go with each Request instance - has nothing to do with HTTP
|
||||
public $params; // parameters
|
||||
|
||||
// HTTP headers for this request - all in lowercase
|
||||
public $headers;
|
||||
|
||||
// Here we store cookies for that request
|
||||
//public $cookies;
|
||||
|
||||
// Collection of POST fields to be submitted
|
||||
public $post;
|
||||
|
||||
// Query string parameters for URL
|
||||
public $get;
|
||||
|
||||
// Files to be uploaded with POST
|
||||
public $files;
|
||||
|
||||
// User set body contents
|
||||
private $body = null;
|
||||
|
||||
// Library generated body that is regenerated through prepare method
|
||||
private $prepared_body = null;
|
||||
|
||||
public function __construct($method, $url, $headers = array(), $body = null){
|
||||
|
||||
$this->params = new ParamStore();
|
||||
$this->headers = new ParamStore();
|
||||
|
||||
// http params
|
||||
$this->post = new ParamStore(null, true);
|
||||
$this->get = new ParamStore(null, true);
|
||||
|
||||
$this->files = new ParamStore(null, true);
|
||||
|
||||
$this->setMethod($method);
|
||||
$this->setUrl($url);
|
||||
$this->setBody($body);
|
||||
|
||||
// make the request ready to be sent right from the start - prepare must be called manually from this point on if you ever add post or file parameters
|
||||
$this->prepare();
|
||||
}
|
||||
|
||||
/*
|
||||
Does multiple things
|
||||
- regenerate content body based on $post and $files parameters
|
||||
- set content-type, content-length headers
|
||||
- set transfer-encoding, expect headers
|
||||
*/
|
||||
public function prepare(){
|
||||
|
||||
/*
|
||||
Any HTTP/1.1 message containing an entity-body SHOULD include a Content-Type header field defining the media type of that body.
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1
|
||||
*/
|
||||
|
||||
// Must be a multipart request
|
||||
if($this->files->all()){
|
||||
|
||||
$boundary = self::generateBoundary();
|
||||
|
||||
$this->prepared_body = Request::buildPostBody($this->post->all(), $this->files->all(), $boundary);
|
||||
$this->headers->set('content-type', 'multipart/form-data; boundary='.$boundary);
|
||||
|
||||
} else if($this->post->all()){
|
||||
|
||||
$this->prepared_body = http_build_query($this->post->all());
|
||||
$this->headers->set('content-type', 'application/x-www-form-urlencoded');
|
||||
|
||||
} else {
|
||||
|
||||
$this->headers->set('content-type', $this->detectContentType($this->body));
|
||||
$this->prepared_body = $this->body;
|
||||
}
|
||||
|
||||
/*
|
||||
The transfer-length of a message is the length of the message-body as it appears in the message; that is, after any transfer-codings have been applied.
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
|
||||
*/
|
||||
|
||||
$len = strlen($this->prepared_body);
|
||||
|
||||
if($len > 0){
|
||||
$this->headers->set('content-length', $len);
|
||||
} else {
|
||||
$this->headers->remove('content-length');
|
||||
$this->headers->remove('content-type');
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
$str = $this->getMethod().' '.$this->getUrl().' HTTP/'.$this->getProtocolVersion()."\r\n";
|
||||
return $str.$this->getRawHeaders()."\r\n\r\n".$this->getRawBody();
|
||||
}
|
||||
|
||||
public function setMethod($method){
|
||||
$this->method = strtoupper($method);
|
||||
}
|
||||
|
||||
public function getMethod(){
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
// this was no longer working --- https://github.com/guzzle/psr7/blob/master/src/functions.php
|
||||
public static function parseQuery($query){
|
||||
$result = array();
|
||||
parse_str($query, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setUrl($url){
|
||||
// remove hashtag - preg_replace so we don't have to check for its existence first - is it possible preserving hashtag?
|
||||
$url = preg_replace('/#.*/', '', $url);
|
||||
|
||||
// check if url has any query parameters
|
||||
$query = parse_url($url, PHP_URL_QUERY);
|
||||
|
||||
// remove it and add the query params to get collection
|
||||
if($query){
|
||||
//$url = str_replace('?'.$query, '', $url);
|
||||
$url = preg_replace('/\?.*/', '', $url);
|
||||
|
||||
$result = self::parseQuery($query);
|
||||
$this->get->replace($result);
|
||||
}
|
||||
|
||||
// url without query params - those will be appended later
|
||||
$this->url = $url;
|
||||
$this->headers->set('host', parse_url($url, PHP_URL_HOST));
|
||||
}
|
||||
|
||||
public function getRawHeaders(){
|
||||
|
||||
$result = array();
|
||||
|
||||
$headers = $this->headers->all();
|
||||
|
||||
// Sort headers by name
|
||||
//ksort($headers);
|
||||
|
||||
// Turn this into name=value pairs
|
||||
foreach($headers as $name => $values){
|
||||
|
||||
// could be an array if multiple headers are sent with the same name?
|
||||
foreach( (array)$values as $value){
|
||||
$name = implode('-', array_map('ucfirst', explode('-', $name)));
|
||||
$result[] = sprintf("%s: %s", $name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\r\n", $result);
|
||||
}
|
||||
|
||||
public function getUrl(){
|
||||
|
||||
// does this URL have any query parameters?
|
||||
if($this->get->all()){
|
||||
return $this->url.'?'.http_build_query($this->get->all());
|
||||
}
|
||||
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function getUri(){
|
||||
return call_user_func_array(array($this, "getUrl"), func_get_args());
|
||||
}
|
||||
|
||||
public function setProtocolVersion($version){
|
||||
$this->protocol_version = $version;
|
||||
}
|
||||
|
||||
public function getProtocolVersion(){
|
||||
return $this->protocol_version;
|
||||
}
|
||||
|
||||
// Set raw contents of the body
|
||||
// this will clear all the values currently stored in POST and FILES
|
||||
// will be ignored during PREPARE if post or files contain any values
|
||||
public function setBody($body, $content_type = false){
|
||||
|
||||
// clear old body data
|
||||
$this->post->clear();
|
||||
$this->files->clear();
|
||||
|
||||
// is this form data?
|
||||
if(is_array($body)){
|
||||
$body = http_build_query($body);
|
||||
}
|
||||
|
||||
$this->body = (string)$body;
|
||||
|
||||
// plain text should be: text/plain; charset=UTF-8
|
||||
if($content_type){
|
||||
$this->headers->set('content-type', $content_type);
|
||||
}
|
||||
|
||||
// do it!
|
||||
$this->prepare();
|
||||
}
|
||||
|
||||
private static function generateBoundary(){
|
||||
return '-----'.md5(microtime().rand());
|
||||
}
|
||||
|
||||
// can be $_POST and $_FILES
|
||||
public static function buildPostBody($fields, $files, $boundary = null){
|
||||
|
||||
// the reason BODY part is not included in sprintf pattern is because of limits
|
||||
$part_field = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n";
|
||||
$part_file = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n";
|
||||
|
||||
// each part should be preceeded by this line
|
||||
if(!$boundary){
|
||||
$boundary = self::generateBoundary();
|
||||
}
|
||||
|
||||
$body = '';
|
||||
|
||||
foreach($fields as $name => $value){
|
||||
$body .= sprintf($part_field, $boundary, $name, $value);
|
||||
$body .= "{$value}\r\n";
|
||||
}
|
||||
|
||||
// data better have [name, tmp_name, and optional type]
|
||||
foreach($files as $name => $values) {
|
||||
// Multiple files can be uploaded using different name for input.
|
||||
// See http://php.net/manual/en/features.file-upload.multiple.php
|
||||
if (!is_array($values['tmp_name'])) {
|
||||
$multiValues = array_map(function ($a) {
|
||||
return (array)$a;
|
||||
}, $values);
|
||||
$fieldName = $name;
|
||||
} else {
|
||||
$multiValues = $values;
|
||||
$fieldName = "{$name}[]";
|
||||
}
|
||||
|
||||
foreach (array_keys($multiValues['tmp_name']) as $key) {
|
||||
|
||||
// There must be no error http://php.net/manual/en/features.file-upload.errors.php
|
||||
if (!$multiValues['tmp_name'][$key] || $multiValues['error'][$key] !== 0 || !is_readable($multiValues['tmp_name'][$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$body .= sprintf($part_file, $boundary, $fieldName, $multiValues['name'][$key], $multiValues['type'][$key]);
|
||||
$body .= file_get_contents($multiValues['tmp_name'][$key]);
|
||||
$body .= "\r\n";
|
||||
}
|
||||
}
|
||||
$body .= "--{$boundary}--\r\n\r\n";
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function detectContentType($data){
|
||||
|
||||
// http://www.w3.org/Protocols/rfc1341/4_Content-Type.html
|
||||
|
||||
// If the media type remains unknown, the recipient SHOULD treat it as type "application/octet-stream".
|
||||
$content_type = 'application/octet-stream';
|
||||
|
||||
if(preg_match('/^{\s*"[^"]+"\s*:/', $data)){
|
||||
$content_type = 'application/json';
|
||||
} else if(preg_match('/^(?:<\?xml[^?>]+\?>)\s*<[^>]+>/i', $data)){
|
||||
$content_type = 'application/xml';
|
||||
} else if(preg_match('/^[a-zA-Z0-9_.~-]+=[^&]*&/', $data)){
|
||||
$content_type = 'application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
return $content_type;
|
||||
}
|
||||
|
||||
// Returns a parsed version of the body
|
||||
/*
|
||||
public function getBody(){
|
||||
|
||||
// what is the content type?
|
||||
$content_type = $this->headers->get('content-type', '');
|
||||
|
||||
switch($content_type){
|
||||
case 'application/x-www-form-urlencoded':
|
||||
$result = array();
|
||||
mb_parse_str($this->body, $result);
|
||||
return $result;
|
||||
case 'application/json':
|
||||
return json_decode($this->body);
|
||||
case 'text/xml':
|
||||
case 'application/xml':
|
||||
case 'application/x-xml':
|
||||
return simplexml_load_string($this->body);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
// Returns raw body string exactly as it appears in the HTTP request
|
||||
public function getRawBody(){
|
||||
return $this->prepared_body;
|
||||
}
|
||||
|
||||
public static function createFromGlobals(){
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) ? 'https' : 'http';
|
||||
|
||||
$url = $scheme.'://'. $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
||||
|
||||
$request = new Request($method, $url);
|
||||
|
||||
// fill in headers
|
||||
foreach($_SERVER as $name => $value){
|
||||
|
||||
if(strpos($name, 'HTTP_') === 0){
|
||||
|
||||
$name = substr($name, 5);
|
||||
$name = str_replace('_', ' ', $name);
|
||||
$name = ucwords(strtolower($name));
|
||||
$name = str_replace(' ', '-', $name);
|
||||
|
||||
$request->headers->set($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
// for extra convenience
|
||||
//$request->params->set('user-ip', $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
// will be empty if content-type is multipart
|
||||
$input = file_get_contents("php://input");
|
||||
|
||||
if(count($_FILES) > 0){
|
||||
$request->post->replace($_POST);
|
||||
$request->files->replace($_FILES);
|
||||
} else if(count($_POST) > 0){
|
||||
$request->post->replace($_POST);
|
||||
} else {
|
||||
$request->setBody($input);
|
||||
}
|
||||
|
||||
// for extra convenience
|
||||
$request->prepare();
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
120
vendor/athlon1600/php-proxy/src/Http/Response.php
vendored
Normal file
120
vendor/athlon1600/php-proxy/src/Http/Response.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Http;
|
||||
|
||||
use Proxy\Http\ParamStore;
|
||||
|
||||
class Response {
|
||||
|
||||
protected $statusCodes = array(
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
307 => 'Temporary Redirect',
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Time-out',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Large',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested range not satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
429 => 'Too Many Requests',
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Time-out',
|
||||
505 => 'Unsupported Version'
|
||||
);
|
||||
|
||||
public $status;
|
||||
|
||||
public $headers;
|
||||
|
||||
private $content;
|
||||
|
||||
// getHeaderLines
|
||||
public function __construct($content = '', $status = 200, $headers = array()){
|
||||
|
||||
$this->headers = new ParamStore($headers);
|
||||
|
||||
$this->setContent($content);
|
||||
$this->setStatusCode($status);
|
||||
}
|
||||
|
||||
public function setStatusCode($code){
|
||||
$this->status = $code;
|
||||
}
|
||||
|
||||
public function getStatusCode(){
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function getStatusText(){
|
||||
return $this->statusCodes[$this->getStatusCode()];
|
||||
}
|
||||
|
||||
public function setContent($content){
|
||||
$this->content = (string)$content;
|
||||
}
|
||||
|
||||
public function getContent(){
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function sendHeaders(){
|
||||
|
||||
if(headers_sent()){
|
||||
return;
|
||||
}
|
||||
|
||||
header(sprintf('HTTP/1.1 %s %s', $this->status, $this->getStatusText()), true, $this->status);
|
||||
|
||||
foreach($this->headers->all() as $name => $value){
|
||||
|
||||
/*
|
||||
Multiple message-header fields with the same field-name MAY be present in a message
|
||||
if and only if the entire field-value for that header field is defined as a comma-separated list
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
|
||||
*/
|
||||
|
||||
$values = is_array($value) ? $value : array($value);
|
||||
|
||||
// false = do not replace previous identical header
|
||||
foreach($values as $value){
|
||||
header("{$name}: {$value}", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function send(){
|
||||
$this->sendHeaders();
|
||||
echo $this->content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
80
vendor/athlon1600/php-proxy/src/Plugin/AbstractPlugin.php
vendored
Normal file
80
vendor/athlon1600/php-proxy/src/Plugin/AbstractPlugin.php
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
abstract class AbstractPlugin implements EventSubscriberInterface {
|
||||
|
||||
// apply these methods only to those events whose request URL passes this filter
|
||||
protected $url_pattern;
|
||||
|
||||
public function onBeforeRequest(ProxyEvent $event){
|
||||
// fired right before a request is being sent to a proxy
|
||||
}
|
||||
|
||||
public function onHeadersReceived(ProxyEvent $event){
|
||||
// fired right after response headers have been fully received - last chance to modify before sending it back to the user
|
||||
}
|
||||
|
||||
public function onCurlWrite(ProxyEvent $event){
|
||||
// fired as the data is being written piece by piece
|
||||
}
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
// fired after the full response=headers+body has been read - will only be called on "non-streaming" responses
|
||||
}
|
||||
|
||||
// dispatch based on filter
|
||||
final public function route(ProxyEvent $event, $event_name, EventDispatcherInterface $dispatcher){
|
||||
|
||||
$url = $event['request']->getUri();
|
||||
|
||||
// url filter provided and current request url does not match it
|
||||
if($this->url_pattern){
|
||||
if(strpos($this->url_pattern, '/') === 0){
|
||||
if(!preg_match($this->url_pattern, $url))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(stripos($url, $this->url_pattern) === false)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch($event_name){
|
||||
|
||||
case 'request.before_send':
|
||||
$this->onBeforeRequest($event);
|
||||
break;
|
||||
|
||||
case 'request.sent':
|
||||
$this->onHeadersReceived($event);
|
||||
break;
|
||||
|
||||
case 'curl.callback.write':
|
||||
$this->onCurlWrite($event);
|
||||
break;
|
||||
|
||||
case 'request.complete':
|
||||
$this->onCompleted($event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This method returns an array indexed by event names and whose values are either the method name to call
|
||||
// or an array composed of the method name to call and a priority.
|
||||
final public static function getSubscribedEvents(){
|
||||
return array(
|
||||
'request.before_send' => 'route',
|
||||
'request.sent' => 'route',
|
||||
'curl.callback.write' => 'route',
|
||||
'request.complete' => 'route'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
57
vendor/athlon1600/php-proxy/src/Plugin/BlockListPlugin.php
vendored
Normal file
57
vendor/athlon1600/php-proxy/src/Plugin/BlockListPlugin.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
use Proxy\Config;
|
||||
|
||||
// https://proxylist.hidemyass.com/upload/
|
||||
// TODO: this file is not found to be existant in ./plugins/ when namespace is specified
|
||||
class BlockListPlugin extends AbstractPlugin {
|
||||
|
||||
function onBeforeRequest(ProxyEvent $event){
|
||||
|
||||
$user_ip = $_SERVER['REMOTE_ADDR'];
|
||||
$user_ip_long = sprintf('%u', ip2long($user_ip));
|
||||
|
||||
$url = $event['request']->getUrl();
|
||||
$url_host = parse_url($url, PHP_URL_HOST);
|
||||
|
||||
$fnc_custom = Config::get('blocklist.custom');
|
||||
if(is_callable($fnc_custom)){
|
||||
|
||||
$ret = call_user_func($fnc_custom, compact('user_ip', 'user_ip_long', 'url', 'url_host') );
|
||||
if(!$ret){
|
||||
throw new \Exception("Error: Access Denied!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Wildcard format: 1.2.3.*
|
||||
2. CIDR format: 1.2.3/24 OR 1.2.3.4/255.255.255.0
|
||||
3. Start-End IP format: 1.2.3.0-1.2.3.255
|
||||
*/
|
||||
$ip_match = false;
|
||||
$action_block = true;
|
||||
|
||||
if(Config::has('blocklist.ip_allow')){
|
||||
$ip_match = Config::get('blocklist.ip_allow');
|
||||
$action_block = false;
|
||||
} else if(Config::has('blocklist.ip_block')){
|
||||
$ip_match = Config::get('blocklist.ip_block');
|
||||
}
|
||||
|
||||
if($ip_match){
|
||||
$m = re_match($ip_match, $user_ip);
|
||||
|
||||
// ip matched and we are in block_mode
|
||||
// ip NOT matched and we are in allow mode
|
||||
if( ($m && $action_block) || (!$m && !$action_block)){
|
||||
throw new \Exception("Error: Access denied!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
132
vendor/athlon1600/php-proxy/src/Plugin/CookiePlugin.php
vendored
Normal file
132
vendor/athlon1600/php-proxy/src/Plugin/CookiePlugin.php
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
class CookiePlugin extends AbstractPlugin {
|
||||
|
||||
const COOKIE_PREFIX = 'pc';
|
||||
|
||||
public function onBeforeRequest(ProxyEvent $event){
|
||||
|
||||
$request = $event['request'];
|
||||
|
||||
// cookie sent by the browser to the server
|
||||
$http_cookie = $request->headers->get("cookie");
|
||||
|
||||
// remove old cookie header and rewrite it
|
||||
$request->headers->remove("cookie");
|
||||
|
||||
/*
|
||||
When the user agent generates an HTTP request, the user agent MUST NOT attach more than one Cookie header field.
|
||||
http://tools.ietf.org/html/rfc6265#section-5.4
|
||||
*/
|
||||
$send_cookies = array();
|
||||
|
||||
// extract "proxy cookies" only
|
||||
// A Proxy Cookie would have the following name: COOKIE_PREFIX_domain-it-belongs-to__cookie-name
|
||||
if(preg_match_all('@pc_(.+?)__(.+?)=([^;]+)@', $http_cookie, $matches, PREG_SET_ORDER)){
|
||||
|
||||
foreach($matches as $match){
|
||||
|
||||
$cookie_name = $match[2];
|
||||
$cookie_value = $match[3];
|
||||
$cookie_domain = str_replace("_", ".", $match[1]);
|
||||
|
||||
// what is the domain or our current URL?
|
||||
$host = parse_url($request->getUri(), PHP_URL_HOST);
|
||||
|
||||
// does this cookie belong to this domain?
|
||||
// sometimes domain begins with a DOT indicating all subdomains - deprecated but still in use on some servers...
|
||||
if(strpos($host, $cookie_domain) !== false){
|
||||
$send_cookies[] = $cookie_name.'='.$cookie_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do we have any cookies to send?
|
||||
if($send_cookies){
|
||||
$request->headers->set('cookie', implode("; ", $send_cookies));
|
||||
}
|
||||
}
|
||||
|
||||
// cookies received from a target server via set-cookie should be rewritten
|
||||
public function onHeadersReceived(ProxyEvent $event){
|
||||
|
||||
$request = $event['request'];
|
||||
$response = $event['response'];
|
||||
|
||||
// does the response send any cookies?
|
||||
$set_cookie = $response->headers->get('set-cookie');
|
||||
|
||||
if($set_cookie){
|
||||
|
||||
// remove set-cookie header and reconstruct it differently
|
||||
$response->headers->remove('set-cookie');
|
||||
|
||||
// loop through each set-cookie line
|
||||
foreach( (array)$set_cookie as $line){
|
||||
|
||||
// parse cookie data as array from header line
|
||||
$cookie = $this->parse_cookie($line, $request->getUri());
|
||||
|
||||
// construct a "proxy cookie" whose name includes the domain to which this cookie belongs to
|
||||
// replace dots with underscores as cookie name can only contain alphanumeric and underscore
|
||||
$cookie_name = sprintf("%s_%s__%s", self::COOKIE_PREFIX, str_replace('.', '_', $cookie['domain']), $cookie['name']);
|
||||
|
||||
// append a simple name=value cookie to the header - no expiration date means that the cookie will be a session cookie
|
||||
$event['response']->headers->set('set-cookie', $cookie_name.'='.$cookie['value'], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adapted from browserkit
|
||||
private function parse_cookie($line, $url){
|
||||
|
||||
$host = parse_url($url, PHP_URL_HOST);
|
||||
|
||||
$data = array(
|
||||
'name' => '',
|
||||
'value' => '',
|
||||
'domain' => $host,
|
||||
'path' => '/',
|
||||
'expires' => 0,
|
||||
'secure' => false,
|
||||
'httpOnly' => true
|
||||
);
|
||||
|
||||
$line = preg_replace('/^Set-Cookie2?: /i', '', trim($line));
|
||||
|
||||
// there should be at least one name=value pair
|
||||
$pairs = array_filter(array_map('trim', explode(';', $line)));
|
||||
|
||||
foreach($pairs as $index => $comp){
|
||||
|
||||
$parts = explode('=', $comp, 2);
|
||||
$key = trim($parts[0]);
|
||||
|
||||
if(count($parts) == 1){
|
||||
|
||||
// secure; HttpOnly; == 1
|
||||
$data[$key] = true;
|
||||
|
||||
} else {
|
||||
|
||||
$value = trim($parts[1]);
|
||||
|
||||
if($index == 0){
|
||||
$data['name'] = $key;
|
||||
$data['value'] = $value;
|
||||
} else {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
69
vendor/athlon1600/php-proxy/src/Plugin/HeaderRewritePlugin.php
vendored
Normal file
69
vendor/athlon1600/php-proxy/src/Plugin/HeaderRewritePlugin.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
class HeaderRewritePlugin extends AbstractPlugin {
|
||||
|
||||
function onBeforeRequest(ProxyEvent $event){
|
||||
|
||||
// tell target website that we only accept plain text without any transformations
|
||||
$event['request']->headers->set('accept-encoding', 'identity');
|
||||
|
||||
// mask proxy referer
|
||||
$event['request']->headers->remove('referer');
|
||||
}
|
||||
|
||||
function onHeadersReceived(ProxyEvent $event){
|
||||
|
||||
// so stupid... onCompleted won't be called on "streaming" responses
|
||||
$response = $event['response'];
|
||||
$request_url = $event['request']->getUri();
|
||||
|
||||
// proxify header location value
|
||||
if($response->headers->has('location')){
|
||||
|
||||
$location = $response->headers->get('location');
|
||||
|
||||
// just in case this is a relative url like: /en
|
||||
$response->headers->set('location', proxify_url($location, $request_url));
|
||||
}
|
||||
|
||||
$code = $response->getStatusCode();
|
||||
$text = $response->getStatusText();
|
||||
|
||||
if($code >= 400 && $code <= 600){
|
||||
throw new \Exception("Error accessing resource: {$code} - {$text}");
|
||||
}
|
||||
|
||||
// we need content-encoding (in case server refuses to serve it in plain text)
|
||||
// content-length: final size of content sent to user may change via plugins, so it makes no sense to send old content-length
|
||||
$forward_headers = array('content-type', 'zzzcontent-length', 'accept-ranges', 'content-range', 'content-disposition', 'location', 'set-cookie');
|
||||
|
||||
foreach($response->headers->all() as $name => $value){
|
||||
|
||||
// is this one of the headers we wish to forward back to the client?
|
||||
if(!in_array($name, $forward_headers)){
|
||||
$response->headers->remove($name);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$response->headers->has('content-disposition')){
|
||||
|
||||
$url_path = parse_url($request_url, PHP_URL_PATH);
|
||||
$filename = basename($url_path);
|
||||
|
||||
$response->headers->set('Content-Disposition', 'filename="'.$filename.'"');
|
||||
}
|
||||
|
||||
// do not ever cache our proxy pages!
|
||||
$response->headers->set("cache-control", "no-cache, no-store, must-revalidate");
|
||||
$response->headers->set("pragma", "no-cache");
|
||||
$response->headers->set("expires", 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
185
vendor/athlon1600/php-proxy/src/Plugin/ProxifyPlugin.php
vendored
Normal file
185
vendor/athlon1600/php-proxy/src/Plugin/ProxifyPlugin.php
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
use Proxy\Config;
|
||||
use Proxy\Html;
|
||||
|
||||
class ProxifyPlugin extends AbstractPlugin {
|
||||
|
||||
private $base_url = '';
|
||||
|
||||
private function css_url($matches){
|
||||
|
||||
$url = trim($matches[1]);
|
||||
|
||||
if(stripos($url, 'data:') === 0){
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
return str_replace($matches[1], proxify_url($matches[1], $this->base_url), $matches[0]);
|
||||
}
|
||||
|
||||
// this.params.logoImg&&(e="background-image: url("+this.params.logoImg+")")
|
||||
private function css_import($matches){
|
||||
return str_replace($matches[2], proxify_url($matches[2], $this->base_url), $matches[0]);
|
||||
}
|
||||
|
||||
// replace src= and href=
|
||||
private function html_attr($matches){
|
||||
|
||||
// could be empty?
|
||||
$url = trim($matches[2]);
|
||||
|
||||
if(stripos($url, 'data:') === 0 || stripos($url, 'magnet:') === 0 ){
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
return str_replace($url, proxify_url($url, $this->base_url), $matches[0]);
|
||||
}
|
||||
|
||||
private function form_action($matches){
|
||||
|
||||
// sometimes form action is empty - which means a postback to the current page
|
||||
// $matches[1] holds single or double quote - whichever was used by webmaster
|
||||
|
||||
// $matches[2] holds form submit URL - can be empty which in that case should be replaced with current URL
|
||||
if(!$matches[2]){
|
||||
$matches[2] = $this->base_url;
|
||||
}
|
||||
|
||||
$new_action = proxify_url($matches[2], $this->base_url);
|
||||
|
||||
// what is form method?
|
||||
$form_post = preg_match('@method=(["\'])post\1@i', $matches[0]) == 1;
|
||||
|
||||
// take entire form string - find real url and replace it with proxified url
|
||||
$result = str_replace($matches[2], $new_action, $matches[0]);
|
||||
|
||||
// must be converted to POST otherwise GET form would just start appending name=value pairs to your proxy url
|
||||
if(!$form_post){
|
||||
|
||||
// may throw Duplicate Attribute warning but only first method matters
|
||||
$result = str_replace("<form", '<form method="POST"', $result);
|
||||
|
||||
// got the idea from Glype - insert this input field to notify proxy later that this form must be converted to GET during http
|
||||
$result .= '<input type="hidden" name="convertGET" value="1">';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function onBeforeRequest(ProxyEvent $event){
|
||||
|
||||
$request = $event['request'];
|
||||
|
||||
// check if one of the POST pairs is convertGET - if so, convert this request to GET
|
||||
if($request->post->has('convertGET')){
|
||||
|
||||
// we don't need this parameter anymore
|
||||
$request->post->remove('convertGET');
|
||||
|
||||
// replace all GET parameters with POST data
|
||||
$request->get->replace($request->post->all());
|
||||
|
||||
// remove POST data
|
||||
$request->post->clear();
|
||||
|
||||
// This is now a GET request
|
||||
$request->setMethod('GET');
|
||||
|
||||
$request->prepare();
|
||||
}
|
||||
}
|
||||
|
||||
private function meta_refresh($matches){
|
||||
$url = $matches[2];
|
||||
return str_replace($url, proxify_url($url, $this->base_url), $matches[0]);
|
||||
}
|
||||
|
||||
// <title>, <base>, <link>, <style>, <meta>, <script>, <noscript>
|
||||
private function proxify_head($str){
|
||||
|
||||
// let's replace page titles with something custom
|
||||
if(Config::get('replace_title')){
|
||||
$str = preg_replace('/<title[^>]*>(.*?)<\/title>/is', '<title>'.Config::get('replace_title').'</title>', $str);
|
||||
}
|
||||
|
||||
|
||||
// base - update base_url contained in href - remove <base> tag entirely
|
||||
//$str = preg_replace_callback('/<base[^>]*href=
|
||||
|
||||
// link - replace href with proxified
|
||||
// link rel="shortcut icon" - replace or remove
|
||||
|
||||
// meta - only interested in http-equiv - replace url refresh
|
||||
// <meta http-equiv="refresh" content="5; url=http://example.com/">
|
||||
$str = preg_replace_callback('/content=(["\'])\d+\s*;\s*url=(.*?)\1/is', array($this, 'meta_refresh'), $str);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
// The <body> background attribute is not supported in HTML5. Use CSS instead.
|
||||
private function proxify_css($str){
|
||||
|
||||
// The HTML5 standard does not require quotes around attribute values.
|
||||
|
||||
// if {1} is not there then youtube breaks for some reason
|
||||
$str = preg_replace_callback('@[^a-z]{1}url\s*\((?:\'|"|)(.*?)(?:\'|"|)\)@im', array($this, 'css_url'), $str);
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/@import
|
||||
// TODO: what about @import directives that are outside <style>?
|
||||
$str = preg_replace_callback('/@import (\'|")(.*?)\1/i', array($this, 'css_import'), $str);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
|
||||
// to be used when proxifying all the relative links
|
||||
$this->base_url = $event['request']->getUri();
|
||||
|
||||
$response = $event['response'];
|
||||
$content_type = $response->headers->get('content-type');
|
||||
|
||||
$str = $response->getContent();
|
||||
|
||||
// DO NOT do any proxification on .js files and text/plain content type
|
||||
if($content_type == 'text/javascript' || $content_type == 'application/javascript' || $content_type == 'application/x-javascript' || $content_type == 'text/plain'){
|
||||
return;
|
||||
}
|
||||
|
||||
// remove JS from urls
|
||||
$js_remove = Config::get('js_remove');
|
||||
if(is_array($js_remove)){
|
||||
$domain = parse_url($this->base_url, PHP_URL_HOST);
|
||||
|
||||
foreach($js_remove as $pattern){
|
||||
if(strpos($domain, $pattern) !== false){
|
||||
$str = Html::remove_scripts($str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add html.no-js
|
||||
|
||||
// let's remove all frames?? does not protect against the frames created dynamically via javascript
|
||||
$str = preg_replace('@<iframe[^>]*>[^<]*<\\/iframe>@is', '', $str);
|
||||
|
||||
$str = $this->proxify_head($str);
|
||||
$str = $this->proxify_css($str);
|
||||
|
||||
// src= and href=
|
||||
$str = preg_replace_callback('@(?:src|href)\s*=\s*(["|\'])(.*?)\1@is', array($this, 'html_attr'), $str);
|
||||
|
||||
// form
|
||||
$str = preg_replace_callback('@<form[^>]*action=(["\'])(.*?)\1[^>]*>@i', array($this, 'form_action'), $str);
|
||||
|
||||
$response->setContent($str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
57
vendor/athlon1600/php-proxy/src/Plugin/StreamPlugin.php
vendored
Normal file
57
vendor/athlon1600/php-proxy/src/Plugin/StreamPlugin.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
// do not buffer certain responses... echo contents immediately, and exit when done
|
||||
class StreamPlugin extends AbstractPlugin {
|
||||
|
||||
// stream: Set to true to stream a response body rather than download it all up front
|
||||
private $output_buffer_types = array('text/html', 'text/plain', 'text/css', 'text/javascript', 'application/x-javascript', 'application/javascript');
|
||||
private $stream = false;
|
||||
|
||||
// we stream response as it is received if its content length exceeds 5 megabytes
|
||||
private $max_content_length = 5000000;
|
||||
|
||||
public function onHeadersReceived(ProxyEvent $event){
|
||||
|
||||
// what content type are we dealing with here? can be empty
|
||||
$content_type = $event['response']->headers->get('content-type');
|
||||
$content_type = clean_content_type($content_type);
|
||||
|
||||
// how big of data can we expect?
|
||||
$content_length = $event['response']->headers->get('content-length');
|
||||
|
||||
// we stream if content is not of "text" content-type or if its size exceeds 5 megabytes
|
||||
if(!in_array($content_type, $this->output_buffer_types) || $content_length > $this->max_content_length){
|
||||
|
||||
$this->stream = true;
|
||||
$event['response']->sendHeaders();
|
||||
|
||||
// it is of no use for us to buffer the data since we're sending it out immediately, but sometimes we must do both, hence the parameter
|
||||
if(!$event['request']->params->has('force_buffering')){
|
||||
$event['proxy']->setOutputBuffering(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onCurlWrite(ProxyEvent $event){
|
||||
|
||||
if($this->stream){
|
||||
echo $event['data'];
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
|
||||
// if this was a streaming response then exit the script immediately since we do not wish to process it any futher
|
||||
if($this->stream){
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
168
vendor/athlon1600/php-proxy/src/Proxy.php
vendored
Normal file
168
vendor/athlon1600/php-proxy/src/Proxy.php
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\GenericEvent;
|
||||
|
||||
use Proxy\Config;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
use Proxy\Http\Request;
|
||||
use Proxy\Http\Response;
|
||||
|
||||
class Proxy {
|
||||
|
||||
// proxy version!
|
||||
const VERSION = '5.0.1';
|
||||
|
||||
private $dispatcher;
|
||||
|
||||
private $request;
|
||||
private $response;
|
||||
|
||||
private $output_buffering = true;
|
||||
private $output_buffer = '';
|
||||
|
||||
private $status_found = false;
|
||||
|
||||
public function __construct(){
|
||||
$this->dispatcher = new EventDispatcher();
|
||||
}
|
||||
|
||||
public function setOutputBuffering($output_buffering){
|
||||
$this->output_buffering = $output_buffering;
|
||||
}
|
||||
|
||||
private function header_callback($ch, $headers){
|
||||
|
||||
$parts = explode(":", $headers, 2);
|
||||
|
||||
// extract status code
|
||||
// if using proxy - we ignore this header: HTTP/1.1 200 Connection established
|
||||
if(preg_match('/HTTP\/1.\d+ (\d+)/', $headers, $matches) && stripos($headers, '200 Connection established') === false){
|
||||
|
||||
$this->response->setStatusCode($matches[1]);
|
||||
$this->status_found = true;
|
||||
|
||||
} else if(count($parts) == 2){
|
||||
|
||||
$name = strtolower($parts[0]);
|
||||
$value = trim($parts[1]);
|
||||
|
||||
// this must be a header: value line
|
||||
$this->response->headers->set($name, $value, false);
|
||||
|
||||
} else if($this->status_found){
|
||||
|
||||
// this is hacky but until anyone comes up with a better way...
|
||||
$event = new ProxyEvent(array('request' => $this->request, 'response' => $this->response, 'proxy' => &$this));
|
||||
|
||||
// this is the end of headers - last line is always empty - notify the dispatcher about this
|
||||
$this->dispatcher->dispatch('request.sent', $event);
|
||||
}
|
||||
|
||||
return strlen($headers);
|
||||
}
|
||||
|
||||
private function write_callback($ch, $str){
|
||||
|
||||
$len = strlen($str);
|
||||
|
||||
$this->dispatcher->dispatch('curl.callback.write', new ProxyEvent(array(
|
||||
'request' => $this->request,
|
||||
'data' => $str
|
||||
)));
|
||||
|
||||
// Do we buffer this piece of data for later output or not?
|
||||
if($this->output_buffering){
|
||||
$this->output_buffer .= $str;
|
||||
}
|
||||
|
||||
return $len;
|
||||
}
|
||||
|
||||
public function getEventDispatcher(){
|
||||
return $this->dispatcher;
|
||||
}
|
||||
|
||||
public function forward(Request $request, $url){
|
||||
|
||||
// change request URL
|
||||
$request->setUrl($url);
|
||||
|
||||
// prepare request and response objects
|
||||
$this->request = $request;
|
||||
$this->response = new Response();
|
||||
|
||||
$options = array(
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_TIMEOUT => 0,
|
||||
|
||||
// don't return anything - we have other functions for that
|
||||
CURLOPT_RETURNTRANSFER => false,
|
||||
CURLOPT_HEADER => false,
|
||||
|
||||
// don't bother with ssl
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_SSL_VERIFYHOST => false,
|
||||
|
||||
// we will take care of redirects
|
||||
CURLOPT_FOLLOWLOCATION => false,
|
||||
CURLOPT_AUTOREFERER => false
|
||||
);
|
||||
|
||||
// this is probably a good place to add custom curl options that way other critical options below would overwrite that
|
||||
$config_options = Config::get('curl', array());
|
||||
|
||||
$options = array_merge_custom($options, $config_options);
|
||||
|
||||
$options[CURLOPT_HEADERFUNCTION] = array($this, 'header_callback');
|
||||
$options[CURLOPT_WRITEFUNCTION] = array($this, 'write_callback');
|
||||
|
||||
// Notify any listeners that the request is ready to be sent, and this is your last chance to make any modifications.
|
||||
$this->dispatcher->dispatch('request.before_send', new ProxyEvent(array('request' => $this->request, 'response' => $this->response)));
|
||||
|
||||
// We may not even need to send this request if response is already available somewhere (CachePlugin)
|
||||
if($this->request->params->has('request.complete')){
|
||||
|
||||
// do nothing?
|
||||
} else {
|
||||
|
||||
// any plugin might have changed our URL by this point
|
||||
$options[CURLOPT_URL] = $this->request->getUri();
|
||||
|
||||
// fill in the rest of cURL options
|
||||
$options[CURLOPT_HTTPHEADER] = explode("\r\n", $this->request->getRawHeaders());
|
||||
$options[CURLOPT_CUSTOMREQUEST] = $this->request->getMethod();
|
||||
$options[CURLOPT_POSTFIELDS] = $this->request->getRawBody();
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, $options);
|
||||
|
||||
// fetch the status - if exception if throw any at callbacks, then the error will be supressed
|
||||
$result = @curl_exec($ch);
|
||||
|
||||
// there must have been an error if at this point
|
||||
if(!$result){
|
||||
|
||||
$error = sprintf('(%d) %s', curl_errno($ch), curl_error($ch));
|
||||
|
||||
throw new \Exception($error);
|
||||
}
|
||||
|
||||
// we have output waiting in the buffer?
|
||||
$this->response->setContent($this->output_buffer);
|
||||
|
||||
// saves memory I would assume?
|
||||
$this->output_buffer = null;
|
||||
}
|
||||
|
||||
$this->dispatcher->dispatch('request.complete', new ProxyEvent(array('request' => $this->request, 'response' => $this->response)));
|
||||
|
||||
return $this->response;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
30
vendor/athlon1600/php-proxy/src/Redis.php
vendored
Normal file
30
vendor/athlon1600/php-proxy/src/Redis.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy;
|
||||
|
||||
class Redis {
|
||||
|
||||
protected static $client;
|
||||
|
||||
public function __construct(){
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public static function __callStatic($method_name, $arguments){
|
||||
|
||||
$params = array(
|
||||
'scheme' => 'tcp',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
);
|
||||
|
||||
if(!static::$client){
|
||||
static::$client = new \Predis\Client($params);
|
||||
}
|
||||
|
||||
return call_user_func_array(array(static::$client, $method_name), $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
199
vendor/athlon1600/php-proxy/src/helpers.php
vendored
Normal file
199
vendor/athlon1600/php-proxy/src/helpers.php
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
use Proxy\Config;
|
||||
|
||||
// strip away extra parameters text/html; charset=UTF-8
|
||||
function clean_content_type($content_type){
|
||||
return trim(preg_replace('@;.*@', '', $content_type));
|
||||
}
|
||||
|
||||
function is_html($content_type){
|
||||
return clean_content_type($content_type) == 'text/html';
|
||||
}
|
||||
|
||||
function in_arrayi($needle, $haystack){
|
||||
return in_array(strtolower($needle), array_map('strtolower', $haystack));
|
||||
}
|
||||
|
||||
function re_match($pattern, $string){
|
||||
|
||||
$quoted = preg_quote($pattern, '#');
|
||||
$translated = strtr($quoted, array(
|
||||
'\*' => '.*',
|
||||
'\?' => '.'
|
||||
));
|
||||
|
||||
return preg_match("#^".$translated."$#i", $string) === 1;
|
||||
}
|
||||
|
||||
// regular array_merge does not work if arrays have numeric keys...
|
||||
function array_merge_custom(){
|
||||
|
||||
$arr = array();
|
||||
$args = func_get_args();
|
||||
|
||||
foreach( (array)$args as $arg){
|
||||
foreach( (array)$arg as $key => $value){
|
||||
$arr[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
// rotate each string character based on corresponding ascii values from some key
|
||||
function str_rot_pass($str, $key, $decrypt = false){
|
||||
|
||||
// if key happens to be shorter than the data
|
||||
$key_len = strlen($key);
|
||||
|
||||
$result = str_repeat(' ', strlen($str));
|
||||
|
||||
for($i=0; $i<strlen($str); $i++){
|
||||
|
||||
if($decrypt){
|
||||
$ascii = ord($str[$i]) - ord($key[$i % $key_len]);
|
||||
} else {
|
||||
$ascii = ord($str[$i]) + ord($key[$i % $key_len]);
|
||||
}
|
||||
|
||||
$result[$i] = chr($ascii);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function app_url(){
|
||||
return (!empty($_SERVER['HTTPS']) ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
|
||||
}
|
||||
|
||||
function render_string($str, $vars = array()){
|
||||
|
||||
preg_match_all('@{([a-z0-9_]+)}@s', $str, $matches, PREG_SET_ORDER);
|
||||
|
||||
foreach($matches as $match){
|
||||
|
||||
extract($vars, EXTR_PREFIX_ALL, "_var");
|
||||
|
||||
$var_val = ${"_var_".$match[1]};
|
||||
|
||||
$str = str_replace($match[0], $var_val, $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
function render_template($file_path, $vars = array()){
|
||||
|
||||
// variables to be used within that template
|
||||
extract($vars);
|
||||
|
||||
ob_start();
|
||||
|
||||
if(file_exists($file_path)){
|
||||
include($file_path);
|
||||
} else {
|
||||
die("Failed to load template: {$file_path}");
|
||||
}
|
||||
|
||||
$contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
function add_http($url){
|
||||
|
||||
if(!preg_match('#^https?://#i', $url)){
|
||||
$url = 'http://' . $url;
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
function time_ms(){
|
||||
return round(microtime(true) * 1000);
|
||||
}
|
||||
|
||||
function base64_url_encode($input){
|
||||
// = at the end is just padding to make the length of the str divisible by 4
|
||||
return rtrim(strtr(base64_encode($input), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
function base64_url_decode($input){
|
||||
return base64_decode(str_pad(strtr($input, '-_', '+/'), strlen($input) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
||||
|
||||
function url_encrypt($url, $key = false){
|
||||
|
||||
if($key){
|
||||
$url = str_rot_pass($url, $key);
|
||||
} else if(Config::get('encryption_key')){
|
||||
$url = str_rot_pass($url, Config::get('encryption_key'));
|
||||
}
|
||||
|
||||
return Config::get('url_mode') ? base64_url_encode($url) : rawurlencode($url);
|
||||
}
|
||||
|
||||
function url_decrypt($url, $key = false){
|
||||
|
||||
$url = Config::get('url_mode') ? base64_url_decode($url) : rawurldecode($url);
|
||||
|
||||
if($key){
|
||||
$url = str_rot_pass($url, $key, true);
|
||||
} else if(Config::get('encryption_key')){
|
||||
$url = str_rot_pass($url, Config::get('encryption_key'), true);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
// www.youtube.com TO proxy-app.com/index.php?q=encrypt_url(www.youtube.com)
|
||||
function proxify_url($url, $base_url = ''){
|
||||
|
||||
$url = htmlspecialchars_decode($url);
|
||||
|
||||
if($base_url){
|
||||
$base_url = add_http($base_url);
|
||||
$url = rel2abs($url, $base_url);
|
||||
}
|
||||
|
||||
return app_url().'?q='.url_encrypt($url);
|
||||
}
|
||||
|
||||
function rel2abs($rel, $base)
|
||||
{
|
||||
if (strpos($rel, "//") === 0) {
|
||||
return "http:" . $rel;
|
||||
}
|
||||
|
||||
if($rel == ""){
|
||||
return "";
|
||||
}
|
||||
|
||||
/* return if already absolute URL */
|
||||
if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;
|
||||
/* queries and anchors */
|
||||
if ($rel[0] == '#' || $rel[0] == '?') return $base . $rel;
|
||||
/* parse base URL and convert to local variables:
|
||||
$scheme, $host, $path */
|
||||
extract(parse_url($base));
|
||||
/* remove non-directory element from path */
|
||||
@$path = preg_replace('#/[^/]*$#', '', $path);
|
||||
/* destroy path if relative url points to root */
|
||||
if ($rel[0] == '/') $path = '';
|
||||
/* dirty absolute URL */
|
||||
$abs = "$host$path/$rel";
|
||||
/* replace '//' or '/./' or '/foo/../' with '/' */
|
||||
$re = array(
|
||||
'#(/\.?/)#',
|
||||
'#/(?!\.\.)[^/]+/\.\./#'
|
||||
);
|
||||
for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {
|
||||
}
|
||||
|
||||
/* absolute URL is ready! */
|
||||
return $scheme . '://' . $abs;
|
||||
}
|
||||
|
||||
?>
|
21
vendor/athlon1600/youtube-downloader/LICENSE
vendored
Normal file
21
vendor/athlon1600/youtube-downloader/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
81
vendor/athlon1600/youtube-downloader/README.md
vendored
Normal file
81
vendor/athlon1600/youtube-downloader/README.md
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
# youtube-downloader
|
||||
|
||||
This project was inspired by a very popular youtube-dl python package:
|
||||
https://github.com/rg3/youtube-dl
|
||||
|
||||
Yes, there are multiple PHP-based youtube downloaders on the Internet, but all of them haven't been updated in years or they depend on youtube-dl.
|
||||
|
||||
This script does not depend on anything other than cURL. No Javascript interpreters, no calls to shell... nothing but pure PHP.
|
||||
|
||||
Demo
|
||||
------
|
||||
|
||||
Just to prove its reliability and the fact that it works even with YouTube videos that encrypt their signature, visit this URL:
|
||||
|
||||
https://api.unblockvideos.com/youtube_downloader?id=e-ORhEE9VVg&selector=mp4
|
||||
|
||||
Or stream it directly:
|
||||
|
||||
https://api.unblockvideos.com/youtube_downloader?id=e-ORhEE9VVg&selector=mp4&redirect=true
|
||||
|
||||
|
||||
Installation
|
||||
-------
|
||||
|
||||
Recommended way of installing this is via [Composer](http://getcomposer.org):
|
||||
|
||||
```bash
|
||||
composer require athlon1600/youtube-downloader
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
|
||||
```php
|
||||
$yt = new YouTubeDownloader();
|
||||
|
||||
$links = $yt->getDownloadLinks("https://www.youtube.com/watch?v=QxsmWxxouIM");
|
||||
|
||||
var_dump($links);
|
||||
```
|
||||
|
||||
Result:
|
||||
```php
|
||||
array(5) {
|
||||
[22]=>
|
||||
array(2) {
|
||||
["url"]=>
|
||||
string(670) "https://r3---sn-vgqs7ney.googlevideo.com/videoplayback?ratebypass=yes&requiressl=yes&initcwndbps=1142500&nh=IgpwZjAxLm9yZDM1Kg42Ni4yMDguMjI4LjIwMQ&key=yt6&mime=video%2Fmp4&mn=sn-vgqs7ney&mm=31&id=o-APybfQxBq_Uf0UwtAWdBuT2hoXzus5lvuXnd9VSmh5Dl&ip=67.184.200.25&gcr=us&sparams=dur%2Cei%2Cgcr%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cupn%2Cexpire&mt=1482861742&ms=au&pl=16&itag=22&ei=Fq1iWM-PIsLyugLMor-gBA&mv=m&source=youtube&upn=pDkyvSW9InM&dur=265.357&ipbits=0&expire=1482883446&lmt=1478829845344913&signature=A27686411B20AD4EB61A29BC695509DB4D003681.9AE606614F809319EEE0B230BFCEFD09F5C39E12"
|
||||
["format"]=>
|
||||
string(13) "MP4 720p (HD)"
|
||||
}
|
||||
[43]=>
|
||||
array(2) {
|
||||
["url"]=>
|
||||
string(704) "https://r3---sn-vgqs7ney.googlevideo.com/videoplayback?ratebypass=yes&requiressl=yes&initcwndbps=1142500&nh=IgpwZjAxLm9yZDM1Kg42Ni4yMDguMjI4LjIwMQ&key=yt6&gir=yes&mime=video%2Fwebm&mn=sn-vgqs7ney&mm=31&id=o-APybfQxBq_Uf0UwtAWdBuT2hoXzus5lvuXnd9VSmh5Dl&clen=23934795&ip=67.184.200.25&gcr=us&sparams=clen%2Cdur%2Cei%2Cgcr%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cupn%2Cexpire&mt=1482861742&ms=au&pl=16&itag=43&ei=Fq1iWM-PIsLyugLMor-gBA&mv=m&source=youtube&upn=pDkyvSW9InM&dur=0.000&ipbits=0&expire=1482883446&lmt=1466552369088504&signature=4A9B43F989EF4DB937C56AC889BF9AFAA1363439.87B358B93A19E3C292BE823A2E7FD505E527956C"
|
||||
["format"]=>
|
||||
string(9) "WebM 360p"
|
||||
}
|
||||
[18]=>
|
||||
array(2) {
|
||||
["url"]=>
|
||||
string(705) "https://r3---sn-vgqs7ney.googlevideo.com/videoplayback?ratebypass=yes&requiressl=yes&initcwndbps=1142500&nh=IgpwZjAxLm9yZDM1Kg42Ni4yMDguMjI4LjIwMQ&key=yt6&gir=yes&mime=video%2Fmp4&mn=sn-vgqs7ney&mm=31&id=o-APybfQxBq_Uf0UwtAWdBuT2hoXzus5lvuXnd9VSmh5Dl&clen=18431345&ip=67.184.200.25&gcr=us&sparams=clen%2Cdur%2Cei%2Cgcr%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cupn%2Cexpire&mt=1482861742&ms=au&pl=16&itag=18&ei=Fq1iWM-PIsLyugLMor-gBA&mv=m&source=youtube&upn=pDkyvSW9InM&dur=265.357&ipbits=0&expire=1482883446&lmt=1478827692757115&signature=0C2203FABCEBC01A0B154C109EA7A03EBB778A17.7FFE657A41B06ABB4729E03253A92E1AA5562D3E"
|
||||
["format"]=>
|
||||
string(8) "MP4 360p"
|
||||
}
|
||||
[36]=>
|
||||
array(2) {
|
||||
["url"]=>
|
||||
string(677) "https://r3---sn-vgqs7ney.googlevideo.com/videoplayback?requiressl=yes&initcwndbps=1142500&nh=IgpwZjAxLm9yZDM1Kg42Ni4yMDguMjI4LjIwMQ&key=yt6&gir=yes&mime=video%2F3gpp&mn=sn-vgqs7ney&mm=31&id=o-APybfQxBq_Uf0UwtAWdBuT2hoXzus5lvuXnd9VSmh5Dl&clen=7400500&ip=67.184.200.25&gcr=us&sparams=clen%2Cdur%2Cei%2Cgcr%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Crequiressl%2Csource%2Cupn%2Cexpire&mt=1482861742&ms=au&pl=16&itag=36&ei=Fq1iWM-PIsLyugLMor-gBA&mv=m&source=youtube&upn=pDkyvSW9InM&dur=265.404&ipbits=0&expire=1482883446&lmt=1466551971126275&signature=121F4D6F18C10D31951E2C2A857E52351BCC1A8C.B6EFCCB6734190053A0F3980FC67D3E508EA30FF"
|
||||
["format"]=>
|
||||
string(7) "Unknown"
|
||||
}
|
||||
[17]=>
|
||||
array(2) {
|
||||
["url"]=>
|
||||
string(677) "https://r3---sn-vgqs7ney.googlevideo.com/videoplayback?requiressl=yes&initcwndbps=1142500&nh=IgpwZjAxLm9yZDM1Kg42Ni4yMDguMjI4LjIwMQ&key=yt6&gir=yes&mime=video%2F3gpp&mn=sn-vgqs7ney&mm=31&id=o-APybfQxBq_Uf0UwtAWdBuT2hoXzus5lvuXnd9VSmh5Dl&clen=2661359&ip=67.184.200.25&gcr=us&sparams=clen%2Cdur%2Cei%2Cgcr%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Crequiressl%2Csource%2Cupn%2Cexpire&mt=1482861742&ms=au&pl=16&itag=17&ei=Fq1iWM-PIsLyugLMor-gBA&mv=m&source=youtube&upn=pDkyvSW9InM&dur=265.404&ipbits=0&expire=1482883446&lmt=1466551946325771&signature=9C0017C6EE3EC754BCB73E4546483807143CC495.A738E50D2B2C9073E9369A8828BA780B6BA453F7"
|
||||
["format"]=>
|
||||
string(8) "3GP 144p"
|
||||
}
|
||||
}
|
||||
```
|
14
vendor/athlon1600/youtube-downloader/composer.json
vendored
Normal file
14
vendor/athlon1600/youtube-downloader/composer.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "athlon1600/youtube-downloader",
|
||||
"description": "PHP powered alternative for youtube-dl",
|
||||
"keywords": ["youtube downloader", "download youtube", "download youtube videos"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/YouTubeDownloader.php"
|
||||
]
|
||||
}
|
||||
}
|
388
vendor/athlon1600/youtube-downloader/src/YouTubeDownloader.php
vendored
Normal file
388
vendor/athlon1600/youtube-downloader/src/YouTubeDownloader.php
vendored
Normal file
@ -0,0 +1,388 @@
|
||||
<?php
|
||||
|
||||
// utils.php
|
||||
function sig_js_decode($player_html){
|
||||
|
||||
// what javascript function is responsible for signature decryption?
|
||||
// var l=f.sig||Xn(f.s)
|
||||
// a.set("signature",Xn(c));return a
|
||||
if(preg_match('/signature",([a-zA-Z0-9$]+)\(/', $player_html, $matches)){
|
||||
|
||||
$func_name = $matches[1];
|
||||
$func_name = preg_quote($func_name);
|
||||
|
||||
// extract code block from that function
|
||||
// single quote in case function name contains $dollar sign
|
||||
// xm=function(a){a=a.split("");wm.zO(a,47);wm.vY(a,1);wm.z9(a,68);wm.zO(a,21);wm.z9(a,34);wm.zO(a,16);wm.z9(a,41);return a.join("")};
|
||||
if(preg_match('/'.$func_name.'=function\([a-z]+\){(.*?)}/', $player_html, $matches)){
|
||||
|
||||
$js_code = $matches[1];
|
||||
|
||||
// extract all relevant statements within that block
|
||||
// wm.vY(a,1);
|
||||
if(preg_match_all('/([a-z0-9]{2})\.([a-z0-9]{2})\([^,]+,(\d+)\)/i', $js_code, $matches) != false){
|
||||
|
||||
// must be identical
|
||||
$obj_list = $matches[1];
|
||||
|
||||
//
|
||||
$func_list = $matches[2];
|
||||
|
||||
// extract javascript code for each one of those statement functions
|
||||
preg_match_all('/('.implode('|', $func_list).'):function(.*?)\}/m', $player_html, $matches2, PREG_SET_ORDER);
|
||||
|
||||
$functions = array();
|
||||
|
||||
// translate each function according to its use
|
||||
foreach($matches2 as $m){
|
||||
|
||||
if(strpos($m[2], 'splice') !== false){
|
||||
$functions[$m[1]] = 'splice';
|
||||
} else if(strpos($m[2], 'a.length') !== false){
|
||||
$functions[$m[1]] = 'swap';
|
||||
} else if(strpos($m[2], 'reverse') !== false){
|
||||
$functions[$m[1]] = 'reverse';
|
||||
}
|
||||
}
|
||||
|
||||
// FINAL STEP! convert it all to instructions set
|
||||
$instructions = array();
|
||||
|
||||
foreach($matches[2] as $index => $name){
|
||||
$instructions[] = array($functions[$name], $matches[3][$index]);
|
||||
}
|
||||
|
||||
return $instructions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// YouTube is capitalized twice because that's how youtube itself does it:
|
||||
// https://developers.google.com/youtube/v3/code_samples/php
|
||||
class YouTubeDownloader {
|
||||
|
||||
private $storage_dir;
|
||||
private $cookie_dir;
|
||||
|
||||
private $itag_info = array(
|
||||
|
||||
18 => "MP4 360p",
|
||||
22 => "MP4 720p (HD)",
|
||||
37 => "MP4 1080",
|
||||
38 => "MP4 3072p",
|
||||
|
||||
// questionable MP4s
|
||||
59 => "MP4 480p",
|
||||
78 => "MP4 480p",
|
||||
|
||||
43 => "WebM 360p",
|
||||
|
||||
17 => "3GP 144p"
|
||||
);
|
||||
|
||||
function __construct(){
|
||||
$this->storage_dir = sys_get_temp_dir();
|
||||
$this->cookie_dir = sys_get_temp_dir();
|
||||
}
|
||||
|
||||
function setStorageDir($dir){
|
||||
$this->storage_dir = $dir;
|
||||
}
|
||||
|
||||
// what identifies each request? user agent, cookies...
|
||||
public function curl($url){
|
||||
|
||||
$ch = curl_init($url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
|
||||
//curl_setopt($ch, CURLOPT_COOKIEJAR, $tmpfname);
|
||||
//curl_setopt($ch, CURLOPT_COOKIEFILE, $tmpfname);
|
||||
|
||||
//curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function head($url){
|
||||
|
||||
$ch = curl_init($url);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
|
||||
curl_setopt($ch, CURLOPT_NOBODY, 1);
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return http_parse_headers($result);
|
||||
}
|
||||
|
||||
// html code of watch?v=aaa
|
||||
private function getInstructions($html){
|
||||
|
||||
// <script src="//s.ytimg.com/yts/jsbin/player-fr_FR-vflHVjlC5/base.js" name="player/base"></script>
|
||||
|
||||
// check what player version that video is using
|
||||
if(preg_match('@<script\s*src="([^"]+player[^"]+js)@', $html, $matches)){
|
||||
|
||||
$player_url = $matches[1];
|
||||
|
||||
// relative protocol?
|
||||
if(strpos($player_url, '//') === 0){
|
||||
$player_url = 'http://'.substr($player_url, 2);
|
||||
} else if(strpos($player_url, '/') === 0){
|
||||
// relative path?
|
||||
$player_url = 'http://www.youtube.com'.$player_url;
|
||||
}
|
||||
|
||||
// try to find instructions list already cached from previous requests...
|
||||
$file_path = $this->storage_dir.'/'.md5($player_url);
|
||||
|
||||
if(file_exists($file_path)){
|
||||
|
||||
// unserialize could fail on empty file
|
||||
$str = file_get_contents($file_path);
|
||||
return unserialize($str);
|
||||
|
||||
} else {
|
||||
|
||||
$js_code = $this->curl($player_url);
|
||||
$instructions = sig_js_decode($js_code);
|
||||
|
||||
if($instructions){
|
||||
file_put_contents($file_path, serialize($instructions));
|
||||
return $instructions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is in beta mode!!
|
||||
public function stream($id){
|
||||
|
||||
$links = $this->getDownloadLinks($id, "mp4");
|
||||
|
||||
if(count($links) == 0){
|
||||
die("no url found!");
|
||||
}
|
||||
|
||||
// grab first available MP4 link
|
||||
$url = $links[0]['url'];
|
||||
|
||||
// request headers
|
||||
$headers = array(
|
||||
'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0'
|
||||
);
|
||||
|
||||
if(isset($_SERVER['HTTP_RANGE'])){
|
||||
$headers[] = 'Range: '.$_SERVER['HTTP_RANGE'];
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
|
||||
|
||||
// we deal with this ourselves
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
|
||||
// whether request to video success
|
||||
$headers = '';
|
||||
$headers_sent = false;
|
||||
$success = false;
|
||||
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($ch, $data) use (&$headers, &$headers_sent){
|
||||
|
||||
$headers .= $data;
|
||||
|
||||
// this should be first line
|
||||
if(preg_match('@HTTP\/\d\.\d\s(\d+)@', $data, $matches)){
|
||||
$status_code = $matches[1];
|
||||
|
||||
// status=ok or partial content
|
||||
if($status_code == 200 || $status_code == 206){
|
||||
$headers_sent = true;
|
||||
header(rtrim($data));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// only headers we wish to forward back to the client
|
||||
$forward = array('content-type', 'content-length', 'accept-ranges', 'content-range');
|
||||
|
||||
$parts = explode(':', $data, 2);
|
||||
|
||||
if($headers_sent && count($parts) == 2 && in_array(trim(strtolower($parts[0])), $forward)){
|
||||
header(rtrim($data));
|
||||
}
|
||||
}
|
||||
|
||||
return strlen($data);
|
||||
});
|
||||
|
||||
// if response is empty - this never gets called
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use (&$headers_sent){
|
||||
|
||||
if($headers_sent){
|
||||
echo $data;
|
||||
flush();
|
||||
}
|
||||
|
||||
return strlen($data);
|
||||
});
|
||||
|
||||
$ret = @curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// if we are still here by now, return status_code
|
||||
return true;
|
||||
}
|
||||
|
||||
// extract youtube video_id from any piece of text
|
||||
public function extractId($str){
|
||||
|
||||
if(preg_match('/[a-z0-9_-]{11}/i', $str, $matches)){
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// selector by format: mp4 360,
|
||||
private function selectFirst($links, $selector){
|
||||
|
||||
$result = array();
|
||||
$formats = preg_split('/\s*,\s*/', $selector);
|
||||
|
||||
// has to be in this order
|
||||
foreach($formats as $f){
|
||||
|
||||
foreach($links as $l){
|
||||
|
||||
if(stripos($l['format'], $f) !== false || $f == 'any'){
|
||||
$result[] = $l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// options | deep_links | append_redirector
|
||||
public function getDownloadLinks($id, $selector = false){
|
||||
|
||||
$result = array();
|
||||
$instructions = array();
|
||||
|
||||
// you can input HTML of /watch? page directory instead of id
|
||||
if(strpos($id, '<div id="player') !== false){
|
||||
$html = $id;
|
||||
} else {
|
||||
$video_id = $this->extractId($id);
|
||||
|
||||
if(!$video_id){
|
||||
return false;
|
||||
}
|
||||
|
||||
$html = $this->curl("https://www.youtube.com/watch?v={$video_id}");
|
||||
}
|
||||
|
||||
// age-gate
|
||||
if(strpos($html, 'player-age-gate-content') !== false){
|
||||
// nothing you can do folks...
|
||||
return false;
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/35608686/how-can-i-get-the-actual-video-url-of-a-youtube-live-stream
|
||||
if(preg_match('@url_encoded_fmt_stream_map["\']:\s*["\']([^"\'\s]*)@', $html, $matches)){
|
||||
|
||||
$parts = explode(",", $matches[1]);
|
||||
|
||||
foreach($parts as $p){
|
||||
$query = str_replace('\u0026', '&', $p);
|
||||
parse_str($query, $arr);
|
||||
|
||||
$url = $arr['url'];
|
||||
|
||||
if(isset($arr['sig'])){
|
||||
$url = $url.'&signature='.$arr['sig'];
|
||||
|
||||
} else if(isset($arr['signature'])){
|
||||
$url = $url.'&signature='.$arr['signature'];
|
||||
|
||||
} else if(isset($arr['s'])){
|
||||
|
||||
// this is probably a VEVO/ads video... signature must be decrypted first! We need instructions for doing that
|
||||
if(count($instructions) == 0){
|
||||
$instructions = (array)$this->getInstructions($html);
|
||||
}
|
||||
|
||||
$dec = $this->sig_decipher($arr['s'], $instructions);
|
||||
$url = $url.'&signature='.$dec;
|
||||
}
|
||||
|
||||
// redirector.googlevideo.com
|
||||
//$url = preg_replace('@(\/\/)[^\.]+(\.googlevideo\.com)@', '$1redirector$2', $url);
|
||||
|
||||
$itag = $arr['itag'];
|
||||
$format = isset($this->itag_info[$itag]) ? $this->itag_info[$itag] : 'Unknown';
|
||||
|
||||
$result[$itag] = array(
|
||||
'url' => $url,
|
||||
'format' => $format
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// do we want all links or just select few?
|
||||
if($selector){
|
||||
return $this->selectFirst($result, $selector);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function sig_decipher($signature, $instructions){
|
||||
|
||||
foreach($instructions as $opt){
|
||||
|
||||
$command = $opt[0];
|
||||
$value = $opt[1];
|
||||
|
||||
if($command == 'swap'){
|
||||
|
||||
$temp = $signature[0];
|
||||
$signature[0] = $signature[$value % strlen($signature)];
|
||||
$signature[$value] = $temp;
|
||||
|
||||
} else if($command == 'splice'){
|
||||
$signature = substr($signature, $value);
|
||||
} else if($command == 'reverse'){
|
||||
$signature = strrev($signature);
|
||||
}
|
||||
}
|
||||
|
||||
return trim($signature);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
7
vendor/autoload.php
vendored
Normal file
7
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit63ec68ee21e36d1027e8f0238820c50e::getLoader();
|
413
vendor/composer/ClassLoader.php
vendored
Normal file
413
vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,413 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see http://www.php-fig.org/psr/psr-0/
|
||||
* @see http://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
private $prefixesPsr0 = array();
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
|
||||
if ('\\' == $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if ($file === null && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if ($file === null) {
|
||||
// Remember that this class does not exist.
|
||||
return $this->classMap[$class] = false;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
21
vendor/composer/LICENSE
vendored
Normal file
21
vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) 2016 Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
9
vendor/composer/autoload_classmap.php
vendored
Normal file
9
vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
12
vendor/composer/autoload_files.php
vendored
Normal file
12
vendor/composer/autoload_files.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'5e97df31a48c3d8473c36e3f1c45e0a4' => $vendorDir . '/athlon1600/youtube-downloader/src/YouTubeDownloader.php',
|
||||
'311a7016008bd2d1bccdd3da08cf87ee' => $vendorDir . '/athlon1600/php-proxy-plugin-bundle/src/utils.php',
|
||||
'fe17454461a24db888b8da8720edd309' => $vendorDir . '/athlon1600/php-proxy/src/helpers.php',
|
||||
);
|
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
12
vendor/composer/autoload_psr4.php
vendored
Normal file
12
vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
|
||||
'Proxy\\Plugin\\' => array($vendorDir . '/athlon1600/php-proxy-plugin-bundle/src'),
|
||||
'Proxy\\' => array($vendorDir . '/athlon1600/php-proxy/src'),
|
||||
);
|
59
vendor/composer/autoload_real.php
vendored
Normal file
59
vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit63ec68ee21e36d1027e8f0238820c50e
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit63ec68ee21e36d1027e8f0238820c50e', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit63ec68ee21e36d1027e8f0238820c50e', 'loadClassLoader'));
|
||||
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire63ec68ee21e36d1027e8f0238820c50e($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire63ec68ee21e36d1027e8f0238820c50e($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
182
vendor/composer/installed.json
vendored
Normal file
182
vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
[
|
||||
{
|
||||
"name": "athlon1600/youtube-downloader",
|
||||
"version": "v1.0.1",
|
||||
"version_normalized": "1.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Athlon1600/youtube-downloader.git",
|
||||
"reference": "50fc4f3ac7e2daf002b9ce21aee95252f87b3ae9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Athlon1600/youtube-downloader/zipball/50fc4f3ac7e2daf002b9ce21aee95252f87b3ae9",
|
||||
"reference": "50fc4f3ac7e2daf002b9ce21aee95252f87b3ae9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"time": "2017-02-26 19:17:47",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/YouTubeDownloader.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "PHP powered alternative for youtube-dl",
|
||||
"keywords": [
|
||||
"download youtube",
|
||||
"download youtube videos",
|
||||
"youtube downloader"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "athlon1600/php-proxy-plugin-bundle",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Athlon1600/php-proxy-plugin-bundle.git",
|
||||
"reference": "172202c9b7913dc397b0a2eeacb68984a73f5c6e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Athlon1600/php-proxy-plugin-bundle/zipball/172202c9b7913dc397b0a2eeacb68984a73f5c6e",
|
||||
"reference": "172202c9b7913dc397b0a2eeacb68984a73f5c6e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"athlon1600/youtube-downloader": "^1.0"
|
||||
},
|
||||
"time": "2017-03-17 19:59:40",
|
||||
"type": "library",
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Proxy\\Plugin\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/utils.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A collection of useful plugins to be used with php-proxy"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v3.3.2",
|
||||
"version_normalized": "3.3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "4054a102470665451108f9b59305c79176ef98f0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4054a102470665451108f9b59305c79176ef98f0",
|
||||
"reference": "4054a102470665451108f9b59305c79176ef98f0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "~2.8|~3.0",
|
||||
"symfony/dependency-injection": "~3.3",
|
||||
"symfony/expression-language": "~2.8|~3.0",
|
||||
"symfony/stopwatch": "~2.8|~3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/dependency-injection": "",
|
||||
"symfony/http-kernel": ""
|
||||
},
|
||||
"time": "2017-06-04 18:15:29",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\EventDispatcher\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "athlon1600/php-proxy",
|
||||
"version": "v5.0.3",
|
||||
"version_normalized": "5.0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Athlon1600/php-proxy.git",
|
||||
"reference": "12584d6892779c719d26f79bf464e7d9a2b48f88"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Athlon1600/php-proxy/zipball/12584d6892779c719d26f79bf464e7d9a2b48f88",
|
||||
"reference": "12584d6892779c719d26f79bf464e7d9a2b48f88",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"symfony/event-dispatcher": "~3.2"
|
||||
},
|
||||
"suggest": {
|
||||
"predis/predis": "For caching purposes"
|
||||
},
|
||||
"time": "2017-05-13 18:26:27",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Proxy\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"homepage": "https://www.php-proxy.com/",
|
||||
"keywords": [
|
||||
"php proxy",
|
||||
"php proxy script",
|
||||
"php web proxy",
|
||||
"proxy script",
|
||||
"web proxy"
|
||||
]
|
||||
}
|
||||
]
|
3
vendor/symfony/event-dispatcher/.gitignore
vendored
Normal file
3
vendor/symfony/event-dispatcher/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
vendor/
|
||||
composer.lock
|
||||
phpunit.xml
|
37
vendor/symfony/event-dispatcher/CHANGELOG.md
vendored
Normal file
37
vendor/symfony/event-dispatcher/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead.
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
|
||||
* The method `getListenerPriority($eventName, $listener)` has been added to the
|
||||
`EventDispatcherInterface`.
|
||||
* The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()`
|
||||
and `Event::getName()` have been removed.
|
||||
The event dispatcher and the event name are passed to the listener call.
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
||||
* added Debug\TraceableEventDispatcher (originally in HttpKernel)
|
||||
* changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface
|
||||
* added RegisterListenersPass (originally in HttpKernel)
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* added TraceableEventDispatcherInterface
|
||||
* added ContainerAwareEventDispatcher
|
||||
* added a reference to the EventDispatcher on the Event
|
||||
* added a reference to the Event name on the event
|
||||
* added fluid interface to the dispatch() method which now returns the Event
|
||||
object
|
||||
* added GenericEvent event class
|
||||
* added the possibility for subscribers to subscribe several times for the
|
||||
same event
|
||||
* added ImmutableEventDispatcher
|
211
vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
vendored
Normal file
211
vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Lazily loads listeners and subscribers from the dependency injection
|
||||
* container.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Jordan Alliot <jordan.alliot@gmail.com>
|
||||
*
|
||||
* @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
*/
|
||||
class ContainerAwareEventDispatcher extends EventDispatcher
|
||||
{
|
||||
/**
|
||||
* The container from where services are loaded.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* The service IDs of the event listeners and subscribers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $listenerIds = array();
|
||||
|
||||
/**
|
||||
* The services registered as listeners.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $listeners = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ContainerInterface $container A ContainerInterface instance
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
$class = get_class($this);
|
||||
if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
|
||||
$class = get_parent_class($class);
|
||||
}
|
||||
if (__CLASS__ !== $class) {
|
||||
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a service as event listener.
|
||||
*
|
||||
* @param string $eventName Event for which the listener is added
|
||||
* @param array $callback The service ID of the listener service & the method
|
||||
* name that has to be called
|
||||
* @param int $priority The higher this value, the earlier an event listener
|
||||
* will be triggered in the chain.
|
||||
* Defaults to 0.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addListenerService($eventName, $callback, $priority = 0)
|
||||
{
|
||||
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
|
||||
if (!is_array($callback) || 2 !== count($callback)) {
|
||||
throw new \InvalidArgumentException('Expected an array("service", "method") argument');
|
||||
}
|
||||
|
||||
$this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
|
||||
}
|
||||
|
||||
public function removeListener($eventName, $listener)
|
||||
{
|
||||
$this->lazyLoad($eventName);
|
||||
|
||||
if (isset($this->listenerIds[$eventName])) {
|
||||
foreach ($this->listenerIds[$eventName] as $i => list($serviceId, $method, $priority)) {
|
||||
$key = $serviceId.'.'.$method;
|
||||
if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) {
|
||||
unset($this->listeners[$eventName][$key]);
|
||||
if (empty($this->listeners[$eventName])) {
|
||||
unset($this->listeners[$eventName]);
|
||||
}
|
||||
unset($this->listenerIds[$eventName][$i]);
|
||||
if (empty($this->listenerIds[$eventName])) {
|
||||
unset($this->listenerIds[$eventName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::removeListener($eventName, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasListeners($eventName = null)
|
||||
{
|
||||
if (null === $eventName) {
|
||||
return $this->listenerIds || $this->listeners || parent::hasListeners();
|
||||
}
|
||||
|
||||
if (isset($this->listenerIds[$eventName])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::hasListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListeners($eventName = null)
|
||||
{
|
||||
if (null === $eventName) {
|
||||
foreach ($this->listenerIds as $serviceEventName => $args) {
|
||||
$this->lazyLoad($serviceEventName);
|
||||
}
|
||||
} else {
|
||||
$this->lazyLoad($eventName);
|
||||
}
|
||||
|
||||
return parent::getListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListenerPriority($eventName, $listener)
|
||||
{
|
||||
$this->lazyLoad($eventName);
|
||||
|
||||
return parent::getListenerPriority($eventName, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a service as event subscriber.
|
||||
*
|
||||
* @param string $serviceId The service ID of the subscriber service
|
||||
* @param string $class The service's class name (which must implement EventSubscriberInterface)
|
||||
*/
|
||||
public function addSubscriberService($serviceId, $class)
|
||||
{
|
||||
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
|
||||
foreach ($class::getSubscribedEvents() as $eventName => $params) {
|
||||
if (is_string($params)) {
|
||||
$this->listenerIds[$eventName][] = array($serviceId, $params, 0);
|
||||
} elseif (is_string($params[0])) {
|
||||
$this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0);
|
||||
} else {
|
||||
foreach ($params as $listener) {
|
||||
$this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getContainer()
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily loads listeners for this event from the dependency injection
|
||||
* container.
|
||||
*
|
||||
* @param string $eventName The name of the event to dispatch. The name of
|
||||
* the event is the name of the method that is
|
||||
* invoked on listeners.
|
||||
*/
|
||||
protected function lazyLoad($eventName)
|
||||
{
|
||||
if (isset($this->listenerIds[$eventName])) {
|
||||
foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) {
|
||||
$listener = $this->container->get($serviceId);
|
||||
|
||||
$key = $serviceId.'.'.$method;
|
||||
if (!isset($this->listeners[$eventName][$key])) {
|
||||
$this->addListener($eventName, array($listener, $method), $priority);
|
||||
} elseif ($listener !== $this->listeners[$eventName][$key]) {
|
||||
parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
|
||||
$this->addListener($eventName, array($listener, $method), $priority);
|
||||
}
|
||||
|
||||
$this->listeners[$eventName][$key] = $listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
324
vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
vendored
Normal file
324
vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Debug;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Collects some data about event listeners.
|
||||
*
|
||||
* This event dispatcher delegates the dispatching to another one.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
{
|
||||
protected $logger;
|
||||
protected $stopwatch;
|
||||
|
||||
private $called;
|
||||
private $dispatcher;
|
||||
private $wrappedListeners;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
|
||||
* @param Stopwatch $stopwatch A Stopwatch instance
|
||||
* @param LoggerInterface $logger A LoggerInterface instance
|
||||
*/
|
||||
public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->logger = $logger;
|
||||
$this->called = array();
|
||||
$this->wrappedListeners = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addListener($eventName, $listener, $priority = 0)
|
||||
{
|
||||
$this->dispatcher->addListener($eventName, $listener, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
$this->dispatcher->addSubscriber($subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeListener($eventName, $listener)
|
||||
{
|
||||
if (isset($this->wrappedListeners[$eventName])) {
|
||||
foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
|
||||
if ($wrappedListener->getWrappedListener() === $listener) {
|
||||
$listener = $wrappedListener;
|
||||
unset($this->wrappedListeners[$eventName][$index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dispatcher->removeListener($eventName, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
return $this->dispatcher->removeSubscriber($subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListeners($eventName = null)
|
||||
{
|
||||
return $this->dispatcher->getListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListenerPriority($eventName, $listener)
|
||||
{
|
||||
// we might have wrapped listeners for the event (if called while dispatching)
|
||||
// in that case get the priority by wrapper
|
||||
if (isset($this->wrappedListeners[$eventName])) {
|
||||
foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
|
||||
if ($wrappedListener->getWrappedListener() === $listener) {
|
||||
return $this->dispatcher->getListenerPriority($eventName, $wrappedListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dispatcher->getListenerPriority($eventName, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasListeners($eventName = null)
|
||||
{
|
||||
return $this->dispatcher->hasListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function dispatch($eventName, Event $event = null)
|
||||
{
|
||||
if (null === $event) {
|
||||
$event = new Event();
|
||||
}
|
||||
|
||||
if (null !== $this->logger && $event->isPropagationStopped()) {
|
||||
$this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName));
|
||||
}
|
||||
|
||||
$this->preProcess($eventName);
|
||||
$this->preDispatch($eventName, $event);
|
||||
|
||||
$e = $this->stopwatch->start($eventName, 'section');
|
||||
|
||||
$this->dispatcher->dispatch($eventName, $event);
|
||||
|
||||
if ($e->isStarted()) {
|
||||
$e->stop();
|
||||
}
|
||||
|
||||
$this->postDispatch($eventName, $event);
|
||||
$this->postProcess($eventName);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCalledListeners()
|
||||
{
|
||||
$called = array();
|
||||
foreach ($this->called as $eventName => $listeners) {
|
||||
foreach ($listeners as $listener) {
|
||||
$called[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName);
|
||||
}
|
||||
}
|
||||
|
||||
return $called;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNotCalledListeners()
|
||||
{
|
||||
try {
|
||||
$allListeners = $this->getListeners();
|
||||
} catch (\Exception $e) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e));
|
||||
}
|
||||
|
||||
// unable to retrieve the uncalled listeners
|
||||
return array();
|
||||
}
|
||||
|
||||
$notCalled = array();
|
||||
foreach ($allListeners as $eventName => $listeners) {
|
||||
foreach ($listeners as $listener) {
|
||||
$called = false;
|
||||
if (isset($this->called[$eventName])) {
|
||||
foreach ($this->called[$eventName] as $l) {
|
||||
if ($l->getWrappedListener() === $listener) {
|
||||
$called = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$called) {
|
||||
if (!$listener instanceof WrappedListener) {
|
||||
$listener = new WrappedListener($listener, null, $this->stopwatch, $this);
|
||||
}
|
||||
$notCalled[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uasort($notCalled, array($this, 'sortListenersByPriority'));
|
||||
|
||||
return $notCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxies all method calls to the original event dispatcher.
|
||||
*
|
||||
* @param string $method The method name
|
||||
* @param array $arguments The method arguments
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
return call_user_func_array(array($this->dispatcher, $method), $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before dispatching the event.
|
||||
*
|
||||
* @param string $eventName The event name
|
||||
* @param Event $event The event
|
||||
*/
|
||||
protected function preDispatch($eventName, Event $event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after dispatching the event.
|
||||
*
|
||||
* @param string $eventName The event name
|
||||
* @param Event $event The event
|
||||
*/
|
||||
protected function postDispatch($eventName, Event $event)
|
||||
{
|
||||
}
|
||||
|
||||
private function preProcess($eventName)
|
||||
{
|
||||
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
|
||||
$priority = $this->getListenerPriority($eventName, $listener);
|
||||
$wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this);
|
||||
$this->wrappedListeners[$eventName][] = $wrappedListener;
|
||||
$this->dispatcher->removeListener($eventName, $listener);
|
||||
$this->dispatcher->addListener($eventName, $wrappedListener, $priority);
|
||||
}
|
||||
}
|
||||
|
||||
private function postProcess($eventName)
|
||||
{
|
||||
unset($this->wrappedListeners[$eventName]);
|
||||
$skipped = false;
|
||||
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
|
||||
if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
|
||||
continue;
|
||||
}
|
||||
// Unwrap listener
|
||||
$priority = $this->getListenerPriority($eventName, $listener);
|
||||
$this->dispatcher->removeListener($eventName, $listener);
|
||||
$this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$context = array('event' => $eventName, 'listener' => $listener->getPretty());
|
||||
}
|
||||
|
||||
if ($listener->wasCalled()) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Notified event "{event}" to listener "{listener}".', $context);
|
||||
}
|
||||
|
||||
if (!isset($this->called[$eventName])) {
|
||||
$this->called[$eventName] = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
$this->called[$eventName]->attach($listener);
|
||||
}
|
||||
|
||||
if (null !== $this->logger && $skipped) {
|
||||
$this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context);
|
||||
}
|
||||
|
||||
if ($listener->stoppedPropagation()) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context);
|
||||
}
|
||||
|
||||
$skipped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sortListenersByPriority($a, $b)
|
||||
{
|
||||
if (is_int($a['priority']) && !is_int($b['priority'])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!is_int($a['priority']) && is_int($b['priority'])) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ($a['priority'] === $b['priority']) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($a['priority'] > $b['priority']) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
34
vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
vendored
Normal file
34
vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Debug;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface TraceableEventDispatcherInterface extends EventDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* Gets the called listeners.
|
||||
*
|
||||
* @return array An array of called listeners
|
||||
*/
|
||||
public function getCalledListeners();
|
||||
|
||||
/**
|
||||
* Gets the not called listeners.
|
||||
*
|
||||
* @return array An array of not called listeners
|
||||
*/
|
||||
public function getNotCalledListeners();
|
||||
}
|
116
vendor/symfony/event-dispatcher/Debug/WrappedListener.php
vendored
Normal file
116
vendor/symfony/event-dispatcher/Debug/WrappedListener.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Debug;
|
||||
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class WrappedListener
|
||||
{
|
||||
private $listener;
|
||||
private $name;
|
||||
private $called;
|
||||
private $stoppedPropagation;
|
||||
private $stopwatch;
|
||||
private $dispatcher;
|
||||
private $pretty;
|
||||
private $stub;
|
||||
|
||||
private static $cloner;
|
||||
|
||||
public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
$this->listener = $listener;
|
||||
$this->name = $name;
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->called = false;
|
||||
$this->stoppedPropagation = false;
|
||||
|
||||
if (is_array($listener)) {
|
||||
$this->name = is_object($listener[0]) ? get_class($listener[0]) : $listener[0];
|
||||
$this->pretty = $this->name.'::'.$listener[1];
|
||||
} elseif ($listener instanceof \Closure) {
|
||||
$this->pretty = $this->name = 'closure';
|
||||
} elseif (is_string($listener)) {
|
||||
$this->pretty = $this->name = $listener;
|
||||
} else {
|
||||
$this->name = get_class($listener);
|
||||
$this->pretty = $this->name.'::__invoke';
|
||||
}
|
||||
|
||||
if (null !== $name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
if (null === self::$cloner) {
|
||||
self::$cloner = class_exists(ClassStub::class) ? new VarCloner() : false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getWrappedListener()
|
||||
{
|
||||
return $this->listener;
|
||||
}
|
||||
|
||||
public function wasCalled()
|
||||
{
|
||||
return $this->called;
|
||||
}
|
||||
|
||||
public function stoppedPropagation()
|
||||
{
|
||||
return $this->stoppedPropagation;
|
||||
}
|
||||
|
||||
public function getPretty()
|
||||
{
|
||||
return $this->pretty;
|
||||
}
|
||||
|
||||
public function getInfo($eventName)
|
||||
{
|
||||
if (null === $this->stub) {
|
||||
$this->stub = false === self::$cloner ? $this->pretty.'()' : new ClassStub($this->pretty.'()', $this->listener);
|
||||
}
|
||||
|
||||
return array(
|
||||
'event' => $eventName,
|
||||
'priority' => null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null,
|
||||
'pretty' => $this->pretty,
|
||||
'stub' => $this->stub,
|
||||
);
|
||||
}
|
||||
|
||||
public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->called = true;
|
||||
|
||||
$e = $this->stopwatch->start($this->name, 'event_listener');
|
||||
|
||||
call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher);
|
||||
|
||||
if ($e->isStarted()) {
|
||||
$e->stop();
|
||||
}
|
||||
|
||||
if ($event->isPropagationStopped()) {
|
||||
$this->stoppedPropagation = true;
|
||||
}
|
||||
}
|
||||
}
|
135
vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
vendored
Normal file
135
vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Compiler pass to register tagged services for an event dispatcher.
|
||||
*/
|
||||
class RegisterListenersPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $dispatcherService;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $listenerTag;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $subscriberTag;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $dispatcherService Service name of the event dispatcher in processed container
|
||||
* @param string $listenerTag Tag name used for listener
|
||||
* @param string $subscriberTag Tag name used for subscribers
|
||||
*/
|
||||
public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber')
|
||||
{
|
||||
$this->dispatcherService = $dispatcherService;
|
||||
$this->listenerTag = $listenerTag;
|
||||
$this->subscriberTag = $subscriberTag;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$definition = $container->findDefinition($this->dispatcherService);
|
||||
|
||||
foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) {
|
||||
$def = $container->getDefinition($id);
|
||||
|
||||
foreach ($events as $event) {
|
||||
$priority = isset($event['priority']) ? $event['priority'] : 0;
|
||||
|
||||
if (!isset($event['event'])) {
|
||||
throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag));
|
||||
}
|
||||
|
||||
if (!isset($event['method'])) {
|
||||
$event['method'] = 'on'.preg_replace_callback(array(
|
||||
'/(?<=\b)[a-z]/i',
|
||||
'/[^a-z0-9]/i',
|
||||
), function ($matches) { return strtoupper($matches[0]); }, $event['event']);
|
||||
$event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
|
||||
}
|
||||
|
||||
$definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority));
|
||||
}
|
||||
}
|
||||
|
||||
$extractingDispatcher = new ExtractingEventDispatcher();
|
||||
|
||||
foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) {
|
||||
$def = $container->getDefinition($id);
|
||||
|
||||
// We must assume that the class value has been correctly filled, even if the service is created by a factory
|
||||
$class = $container->getParameterBag()->resolveValue($def->getClass());
|
||||
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
|
||||
|
||||
if (!is_subclass_of($class, $interface)) {
|
||||
if (!class_exists($class, false)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
|
||||
}
|
||||
$container->addObjectResource($class);
|
||||
|
||||
ExtractingEventDispatcher::$subscriber = $class;
|
||||
$extractingDispatcher->addSubscriber($extractingDispatcher);
|
||||
foreach ($extractingDispatcher->listeners as $args) {
|
||||
$args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]);
|
||||
$definition->addMethodCall('addListener', $args);
|
||||
}
|
||||
$extractingDispatcher->listeners = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface
|
||||
{
|
||||
public $listeners = array();
|
||||
|
||||
public static $subscriber;
|
||||
|
||||
public function addListener($eventName, $listener, $priority = 0)
|
||||
{
|
||||
$this->listeners[] = array($eventName, $listener[1], $priority);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
$callback = array(self::$subscriber, 'getSubscribedEvents');
|
||||
|
||||
return $callback();
|
||||
}
|
||||
}
|
58
vendor/symfony/event-dispatcher/Event.php
vendored
Normal file
58
vendor/symfony/event-dispatcher/Event.php
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
/**
|
||||
* Event is the base class for classes containing event data.
|
||||
*
|
||||
* This class contains no event data. It is used by events that do not pass
|
||||
* state information to an event handler when an event is raised.
|
||||
*
|
||||
* You can call the method stopPropagation() to abort the execution of
|
||||
* further listeners in your event listener.
|
||||
*
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
/**
|
||||
* @var bool Whether no further event listeners should be triggered
|
||||
*/
|
||||
private $propagationStopped = false;
|
||||
|
||||
/**
|
||||
* Returns whether further event listeners should be triggered.
|
||||
*
|
||||
* @see Event::stopPropagation()
|
||||
*
|
||||
* @return bool Whether propagation was already stopped for this event
|
||||
*/
|
||||
public function isPropagationStopped()
|
||||
{
|
||||
return $this->propagationStopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the propagation of the event to further event listeners.
|
||||
*
|
||||
* If multiple event listeners are connected to the same event, no
|
||||
* further event listener will be triggered once any trigger calls
|
||||
* stopPropagation().
|
||||
*/
|
||||
public function stopPropagation()
|
||||
{
|
||||
$this->propagationStopped = true;
|
||||
}
|
||||
}
|
236
vendor/symfony/event-dispatcher/EventDispatcher.php
vendored
Normal file
236
vendor/symfony/event-dispatcher/EventDispatcher.php
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
/**
|
||||
* The EventDispatcherInterface is the central point of Symfony's event listener system.
|
||||
*
|
||||
* Listeners are registered on the manager and events are dispatched through the
|
||||
* manager.
|
||||
*
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Jordan Alliot <jordan.alliot@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class EventDispatcher implements EventDispatcherInterface
|
||||
{
|
||||
private $listeners = array();
|
||||
private $sorted = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function dispatch($eventName, Event $event = null)
|
||||
{
|
||||
if (null === $event) {
|
||||
$event = new Event();
|
||||
}
|
||||
|
||||
if ($listeners = $this->getListeners($eventName)) {
|
||||
$this->doDispatch($listeners, $eventName, $event);
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListeners($eventName = null)
|
||||
{
|
||||
if (null !== $eventName) {
|
||||
if (empty($this->listeners[$eventName])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!isset($this->sorted[$eventName])) {
|
||||
$this->sortListeners($eventName);
|
||||
}
|
||||
|
||||
return $this->sorted[$eventName];
|
||||
}
|
||||
|
||||
foreach ($this->listeners as $eventName => $eventListeners) {
|
||||
if (!isset($this->sorted[$eventName])) {
|
||||
$this->sortListeners($eventName);
|
||||
}
|
||||
}
|
||||
|
||||
return array_filter($this->sorted);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListenerPriority($eventName, $listener)
|
||||
{
|
||||
if (empty($this->listeners[$eventName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
$listener[0] = $listener[0]();
|
||||
}
|
||||
|
||||
foreach ($this->listeners[$eventName] as $priority => $listeners) {
|
||||
foreach ($listeners as $k => $v) {
|
||||
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
|
||||
$v[0] = $v[0]();
|
||||
$this->listeners[$eventName][$priority][$k] = $v;
|
||||
}
|
||||
if ($v === $listener) {
|
||||
return $priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasListeners($eventName = null)
|
||||
{
|
||||
if (null !== $eventName) {
|
||||
return !empty($this->listeners[$eventName]);
|
||||
}
|
||||
|
||||
foreach ($this->listeners as $eventListeners) {
|
||||
if ($eventListeners) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addListener($eventName, $listener, $priority = 0)
|
||||
{
|
||||
$this->listeners[$eventName][$priority][] = $listener;
|
||||
unset($this->sorted[$eventName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeListener($eventName, $listener)
|
||||
{
|
||||
if (empty($this->listeners[$eventName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
$listener[0] = $listener[0]();
|
||||
}
|
||||
|
||||
foreach ($this->listeners[$eventName] as $priority => $listeners) {
|
||||
foreach ($listeners as $k => $v) {
|
||||
if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
|
||||
$v[0] = $v[0]();
|
||||
}
|
||||
if ($v === $listener) {
|
||||
unset($listeners[$k], $this->sorted[$eventName]);
|
||||
} else {
|
||||
$listeners[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
if ($listeners) {
|
||||
$this->listeners[$eventName][$priority] = $listeners;
|
||||
} else {
|
||||
unset($this->listeners[$eventName][$priority]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
|
||||
if (is_string($params)) {
|
||||
$this->addListener($eventName, array($subscriber, $params));
|
||||
} elseif (is_string($params[0])) {
|
||||
$this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
|
||||
} else {
|
||||
foreach ($params as $listener) {
|
||||
$this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
|
||||
if (is_array($params) && is_array($params[0])) {
|
||||
foreach ($params as $listener) {
|
||||
$this->removeListener($eventName, array($subscriber, $listener[0]));
|
||||
}
|
||||
} else {
|
||||
$this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the listeners of an event.
|
||||
*
|
||||
* This method can be overridden to add functionality that is executed
|
||||
* for each listener.
|
||||
*
|
||||
* @param callable[] $listeners The event listeners
|
||||
* @param string $eventName The name of the event to dispatch
|
||||
* @param Event $event The event object to pass to the event handlers/listeners
|
||||
*/
|
||||
protected function doDispatch($listeners, $eventName, Event $event)
|
||||
{
|
||||
foreach ($listeners as $listener) {
|
||||
if ($event->isPropagationStopped()) {
|
||||
break;
|
||||
}
|
||||
call_user_func($listener, $event, $eventName, $this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the internal list of listeners for the given event by priority.
|
||||
*
|
||||
* @param string $eventName The name of the event
|
||||
*/
|
||||
private function sortListeners($eventName)
|
||||
{
|
||||
krsort($this->listeners[$eventName]);
|
||||
$this->sorted[$eventName] = array();
|
||||
|
||||
foreach ($this->listeners[$eventName] as $priority => $listeners) {
|
||||
foreach ($listeners as $k => $listener) {
|
||||
if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
|
||||
$listener[0] = $listener[0]();
|
||||
$this->listeners[$eventName][$priority][$k] = $listener;
|
||||
}
|
||||
$this->sorted[$eventName][] = $listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
100
vendor/symfony/event-dispatcher/EventDispatcherInterface.php
vendored
Normal file
100
vendor/symfony/event-dispatcher/EventDispatcherInterface.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
/**
|
||||
* The EventDispatcherInterface is the central point of Symfony's event listener system.
|
||||
* Listeners are registered on the manager and events are dispatched through the
|
||||
* manager.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface EventDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* Dispatches an event to all registered listeners.
|
||||
*
|
||||
* @param string $eventName The name of the event to dispatch. The name of
|
||||
* the event is the name of the method that is
|
||||
* invoked on listeners.
|
||||
* @param Event $event The event to pass to the event handlers/listeners
|
||||
* If not supplied, an empty Event instance is created.
|
||||
*
|
||||
* @return Event
|
||||
*/
|
||||
public function dispatch($eventName, Event $event = null);
|
||||
|
||||
/**
|
||||
* Adds an event listener that listens on the specified events.
|
||||
*
|
||||
* @param string $eventName The event to listen on
|
||||
* @param callable $listener The listener
|
||||
* @param int $priority The higher this value, the earlier an event
|
||||
* listener will be triggered in the chain (defaults to 0)
|
||||
*/
|
||||
public function addListener($eventName, $listener, $priority = 0);
|
||||
|
||||
/**
|
||||
* Adds an event subscriber.
|
||||
*
|
||||
* The subscriber is asked for all the events he is
|
||||
* interested in and added as a listener for these events.
|
||||
*
|
||||
* @param EventSubscriberInterface $subscriber The subscriber
|
||||
*/
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber);
|
||||
|
||||
/**
|
||||
* Removes an event listener from the specified events.
|
||||
*
|
||||
* @param string $eventName The event to remove a listener from
|
||||
* @param callable $listener The listener to remove
|
||||
*/
|
||||
public function removeListener($eventName, $listener);
|
||||
|
||||
/**
|
||||
* Removes an event subscriber.
|
||||
*
|
||||
* @param EventSubscriberInterface $subscriber The subscriber
|
||||
*/
|
||||
public function removeSubscriber(EventSubscriberInterface $subscriber);
|
||||
|
||||
/**
|
||||
* Gets the listeners of a specific event or all listeners sorted by descending priority.
|
||||
*
|
||||
* @param string $eventName The name of the event
|
||||
*
|
||||
* @return array The event listeners for the specified event, or all event listeners by event name
|
||||
*/
|
||||
public function getListeners($eventName = null);
|
||||
|
||||
/**
|
||||
* Gets the listener priority for a specific event.
|
||||
*
|
||||
* Returns null if the event or the listener does not exist.
|
||||
*
|
||||
* @param string $eventName The name of the event
|
||||
* @param callable $listener The listener
|
||||
*
|
||||
* @return int|null The event listener priority
|
||||
*/
|
||||
public function getListenerPriority($eventName, $listener);
|
||||
|
||||
/**
|
||||
* Checks whether an event has any registered listeners.
|
||||
*
|
||||
* @param string $eventName The name of the event
|
||||
*
|
||||
* @return bool true if the specified event has any listeners, false otherwise
|
||||
*/
|
||||
public function hasListeners($eventName = null);
|
||||
}
|
46
vendor/symfony/event-dispatcher/EventSubscriberInterface.php
vendored
Normal file
46
vendor/symfony/event-dispatcher/EventSubscriberInterface.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
/**
|
||||
* An EventSubscriber knows himself what events he is interested in.
|
||||
* If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
|
||||
* {@link getSubscribedEvents} and registers the subscriber as a listener for all
|
||||
* returned events.
|
||||
*
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array of event names this subscriber wants to listen to.
|
||||
*
|
||||
* The array keys are event names and the value can be:
|
||||
*
|
||||
* * The method name to call (priority defaults to 0)
|
||||
* * An array composed of the method name to call and the priority
|
||||
* * An array of arrays composed of the method names to call and respective
|
||||
* priorities, or 0 if unset
|
||||
*
|
||||
* For instance:
|
||||
*
|
||||
* * array('eventName' => 'methodName')
|
||||
* * array('eventName' => array('methodName', $priority))
|
||||
* * array('eventName' => array(array('methodName1', $priority), array('methodName2')))
|
||||
*
|
||||
* @return array The event names to listen to
|
||||
*/
|
||||
public static function getSubscribedEvents();
|
||||
}
|
186
vendor/symfony/event-dispatcher/GenericEvent.php
vendored
Normal file
186
vendor/symfony/event-dispatcher/GenericEvent.php
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
/**
|
||||
* Event encapsulation class.
|
||||
*
|
||||
* Encapsulates events thus decoupling the observer from the subject they encapsulate.
|
||||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
*/
|
||||
class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Event subject.
|
||||
*
|
||||
* @var mixed usually object or callable
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* Array of arguments.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments;
|
||||
|
||||
/**
|
||||
* Encapsulate an event with $subject and $args.
|
||||
*
|
||||
* @param mixed $subject The subject of the event, usually an object
|
||||
* @param array $arguments Arguments to store in the event
|
||||
*/
|
||||
public function __construct($subject = null, array $arguments = array())
|
||||
{
|
||||
$this->subject = $subject;
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for subject property.
|
||||
*
|
||||
* @return mixed $subject The observer subject
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get argument by key.
|
||||
*
|
||||
* @param string $key Key
|
||||
*
|
||||
* @return mixed Contents of array key
|
||||
*
|
||||
* @throws \InvalidArgumentException If key is not found.
|
||||
*/
|
||||
public function getArgument($key)
|
||||
{
|
||||
if ($this->hasArgument($key)) {
|
||||
return $this->arguments[$key];
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add argument to event.
|
||||
*
|
||||
* @param string $key Argument name
|
||||
* @param mixed $value Value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setArgument($key, $value)
|
||||
{
|
||||
$this->arguments[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for all arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set args property.
|
||||
*
|
||||
* @param array $args Arguments
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setArguments(array $args = array())
|
||||
{
|
||||
$this->arguments = $args;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has argument.
|
||||
*
|
||||
* @param string $key Key of arguments array
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasArgument($key)
|
||||
{
|
||||
return array_key_exists($key, $this->arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess for argument getter.
|
||||
*
|
||||
* @param string $key Array key
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException If key does not exist in $this->args.
|
||||
*/
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return $this->getArgument($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess for argument setter.
|
||||
*
|
||||
* @param string $key Array key to set
|
||||
* @param mixed $value Value
|
||||
*/
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
$this->setArgument($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess for unset argument.
|
||||
*
|
||||
* @param string $key Array key
|
||||
*/
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
if ($this->hasArgument($key)) {
|
||||
unset($this->arguments[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess has argument.
|
||||
*
|
||||
* @param string $key Array key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return $this->hasArgument($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* IteratorAggregate for iterating over the object like an array.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->arguments);
|
||||
}
|
||||
}
|
101
vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php
vendored
Normal file
101
vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher;
|
||||
|
||||
/**
|
||||
* A read-only proxy for an event dispatcher.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ImmutableEventDispatcher implements EventDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* The proxied dispatcher.
|
||||
*
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
private $dispatcher;
|
||||
|
||||
/**
|
||||
* Creates an unmodifiable proxy for an event dispatcher.
|
||||
*
|
||||
* @param EventDispatcherInterface $dispatcher The proxied event dispatcher
|
||||
*/
|
||||
public function __construct(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function dispatch($eventName, Event $event = null)
|
||||
{
|
||||
return $this->dispatcher->dispatch($eventName, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addListener($eventName, $listener, $priority = 0)
|
||||
{
|
||||
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeListener($eventName, $listener)
|
||||
{
|
||||
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeSubscriber(EventSubscriberInterface $subscriber)
|
||||
{
|
||||
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListeners($eventName = null)
|
||||
{
|
||||
return $this->dispatcher->getListeners($eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListenerPriority($eventName, $listener)
|
||||
{
|
||||
return $this->dispatcher->getListenerPriority($eventName, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasListeners($eventName = null)
|
||||
{
|
||||
return $this->dispatcher->hasListeners($eventName);
|
||||
}
|
||||
}
|
19
vendor/symfony/event-dispatcher/LICENSE
vendored
Normal file
19
vendor/symfony/event-dispatcher/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-2017 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
15
vendor/symfony/event-dispatcher/README.md
vendored
Normal file
15
vendor/symfony/event-dispatcher/README.md
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
EventDispatcher Component
|
||||
=========================
|
||||
|
||||
The EventDispatcher component provides tools that allow your application
|
||||
components to communicate with each other by dispatching events and listening to
|
||||
them.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
442
vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php
vendored
Normal file
442
vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php
vendored
Normal file
@ -0,0 +1,442 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
abstract class AbstractEventDispatcherTest extends TestCase
|
||||
{
|
||||
/* Some pseudo events */
|
||||
const preFoo = 'pre.foo';
|
||||
const postFoo = 'post.foo';
|
||||
const preBar = 'pre.bar';
|
||||
const postBar = 'post.bar';
|
||||
|
||||
/**
|
||||
* @var EventDispatcher
|
||||
*/
|
||||
private $dispatcher;
|
||||
|
||||
private $listener;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->dispatcher = $this->createEventDispatcher();
|
||||
$this->listener = new TestEventListener();
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->dispatcher = null;
|
||||
$this->listener = null;
|
||||
}
|
||||
|
||||
abstract protected function createEventDispatcher();
|
||||
|
||||
public function testInitialState()
|
||||
{
|
||||
$this->assertEquals(array(), $this->dispatcher->getListeners());
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
|
||||
}
|
||||
|
||||
public function testAddListener()
|
||||
{
|
||||
$this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
|
||||
$this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
|
||||
$this->assertTrue($this->dispatcher->hasListeners());
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
|
||||
$this->assertCount(1, $this->dispatcher->getListeners(self::preFoo));
|
||||
$this->assertCount(1, $this->dispatcher->getListeners(self::postFoo));
|
||||
$this->assertCount(2, $this->dispatcher->getListeners());
|
||||
}
|
||||
|
||||
public function testGetListenersSortsByPriority()
|
||||
{
|
||||
$listener1 = new TestEventListener();
|
||||
$listener2 = new TestEventListener();
|
||||
$listener3 = new TestEventListener();
|
||||
$listener1->name = '1';
|
||||
$listener2->name = '2';
|
||||
$listener3->name = '3';
|
||||
|
||||
$this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10);
|
||||
$this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10);
|
||||
$this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo'));
|
||||
|
||||
$expected = array(
|
||||
array($listener2, 'preFoo'),
|
||||
array($listener3, 'preFoo'),
|
||||
array($listener1, 'preFoo'),
|
||||
);
|
||||
|
||||
$this->assertSame($expected, $this->dispatcher->getListeners('pre.foo'));
|
||||
}
|
||||
|
||||
public function testGetAllListenersSortsByPriority()
|
||||
{
|
||||
$listener1 = new TestEventListener();
|
||||
$listener2 = new TestEventListener();
|
||||
$listener3 = new TestEventListener();
|
||||
$listener4 = new TestEventListener();
|
||||
$listener5 = new TestEventListener();
|
||||
$listener6 = new TestEventListener();
|
||||
|
||||
$this->dispatcher->addListener('pre.foo', $listener1, -10);
|
||||
$this->dispatcher->addListener('pre.foo', $listener2);
|
||||
$this->dispatcher->addListener('pre.foo', $listener3, 10);
|
||||
$this->dispatcher->addListener('post.foo', $listener4, -10);
|
||||
$this->dispatcher->addListener('post.foo', $listener5);
|
||||
$this->dispatcher->addListener('post.foo', $listener6, 10);
|
||||
|
||||
$expected = array(
|
||||
'pre.foo' => array($listener3, $listener2, $listener1),
|
||||
'post.foo' => array($listener6, $listener5, $listener4),
|
||||
);
|
||||
|
||||
$this->assertSame($expected, $this->dispatcher->getListeners());
|
||||
}
|
||||
|
||||
public function testGetListenerPriority()
|
||||
{
|
||||
$listener1 = new TestEventListener();
|
||||
$listener2 = new TestEventListener();
|
||||
|
||||
$this->dispatcher->addListener('pre.foo', $listener1, -10);
|
||||
$this->dispatcher->addListener('pre.foo', $listener2);
|
||||
|
||||
$this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1));
|
||||
$this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2));
|
||||
$this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2));
|
||||
$this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {}));
|
||||
}
|
||||
|
||||
public function testDispatch()
|
||||
{
|
||||
$this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
|
||||
$this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
|
||||
$this->dispatcher->dispatch(self::preFoo);
|
||||
$this->assertTrue($this->listener->preFooInvoked);
|
||||
$this->assertFalse($this->listener->postFooInvoked);
|
||||
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent'));
|
||||
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
|
||||
$event = new Event();
|
||||
$return = $this->dispatcher->dispatch(self::preFoo, $event);
|
||||
$this->assertSame($event, $return);
|
||||
}
|
||||
|
||||
public function testDispatchForClosure()
|
||||
{
|
||||
$invoked = 0;
|
||||
$listener = function () use (&$invoked) {
|
||||
++$invoked;
|
||||
};
|
||||
$this->dispatcher->addListener('pre.foo', $listener);
|
||||
$this->dispatcher->addListener('post.foo', $listener);
|
||||
$this->dispatcher->dispatch(self::preFoo);
|
||||
$this->assertEquals(1, $invoked);
|
||||
}
|
||||
|
||||
public function testStopEventPropagation()
|
||||
{
|
||||
$otherListener = new TestEventListener();
|
||||
|
||||
// postFoo() stops the propagation, so only one listener should
|
||||
// be executed
|
||||
// Manually set priority to enforce $this->listener to be called first
|
||||
$this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10);
|
||||
$this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo'));
|
||||
$this->dispatcher->dispatch(self::postFoo);
|
||||
$this->assertTrue($this->listener->postFooInvoked);
|
||||
$this->assertFalse($otherListener->postFooInvoked);
|
||||
}
|
||||
|
||||
public function testDispatchByPriority()
|
||||
{
|
||||
$invoked = array();
|
||||
$listener1 = function () use (&$invoked) {
|
||||
$invoked[] = '1';
|
||||
};
|
||||
$listener2 = function () use (&$invoked) {
|
||||
$invoked[] = '2';
|
||||
};
|
||||
$listener3 = function () use (&$invoked) {
|
||||
$invoked[] = '3';
|
||||
};
|
||||
$this->dispatcher->addListener('pre.foo', $listener1, -10);
|
||||
$this->dispatcher->addListener('pre.foo', $listener2);
|
||||
$this->dispatcher->addListener('pre.foo', $listener3, 10);
|
||||
$this->dispatcher->dispatch(self::preFoo);
|
||||
$this->assertEquals(array('3', '2', '1'), $invoked);
|
||||
}
|
||||
|
||||
public function testRemoveListener()
|
||||
{
|
||||
$this->dispatcher->addListener('pre.bar', $this->listener);
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preBar));
|
||||
$this->dispatcher->removeListener('pre.bar', $this->listener);
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::preBar));
|
||||
$this->dispatcher->removeListener('notExists', $this->listener);
|
||||
}
|
||||
|
||||
public function testAddSubscriber()
|
||||
{
|
||||
$eventSubscriber = new TestEventSubscriber();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
|
||||
}
|
||||
|
||||
public function testAddSubscriberWithPriorities()
|
||||
{
|
||||
$eventSubscriber = new TestEventSubscriber();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
|
||||
$eventSubscriber = new TestEventSubscriberWithPriorities();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
|
||||
$listeners = $this->dispatcher->getListeners('pre.foo');
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertCount(2, $listeners);
|
||||
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
|
||||
}
|
||||
|
||||
public function testAddSubscriberWithMultipleListeners()
|
||||
{
|
||||
$eventSubscriber = new TestEventSubscriberWithMultipleListeners();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
|
||||
$listeners = $this->dispatcher->getListeners('pre.foo');
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertCount(2, $listeners);
|
||||
$this->assertEquals('preFoo2', $listeners[0][1]);
|
||||
}
|
||||
|
||||
public function testRemoveSubscriber()
|
||||
{
|
||||
$eventSubscriber = new TestEventSubscriber();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
|
||||
$this->dispatcher->removeSubscriber($eventSubscriber);
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
|
||||
}
|
||||
|
||||
public function testRemoveSubscriberWithPriorities()
|
||||
{
|
||||
$eventSubscriber = new TestEventSubscriberWithPriorities();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->dispatcher->removeSubscriber($eventSubscriber);
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
|
||||
}
|
||||
|
||||
public function testRemoveSubscriberWithMultipleListeners()
|
||||
{
|
||||
$eventSubscriber = new TestEventSubscriberWithMultipleListeners();
|
||||
$this->dispatcher->addSubscriber($eventSubscriber);
|
||||
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
|
||||
$this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
|
||||
$this->dispatcher->removeSubscriber($eventSubscriber);
|
||||
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
|
||||
}
|
||||
|
||||
public function testEventReceivesTheDispatcherInstanceAsArgument()
|
||||
{
|
||||
$listener = new TestWithDispatcher();
|
||||
$this->dispatcher->addListener('test', array($listener, 'foo'));
|
||||
$this->assertNull($listener->name);
|
||||
$this->assertNull($listener->dispatcher);
|
||||
$this->dispatcher->dispatch('test');
|
||||
$this->assertEquals('test', $listener->name);
|
||||
$this->assertSame($this->dispatcher, $listener->dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://bugs.php.net/bug.php?id=62976
|
||||
*
|
||||
* This bug affects:
|
||||
* - The PHP 5.3 branch for versions < 5.3.18
|
||||
* - The PHP 5.4 branch for versions < 5.4.8
|
||||
* - The PHP 5.5 branch is not affected
|
||||
*/
|
||||
public function testWorkaroundForPhpBug62976()
|
||||
{
|
||||
$dispatcher = $this->createEventDispatcher();
|
||||
$dispatcher->addListener('bug.62976', new CallableClass());
|
||||
$dispatcher->removeListener('bug.62976', function () {});
|
||||
$this->assertTrue($dispatcher->hasListeners('bug.62976'));
|
||||
}
|
||||
|
||||
public function testHasListenersWhenAddedCallbackListenerIsRemoved()
|
||||
{
|
||||
$listener = function () {};
|
||||
$this->dispatcher->addListener('foo', $listener);
|
||||
$this->dispatcher->removeListener('foo', $listener);
|
||||
$this->assertFalse($this->dispatcher->hasListeners());
|
||||
}
|
||||
|
||||
public function testGetListenersWhenAddedCallbackListenerIsRemoved()
|
||||
{
|
||||
$listener = function () {};
|
||||
$this->dispatcher->addListener('foo', $listener);
|
||||
$this->dispatcher->removeListener('foo', $listener);
|
||||
$this->assertSame(array(), $this->dispatcher->getListeners());
|
||||
}
|
||||
|
||||
public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled()
|
||||
{
|
||||
$this->assertFalse($this->dispatcher->hasListeners('foo'));
|
||||
$this->assertFalse($this->dispatcher->hasListeners());
|
||||
}
|
||||
|
||||
public function testHasListenersIsLazy()
|
||||
{
|
||||
$called = 0;
|
||||
$listener = array(function () use (&$called) { ++$called; }, 'onFoo');
|
||||
$this->dispatcher->addListener('foo', $listener);
|
||||
$this->assertTrue($this->dispatcher->hasListeners());
|
||||
$this->assertTrue($this->dispatcher->hasListeners('foo'));
|
||||
$this->assertSame(0, $called);
|
||||
}
|
||||
|
||||
public function testDispatchLazyListener()
|
||||
{
|
||||
$called = 0;
|
||||
$factory = function () use (&$called) {
|
||||
++$called;
|
||||
|
||||
return new TestWithDispatcher();
|
||||
};
|
||||
$this->dispatcher->addListener('foo', array($factory, 'foo'));
|
||||
$this->assertSame(0, $called);
|
||||
$this->dispatcher->dispatch('foo', new Event());
|
||||
$this->dispatcher->dispatch('foo', new Event());
|
||||
$this->assertSame(1, $called);
|
||||
}
|
||||
|
||||
public function testRemoveFindsLazyListeners()
|
||||
{
|
||||
$test = new TestWithDispatcher();
|
||||
$factory = function () use ($test) { return $test; };
|
||||
|
||||
$this->dispatcher->addListener('foo', array($factory, 'foo'));
|
||||
$this->assertTrue($this->dispatcher->hasListeners('foo'));
|
||||
$this->dispatcher->removeListener('foo', array($test, 'foo'));
|
||||
$this->assertFalse($this->dispatcher->hasListeners('foo'));
|
||||
|
||||
$this->dispatcher->addListener('foo', array($test, 'foo'));
|
||||
$this->assertTrue($this->dispatcher->hasListeners('foo'));
|
||||
$this->dispatcher->removeListener('foo', array($factory, 'foo'));
|
||||
$this->assertFalse($this->dispatcher->hasListeners('foo'));
|
||||
}
|
||||
|
||||
public function testPriorityFindsLazyListeners()
|
||||
{
|
||||
$test = new TestWithDispatcher();
|
||||
$factory = function () use ($test) { return $test; };
|
||||
|
||||
$this->dispatcher->addListener('foo', array($factory, 'foo'), 3);
|
||||
$this->assertSame(3, $this->dispatcher->getListenerPriority('foo', array($test, 'foo')));
|
||||
$this->dispatcher->removeListener('foo', array($factory, 'foo'));
|
||||
|
||||
$this->dispatcher->addListener('foo', array($test, 'foo'), 5);
|
||||
$this->assertSame(5, $this->dispatcher->getListenerPriority('foo', array($factory, 'foo')));
|
||||
}
|
||||
|
||||
public function testGetLazyListeners()
|
||||
{
|
||||
$test = new TestWithDispatcher();
|
||||
$factory = function () use ($test) { return $test; };
|
||||
|
||||
$this->dispatcher->addListener('foo', array($factory, 'foo'), 3);
|
||||
$this->assertSame(array(array($test, 'foo')), $this->dispatcher->getListeners('foo'));
|
||||
|
||||
$this->dispatcher->removeListener('foo', array($test, 'foo'));
|
||||
$this->dispatcher->addListener('bar', array($factory, 'foo'), 3);
|
||||
$this->assertSame(array('bar' => array(array($test, 'foo'))), $this->dispatcher->getListeners());
|
||||
}
|
||||
}
|
||||
|
||||
class CallableClass
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class TestEventListener
|
||||
{
|
||||
public $preFooInvoked = false;
|
||||
public $postFooInvoked = false;
|
||||
|
||||
/* Listener methods */
|
||||
|
||||
public function preFoo(Event $e)
|
||||
{
|
||||
$this->preFooInvoked = true;
|
||||
}
|
||||
|
||||
public function postFoo(Event $e)
|
||||
{
|
||||
$this->postFooInvoked = true;
|
||||
|
||||
$e->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
class TestWithDispatcher
|
||||
{
|
||||
public $name;
|
||||
public $dispatcher;
|
||||
|
||||
public function foo(Event $e, $name, $dispatcher)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
class TestEventSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo');
|
||||
}
|
||||
}
|
||||
|
||||
class TestEventSubscriberWithPriorities implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'pre.foo' => array('preFoo', 10),
|
||||
'post.foo' => array('postFoo'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array('pre.foo' => array(
|
||||
array('preFoo1'),
|
||||
array('preFoo2', 10),
|
||||
));
|
||||
}
|
||||
}
|
210
vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php
vendored
Normal file
210
vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest
|
||||
{
|
||||
protected function createEventDispatcher()
|
||||
{
|
||||
$container = new Container();
|
||||
|
||||
return new ContainerAwareEventDispatcher($container);
|
||||
}
|
||||
|
||||
public function testAddAListenerService()
|
||||
{
|
||||
$event = new Event();
|
||||
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock();
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEvent')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.listener', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
|
||||
|
||||
$dispatcher->dispatch('onEvent', $event);
|
||||
}
|
||||
|
||||
public function testAddASubscriberService()
|
||||
{
|
||||
$event = new Event();
|
||||
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\SubscriberService')->getMock();
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEvent')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEventWithPriority')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEventNested')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.subscriber', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService');
|
||||
|
||||
$dispatcher->dispatch('onEvent', $event);
|
||||
$dispatcher->dispatch('onEventWithPriority', $event);
|
||||
$dispatcher->dispatch('onEventNested', $event);
|
||||
}
|
||||
|
||||
public function testPreventDuplicateListenerService()
|
||||
{
|
||||
$event = new Event();
|
||||
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock();
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEvent')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.listener', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10);
|
||||
|
||||
$dispatcher->dispatch('onEvent', $event);
|
||||
}
|
||||
|
||||
public function testHasListenersOnLazyLoad()
|
||||
{
|
||||
$event = new Event();
|
||||
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock();
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.listener', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
|
||||
|
||||
$service
|
||||
->expects($this->once())
|
||||
->method('onEvent')
|
||||
->with($event)
|
||||
;
|
||||
|
||||
$this->assertTrue($dispatcher->hasListeners());
|
||||
|
||||
if ($dispatcher->hasListeners('onEvent')) {
|
||||
$dispatcher->dispatch('onEvent');
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetListenersOnLazyLoad()
|
||||
{
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock();
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.listener', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
|
||||
|
||||
$listeners = $dispatcher->getListeners();
|
||||
|
||||
$this->assertTrue(isset($listeners['onEvent']));
|
||||
|
||||
$this->assertCount(1, $dispatcher->getListeners('onEvent'));
|
||||
}
|
||||
|
||||
public function testRemoveAfterDispatch()
|
||||
{
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock();
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.listener', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
|
||||
|
||||
$dispatcher->dispatch('onEvent', new Event());
|
||||
$dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
|
||||
$this->assertFalse($dispatcher->hasListeners('onEvent'));
|
||||
}
|
||||
|
||||
public function testRemoveBeforeDispatch()
|
||||
{
|
||||
$service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock();
|
||||
|
||||
$container = new Container();
|
||||
$container->set('service.listener', $service);
|
||||
|
||||
$dispatcher = new ContainerAwareEventDispatcher($container);
|
||||
$dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
|
||||
|
||||
$dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
|
||||
$this->assertFalse($dispatcher->hasListeners('onEvent'));
|
||||
}
|
||||
}
|
||||
|
||||
class Service
|
||||
{
|
||||
public function onEvent(Event $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriberService implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'onEvent' => 'onEvent',
|
||||
'onEventWithPriority' => array('onEventWithPriority', 10),
|
||||
'onEventNested' => array(array('onEventNested')),
|
||||
);
|
||||
}
|
||||
|
||||
public function onEvent(Event $e)
|
||||
{
|
||||
}
|
||||
|
||||
public function onEventWithPriority(Event $e)
|
||||
{
|
||||
}
|
||||
|
||||
public function onEventNested(Event $e)
|
||||
{
|
||||
}
|
||||
}
|
242
vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php
vendored
Normal file
242
vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests\Debug;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
class TraceableEventDispatcherTest extends TestCase
|
||||
{
|
||||
public function testAddRemoveListener()
|
||||
{
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
|
||||
|
||||
$tdispatcher->addListener('foo', $listener = function () {});
|
||||
$listeners = $dispatcher->getListeners('foo');
|
||||
$this->assertCount(1, $listeners);
|
||||
$this->assertSame($listener, $listeners[0]);
|
||||
|
||||
$tdispatcher->removeListener('foo', $listener);
|
||||
$this->assertCount(0, $dispatcher->getListeners('foo'));
|
||||
}
|
||||
|
||||
public function testGetListeners()
|
||||
{
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
|
||||
|
||||
$tdispatcher->addListener('foo', $listener = function () {});
|
||||
$this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo'));
|
||||
}
|
||||
|
||||
public function testHasListeners()
|
||||
{
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
|
||||
|
||||
$this->assertFalse($dispatcher->hasListeners('foo'));
|
||||
$this->assertFalse($tdispatcher->hasListeners('foo'));
|
||||
|
||||
$tdispatcher->addListener('foo', $listener = function () {});
|
||||
$this->assertTrue($dispatcher->hasListeners('foo'));
|
||||
$this->assertTrue($tdispatcher->hasListeners('foo'));
|
||||
}
|
||||
|
||||
public function testGetListenerPriority()
|
||||
{
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
|
||||
|
||||
$tdispatcher->addListener('foo', function () {}, 123);
|
||||
|
||||
$listeners = $dispatcher->getListeners('foo');
|
||||
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
|
||||
|
||||
// Verify that priority is preserved when listener is removed and re-added
|
||||
// in preProcess() and postProcess().
|
||||
$tdispatcher->dispatch('foo', new Event());
|
||||
$listeners = $dispatcher->getListeners('foo');
|
||||
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
|
||||
}
|
||||
|
||||
public function testGetListenerPriorityWhileDispatching()
|
||||
{
|
||||
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$priorityWhileDispatching = null;
|
||||
|
||||
$listener = function () use ($tdispatcher, &$priorityWhileDispatching, &$listener) {
|
||||
$priorityWhileDispatching = $tdispatcher->getListenerPriority('bar', $listener);
|
||||
};
|
||||
|
||||
$tdispatcher->addListener('bar', $listener, 5);
|
||||
$tdispatcher->dispatch('bar');
|
||||
$this->assertSame(5, $priorityWhileDispatching);
|
||||
}
|
||||
|
||||
public function testAddRemoveSubscriber()
|
||||
{
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
|
||||
|
||||
$subscriber = new EventSubscriber();
|
||||
|
||||
$tdispatcher->addSubscriber($subscriber);
|
||||
$listeners = $dispatcher->getListeners('foo');
|
||||
$this->assertCount(1, $listeners);
|
||||
$this->assertSame(array($subscriber, 'call'), $listeners[0]);
|
||||
|
||||
$tdispatcher->removeSubscriber($subscriber);
|
||||
$this->assertCount(0, $dispatcher->getListeners('foo'));
|
||||
}
|
||||
|
||||
public function testGetCalledListeners()
|
||||
{
|
||||
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$tdispatcher->addListener('foo', function () {}, 5);
|
||||
|
||||
$listeners = $tdispatcher->getNotCalledListeners();
|
||||
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
|
||||
unset($listeners['foo.closure']['stub']);
|
||||
$this->assertEquals(array(), $tdispatcher->getCalledListeners());
|
||||
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
|
||||
|
||||
$tdispatcher->dispatch('foo');
|
||||
|
||||
$listeners = $tdispatcher->getCalledListeners();
|
||||
$this->assertArrayHasKey('stub', $listeners['foo.closure']);
|
||||
unset($listeners['foo.closure']['stub']);
|
||||
$this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners);
|
||||
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
|
||||
}
|
||||
|
||||
public function testGetCalledListenersNested()
|
||||
{
|
||||
$tdispatcher = null;
|
||||
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) {
|
||||
$tdispatcher = $dispatcher;
|
||||
$dispatcher->dispatch('bar');
|
||||
});
|
||||
$dispatcher->addListener('bar', function (Event $event) {});
|
||||
$dispatcher->dispatch('foo');
|
||||
$this->assertSame($dispatcher, $tdispatcher);
|
||||
$this->assertCount(2, $dispatcher->getCalledListeners());
|
||||
}
|
||||
|
||||
public function testLogger()
|
||||
{
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
|
||||
$tdispatcher->addListener('foo', $listener1 = function () {});
|
||||
$tdispatcher->addListener('foo', $listener2 = function () {});
|
||||
|
||||
$logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure'));
|
||||
$logger->expects($this->at(1))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure'));
|
||||
|
||||
$tdispatcher->dispatch('foo');
|
||||
}
|
||||
|
||||
public function testLoggerWithStoppedEvent()
|
||||
{
|
||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
|
||||
$tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); });
|
||||
$tdispatcher->addListener('foo', $listener2 = function () {});
|
||||
|
||||
$logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure'));
|
||||
$logger->expects($this->at(1))->method('debug')->with('Listener "{listener}" stopped propagation of the event "{event}".', array('event' => 'foo', 'listener' => 'closure'));
|
||||
$logger->expects($this->at(2))->method('debug')->with('Listener "{listener}" was not called for event "{event}".', array('event' => 'foo', 'listener' => 'closure'));
|
||||
|
||||
$tdispatcher->dispatch('foo');
|
||||
}
|
||||
|
||||
public function testDispatchCallListeners()
|
||||
{
|
||||
$called = array();
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
|
||||
$tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10);
|
||||
$tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20);
|
||||
|
||||
$tdispatcher->dispatch('foo');
|
||||
|
||||
$this->assertSame(array('foo2', 'foo1'), $called);
|
||||
}
|
||||
|
||||
public function testDispatchNested()
|
||||
{
|
||||
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$loop = 1;
|
||||
$dispatchedEvents = 0;
|
||||
$dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) {
|
||||
++$loop;
|
||||
if (2 == $loop) {
|
||||
$dispatcher->dispatch('foo');
|
||||
}
|
||||
});
|
||||
$dispatcher->addListener('foo', function () use (&$dispatchedEvents) {
|
||||
++$dispatchedEvents;
|
||||
});
|
||||
|
||||
$dispatcher->dispatch('foo');
|
||||
|
||||
$this->assertSame(2, $dispatchedEvents);
|
||||
}
|
||||
|
||||
public function testDispatchReusedEventNested()
|
||||
{
|
||||
$nestedCall = false;
|
||||
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$dispatcher->addListener('foo', function (Event $e) use ($dispatcher) {
|
||||
$dispatcher->dispatch('bar', $e);
|
||||
});
|
||||
$dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) {
|
||||
$nestedCall = true;
|
||||
});
|
||||
|
||||
$this->assertFalse($nestedCall);
|
||||
$dispatcher->dispatch('foo');
|
||||
$this->assertTrue($nestedCall);
|
||||
}
|
||||
|
||||
public function testListenerCanRemoveItselfWhenExecuted()
|
||||
{
|
||||
$eventDispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$listener1 = function ($event, $eventName, EventDispatcherInterface $dispatcher) use (&$listener1) {
|
||||
$dispatcher->removeListener('foo', $listener1);
|
||||
};
|
||||
$eventDispatcher->addListener('foo', $listener1);
|
||||
$eventDispatcher->addListener('foo', function () {});
|
||||
$eventDispatcher->dispatch('foo');
|
||||
|
||||
$this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed');
|
||||
}
|
||||
}
|
||||
|
||||
class EventSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array('foo' => 'call');
|
||||
}
|
||||
}
|
167
vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
vendored
Normal file
167
vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
|
||||
|
||||
class RegisterListenersPassTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Tests that event subscribers not implementing EventSubscriberInterface
|
||||
* trigger an exception.
|
||||
*
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testEventSubscriberWithoutInterface()
|
||||
{
|
||||
// one service, not implementing any interface
|
||||
$services = array(
|
||||
'my_event_subscriber' => array(0 => array()),
|
||||
);
|
||||
|
||||
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
|
||||
$definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue('stdClass'));
|
||||
|
||||
$builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock();
|
||||
$builder->expects($this->any())
|
||||
->method('hasDefinition')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
// We don't test kernel.event_listener here
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('findTaggedServiceIds')
|
||||
->will($this->onConsecutiveCalls(array(), $services));
|
||||
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('getDefinition')
|
||||
->will($this->returnValue($definition));
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($builder);
|
||||
}
|
||||
|
||||
public function testValidEventSubscriber()
|
||||
{
|
||||
$services = array(
|
||||
'my_event_subscriber' => array(0 => array()),
|
||||
);
|
||||
|
||||
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
|
||||
$definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue('Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService'));
|
||||
|
||||
$builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'findDefinition'))->getMock();
|
||||
$builder->expects($this->any())
|
||||
->method('hasDefinition')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
// We don't test kernel.event_listener here
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('findTaggedServiceIds')
|
||||
->will($this->onConsecutiveCalls(array(), $services));
|
||||
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('getDefinition')
|
||||
->will($this->returnValue($definition));
|
||||
|
||||
$builder->expects($this->atLeastOnce())
|
||||
->method('findDefinition')
|
||||
->will($this->returnValue($definition));
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage The service "foo" tagged "kernel.event_listener" must not be abstract.
|
||||
*/
|
||||
public function testAbstractEventListener()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', array());
|
||||
$container->register('event_dispatcher', 'stdClass');
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage The service "foo" tagged "kernel.event_subscriber" must not be abstract.
|
||||
*/
|
||||
public function testAbstractEventSubscriber()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_subscriber', array());
|
||||
$container->register('event_dispatcher', 'stdClass');
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($container);
|
||||
}
|
||||
|
||||
public function testEventSubscriberResolvableClassName()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$container->setParameter('subscriber.class', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService');
|
||||
$container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', array());
|
||||
$container->register('event_dispatcher', 'stdClass');
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($container);
|
||||
|
||||
$definition = $container->getDefinition('event_dispatcher');
|
||||
$expectedCalls = array(
|
||||
array(
|
||||
'addListener',
|
||||
array(
|
||||
'event',
|
||||
array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'),
|
||||
0,
|
||||
),
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage You have requested a non-existent parameter "subscriber.class"
|
||||
*/
|
||||
public function testEventSubscriberUnresolvableClassName()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', array());
|
||||
$container->register('event_dispatcher', 'stdClass');
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($container);
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'event' => 'onEvent',
|
||||
);
|
||||
}
|
||||
}
|
22
vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php
vendored
Normal file
22
vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
class EventDispatcherTest extends AbstractEventDispatcherTest
|
||||
{
|
||||
protected function createEventDispatcher()
|
||||
{
|
||||
return new EventDispatcher();
|
||||
}
|
||||
}
|
55
vendor/symfony/event-dispatcher/Tests/EventTest.php
vendored
Normal file
55
vendor/symfony/event-dispatcher/Tests/EventTest.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Test class for Event.
|
||||
*/
|
||||
class EventTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\EventDispatcher\Event
|
||||
*/
|
||||
protected $event;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$this->event = new Event();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->event = null;
|
||||
}
|
||||
|
||||
public function testIsPropagationStopped()
|
||||
{
|
||||
$this->assertFalse($this->event->isPropagationStopped());
|
||||
}
|
||||
|
||||
public function testStopPropagationAndIsPropagationStopped()
|
||||
{
|
||||
$this->event->stopPropagation();
|
||||
$this->assertTrue($this->event->isPropagationStopped());
|
||||
}
|
||||
}
|
140
vendor/symfony/event-dispatcher/Tests/GenericEventTest.php
vendored
Normal file
140
vendor/symfony/event-dispatcher/Tests/GenericEventTest.php
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\GenericEvent;
|
||||
|
||||
/**
|
||||
* Test class for Event.
|
||||
*/
|
||||
class GenericEventTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var GenericEvent
|
||||
*/
|
||||
private $event;
|
||||
|
||||
private $subject;
|
||||
|
||||
/**
|
||||
* Prepares the environment before running a test.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->subject = new \stdClass();
|
||||
$this->event = new GenericEvent($this->subject, array('name' => 'Event'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the environment after running a test.
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->subject = null;
|
||||
$this->event = null;
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testConstruct()
|
||||
{
|
||||
$this->assertEquals($this->event, new GenericEvent($this->subject, array('name' => 'Event')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Event->getArgs().
|
||||
*/
|
||||
public function testGetArguments()
|
||||
{
|
||||
// test getting all
|
||||
$this->assertSame(array('name' => 'Event'), $this->event->getArguments());
|
||||
}
|
||||
|
||||
public function testSetArguments()
|
||||
{
|
||||
$result = $this->event->setArguments(array('foo' => 'bar'));
|
||||
$this->assertAttributeSame(array('foo' => 'bar'), 'arguments', $this->event);
|
||||
$this->assertSame($this->event, $result);
|
||||
}
|
||||
|
||||
public function testSetArgument()
|
||||
{
|
||||
$result = $this->event->setArgument('foo2', 'bar2');
|
||||
$this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event);
|
||||
$this->assertEquals($this->event, $result);
|
||||
}
|
||||
|
||||
public function testGetArgument()
|
||||
{
|
||||
// test getting key
|
||||
$this->assertEquals('Event', $this->event->getArgument('name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testGetArgException()
|
||||
{
|
||||
$this->event->getArgument('nameNotExist');
|
||||
}
|
||||
|
||||
public function testOffsetGet()
|
||||
{
|
||||
// test getting key
|
||||
$this->assertEquals('Event', $this->event['name']);
|
||||
|
||||
// test getting invalid arg
|
||||
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException');
|
||||
$this->assertFalse($this->event['nameNotExist']);
|
||||
}
|
||||
|
||||
public function testOffsetSet()
|
||||
{
|
||||
$this->event['foo2'] = 'bar2';
|
||||
$this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event);
|
||||
}
|
||||
|
||||
public function testOffsetUnset()
|
||||
{
|
||||
unset($this->event['name']);
|
||||
$this->assertAttributeSame(array(), 'arguments', $this->event);
|
||||
}
|
||||
|
||||
public function testOffsetIsset()
|
||||
{
|
||||
$this->assertTrue(isset($this->event['name']));
|
||||
$this->assertFalse(isset($this->event['nameNotExist']));
|
||||
}
|
||||
|
||||
public function testHasArgument()
|
||||
{
|
||||
$this->assertTrue($this->event->hasArgument('name'));
|
||||
$this->assertFalse($this->event->hasArgument('nameNotExist'));
|
||||
}
|
||||
|
||||
public function testGetSubject()
|
||||
{
|
||||
$this->assertSame($this->subject, $this->event->getSubject());
|
||||
}
|
||||
|
||||
public function testHasIterator()
|
||||
{
|
||||
$data = array();
|
||||
foreach ($this->event as $key => $value) {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
$this->assertEquals(array('name' => 'Event'), $data);
|
||||
}
|
||||
}
|
106
vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php
vendored
Normal file
106
vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ImmutableEventDispatcherTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
private $innerDispatcher;
|
||||
|
||||
/**
|
||||
* @var ImmutableEventDispatcher
|
||||
*/
|
||||
private $dispatcher;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->innerDispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
|
||||
$this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher);
|
||||
}
|
||||
|
||||
public function testDispatchDelegates()
|
||||
{
|
||||
$event = new Event();
|
||||
|
||||
$this->innerDispatcher->expects($this->once())
|
||||
->method('dispatch')
|
||||
->with('event', $event)
|
||||
->will($this->returnValue('result'));
|
||||
|
||||
$this->assertSame('result', $this->dispatcher->dispatch('event', $event));
|
||||
}
|
||||
|
||||
public function testGetListenersDelegates()
|
||||
{
|
||||
$this->innerDispatcher->expects($this->once())
|
||||
->method('getListeners')
|
||||
->with('event')
|
||||
->will($this->returnValue('result'));
|
||||
|
||||
$this->assertSame('result', $this->dispatcher->getListeners('event'));
|
||||
}
|
||||
|
||||
public function testHasListenersDelegates()
|
||||
{
|
||||
$this->innerDispatcher->expects($this->once())
|
||||
->method('hasListeners')
|
||||
->with('event')
|
||||
->will($this->returnValue('result'));
|
||||
|
||||
$this->assertSame('result', $this->dispatcher->hasListeners('event'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
*/
|
||||
public function testAddListenerDisallowed()
|
||||
{
|
||||
$this->dispatcher->addListener('event', function () { return 'foo'; });
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
*/
|
||||
public function testAddSubscriberDisallowed()
|
||||
{
|
||||
$subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock();
|
||||
|
||||
$this->dispatcher->addSubscriber($subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
*/
|
||||
public function testRemoveListenerDisallowed()
|
||||
{
|
||||
$this->dispatcher->removeListener('event', function () { return 'foo'; });
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
*/
|
||||
public function testRemoveSubscriberDisallowed()
|
||||
{
|
||||
$subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock();
|
||||
|
||||
$this->dispatcher->removeSubscriber($subscriber);
|
||||
}
|
||||
}
|
47
vendor/symfony/event-dispatcher/composer.json
vendored
Normal file
47
vendor/symfony/event-dispatcher/composer.json
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"type": "library",
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"keywords": [],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dependency-injection": "~3.3",
|
||||
"symfony/expression-language": "~2.8|~3.0",
|
||||
"symfony/config": "~2.8|~3.0",
|
||||
"symfony/stopwatch": "~2.8|~3.0",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/dependency-injection": "",
|
||||
"symfony/http-kernel": ""
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\EventDispatcher\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
31
vendor/symfony/event-dispatcher/phpunit.xml.dist
vendored
Normal file
31
vendor/symfony/event-dispatcher/phpunit.xml.dist
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
>
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Symfony EventDispatcher Component Test Suite">
|
||||
<directory>./Tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./</directory>
|
||||
<exclude>
|
||||
<directory>./Resources</directory>
|
||||
<directory>./Tests</directory>
|
||||
<directory>./vendor</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
Loading…
Reference in New Issue
Block a user