Merge branch 'release-2.3.0'

This commit is contained in:
Pierre Rudloff 2020-05-14 12:40:03 +02:00
commit c136534723
50 changed files with 1010 additions and 858 deletions

View file

@ -26,7 +26,9 @@ FileETag None
</ifmodule> </ifmodule>
<ifmodule mod_filter.c> <ifmodule mod_filter.c>
AddOutputFilterByType DEFLATE text/css text/html application/javascript font/truetype <IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/css text/html application/javascript font/truetype
</IfModule>
</ifmodule> </ifmodule>
<ifmodule mod_headers.c> <ifmodule mod_headers.c>

View file

@ -2,10 +2,10 @@
language: php language: php
php: 7.3 php: 7.3
addons: addons:
apt: apt:
packages: packages:
- language-pack-fr - language-pack-fr
install: composer install --no-progress install: composer install --no-progress
script: script:
- composer lint - composer lint
- composer test - composer test

View file

@ -7,6 +7,7 @@
namespace Alltube; namespace Alltube;
use Exception; use Exception;
use Jawira\CaseConverter\CaseConverterException;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
use Jawira\CaseConverter\Convert; use Jawira\CaseConverter\Convert;
@ -39,7 +40,7 @@ class Config
/** /**
* youtube-dl parameters. * youtube-dl parameters.
* *
* @var array * @var string[]
*/ */
public $params = ['--no-warnings', '--ignore-errors', '--flat-playlist', '--restrict-filenames', '--no-playlist']; public $params = ['--no-warnings', '--ignore-errors', '--flat-playlist', '--restrict-filenames', '--no-playlist'];
@ -60,7 +61,7 @@ class Config
/** /**
* List of formats available in advanced conversion mode. * List of formats available in advanced conversion mode.
* *
* @var array * @var string[]
*/ */
public $convertAdvancedFormats = ['mp3', 'avi', 'flv', 'wav']; public $convertAdvancedFormats = ['mp3', 'avi', 'flv', 'wav'];
@ -121,17 +122,10 @@ class Config
*/ */
public $appName = 'AllTube Download'; public $appName = 'AllTube Download';
/**
* YAML config file path.
*
* @var string
*/
private $file;
/** /**
* Generic formats supported by youtube-dl. * Generic formats supported by youtube-dl.
* *
* @var array * @var string[]
*/ */
public $genericFormats = []; public $genericFormats = [];
@ -145,7 +139,8 @@ class Config
/** /**
* Config constructor. * Config constructor.
* *
* @param array $options Options * @param mixed[] $options Options
* @throws CaseConverterException
*/ */
private function __construct(array $options = []) private function __construct(array $options = [])
{ {
@ -156,9 +151,9 @@ class Config
if (empty($this->genericFormats)) { if (empty($this->genericFormats)) {
// We don't put this in the class definition so it can be detected by xgettext. // We don't put this in the class definition so it can be detected by xgettext.
$this->genericFormats = [ $this->genericFormats = [
'best' => $localeManager->t('Best'), 'best' => $localeManager->t('Best'),
'bestvideo+bestaudio' => $localeManager->t('Remux best video with best audio'), 'bestvideo+bestaudio' => $localeManager->t('Remux best video with best audio'),
'worst' => $localeManager->t('Worst'), 'worst' => $localeManager->t('Worst'),
]; ];
} }
@ -195,10 +190,10 @@ class Config
/** /**
* Throw an exception if some of the options are invalid. * Throw an exception if some of the options are invalid.
* *
* @throws Exception If youtube-dl is missing * @return void
* @throws Exception If Python is missing * @throws Exception If Python is missing
* *
* @return void * @throws Exception If youtube-dl is missing
*/ */
private function validateOptions() private function validateOptions()
{ {
@ -216,7 +211,7 @@ class Config
/** /**
* Apply the provided options. * Apply the provided options.
* *
* @param array $options Options * @param mixed[] $options Options
* *
* @return void * @return void
*/ */
@ -235,6 +230,7 @@ class Config
* If the value is an array, you should use the YAML format: "CONVERT_ADVANCED_FORMATS='[foo, bar]'" * If the value is an array, you should use the YAML format: "CONVERT_ADVANCED_FORMATS='[foo, bar]'"
* *
* @return void * @return void
* @throws CaseConverterException
*/ */
private function getEnv() private function getEnv()
{ {
@ -265,11 +261,13 @@ class Config
* Set options from a YAML file. * Set options from a YAML file.
* *
* @param string $file Path to the YAML file * @param string $file Path to the YAML file
* @return void
* @throws Exception
*/ */
public static function setFile($file) public static function setFile($file)
{ {
if (is_file($file)) { if (is_file($file)) {
$options = Yaml::parse(file_get_contents($file)); $options = Yaml::parse(strval(file_get_contents($file)));
self::$instance = new self($options); self::$instance = new self($options);
self::$instance->validateOptions(); self::$instance->validateOptions();
} else { } else {
@ -280,8 +278,10 @@ class Config
/** /**
* Manually set some options. * Manually set some options.
* *
* @param array $options Options (see `config/config.example.yml` for available options) * @param mixed[] $options Options (see `config/config.example.yml` for available options)
* @param bool $update True to update an existing instance * @param bool $update True to update an existing instance
* @return void
* @throws Exception
*/ */
public static function setOptions(array $options, $update = true) public static function setOptions(array $options, $update = true)
{ {

View file

@ -104,12 +104,14 @@ class Locale
/** /**
* Get country information from locale. * Get country information from locale.
* *
* @return Country|array * @return Country|Country[]|null
*/ */
public function getCountry() public function getCountry()
{ {
if (isset($this->region)) { if (isset($this->region)) {
return country($this->getIso3166()); return country($this->getIso3166());
} }
return null;
} }
} }

View file

@ -7,7 +7,6 @@
namespace Alltube; namespace Alltube;
use Aura\Session\Segment; use Aura\Session\Segment;
use Symfony\Component\Process\Process;
use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\PoFileLoader; use Symfony\Component\Translation\Loader\PoFileLoader;
@ -19,7 +18,7 @@ class LocaleManager
/** /**
* Supported locales. * Supported locales.
* *
* @var array * @var string[]
*/ */
private $supportedLocales = ['en_US', 'fr_FR', 'zh_CN', 'es_ES', 'pt_BR', 'de_DE', 'ar', 'pl_PL', 'tr_TR']; private $supportedLocales = ['en_US', 'fr_FR', 'zh_CN', 'es_ES', 'pt_BR', 'de_DE', 'ar', 'pl_PL', 'tr_TR'];
@ -112,6 +111,7 @@ class LocaleManager
* Set the current locale. * Set the current locale.
* *
* @param Locale $locale Locale * @param Locale $locale Locale
* @return void
*/ */
public function setLocale(Locale $locale) public function setLocale(Locale $locale)
{ {
@ -122,6 +122,7 @@ class LocaleManager
/** /**
* Unset the current locale. * Unset the current locale.
* @return void
*/ */
public function unsetLocale() public function unsetLocale()
{ {
@ -133,8 +134,8 @@ class LocaleManager
/** /**
* Smarty "t" block. * Smarty "t" block.
* *
* @param array $params Block parameters * @param mixed[] $params Block parameters
* @param string $text Block content * @param string $text Block content
* *
* @return string Translated string * @return string Translated string
*/ */
@ -152,6 +153,7 @@ class LocaleManager
* *
* @param string $string String to translate * @param string $string String to translate
* *
* @param mixed[] $params
* @return string Translated string * @return string Translated string
*/ */
public function t($string, array $params = []) public function t($string, array $params = [])

View file

@ -36,9 +36,9 @@ class LocaleMiddleware
/** /**
* Test if a locale can be used for the current user. * Test if a locale can be used for the current user.
* *
* @param array $proposedLocale Locale array created by AcceptLanguage::parse() * @param mixed[] $proposedLocale Locale array created by AcceptLanguage::parse()
* *
* @return Locale Locale if chosen, nothing otherwise * @return Locale|null Locale if chosen, nothing otherwise
*/ */
public function testLocale(array $proposedLocale) public function testLocale(array $proposedLocale)
{ {
@ -52,14 +52,16 @@ class LocaleMiddleware
return new Locale($proposedLocale['language'] . '_' . $proposedLocale['region']); return new Locale($proposedLocale['language'] . '_' . $proposedLocale['region']);
} }
} }
return null;
} }
/** /**
* Main middleware function. * Main middleware function.
* *
* @param Request $request PSR request * @param Request $request PSR request
* @param Response $response PSR response * @param Response $response PSR response
* @param callable $next Next middleware * @param callable $next Next middleware
* *
* @return Response * @return Response
*/ */

View file

@ -21,7 +21,7 @@ class UglyRouter extends Router
* *
* @param ServerRequestInterface $request The current HTTP request object * @param ServerRequestInterface $request The current HTTP request object
* *
* @return array * @return mixed[]
* *
* @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php * @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
*/ */
@ -42,14 +42,14 @@ class UglyRouter extends Router
/** /**
* Build the path for a named route including the base path. * Build the path for a named route including the base path.
* *
* @param string $name Route name * @param string $name Route name
* @param array $data Named argument replacement data * @param string[] $data Named argument replacement data
* @param array $queryParams Optional query string parameters * @param string[] $queryParams Optional query string parameters
*
* @throws RuntimeException If named route does not exist
* @throws InvalidArgumentException If required data not provided
* *
* @return string * @return string
* @throws InvalidArgumentException If required data not provided
*
* @throws RuntimeException If named route does not exist
*/ */
public function pathFor($name, array $data = [], array $queryParams = []) public function pathFor($name, array $data = [], array $queryParams = [])
{ {

View file

@ -10,7 +10,7 @@ use Alltube\Exception\EmptyUrlException;
use Alltube\Exception\PasswordException; use Alltube\Exception\PasswordException;
use Exception; use Exception;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface;
use stdClass; use stdClass;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
@ -19,16 +19,16 @@ use Symfony\Component\Process\Process;
* *
* Due to the way youtube-dl behaves, this class can also contain information about a playlist. * Due to the way youtube-dl behaves, this class can also contain information about a playlist.
* *
* @property-read string $title Title * @property-read string $title Title
* @property-read string $protocol Network protocol (HTTP, RTMP, etc.) * @property-read string $protocol Network protocol (HTTP, RTMP, etc.)
* @property-read string $url File URL * @property-read string $url File URL
* @property-read string $ext File extension * @property-read string $ext File extension
* @property-read string $extractor_key youtube-dl extractor class used * @property-read string $extractor_key youtube-dl extractor class used
* @property-read array $entries List of videos (if the object contains information about a playlist) * @property-read array $entries List of videos (if the object contains information about a playlist)
* @property-read array $rtmp_conn * @property-read array $rtmp_conn
* @property-read string|null $_type Object type (usually "playlist" or null) * @property-read string|null $_type Object type (usually "playlist" or null)
* @property-read stdClass $downloader_options * @property-read stdClass $downloader_options
* @property-read stdClass $http_headers * @property-read stdClass $http_headers
*/ */
class Video class Video
{ {
@ -70,7 +70,7 @@ class Video
/** /**
* URLs of the video files. * URLs of the video files.
* *
* @var array * @var string[]
*/ */
private $urls; private $urls;
@ -84,11 +84,11 @@ class Video
/** /**
* VideoDownload constructor. * VideoDownload constructor.
* *
* @param string $webpageUrl URL of the page containing the video * @param string $webpageUrl URL of the page containing the video
* @param string $requestedFormat Requested video format * @param string $requestedFormat Requested video format
* (can be any format string accepted by youtube-dl, * (can be any format string accepted by youtube-dl,
* including selectors like "[height<=720]") * including selectors like "[height<=720]")
* @param string $password Password * @param string $password Password
*/ */
public function __construct($webpageUrl, $requestedFormat = 'best', $password = null) public function __construct($webpageUrl, $requestedFormat = 'best', $password = null)
{ {
@ -105,7 +105,7 @@ class Video
* *
* @param string[] $arguments Arguments * @param string[] $arguments Arguments
* *
* @return Process * @return Process<string>
*/ */
private static function getProcess(array $arguments) private static function getProcess(array $arguments)
{ {
@ -124,7 +124,9 @@ class Video
* List all extractors. * List all extractors.
* *
* @return string[] Extractors * @return string[] Extractors
* */ *
* @throws PasswordException
*/
public static function getExtractors() public static function getExtractors()
{ {
$video = new self(''); $video = new self('');
@ -135,13 +137,13 @@ class Video
/** /**
* Call youtube-dl. * Call youtube-dl.
* *
* @param array $arguments Arguments * @param string[] $arguments Arguments
* *
* @throws PasswordException If the video is protected by a password and no password was specified * @return string Result
* @throws Exception If the password is wrong * @throws Exception If the password is wrong
* @throws Exception If youtube-dl returns an error * @throws Exception If youtube-dl returns an error
* *
* @return string Result * @throws PasswordException If the video is protected by a password and no password was specified
*/ */
private function callYoutubedl(array $arguments) private function callYoutubedl(array $arguments)
{ {
@ -153,7 +155,7 @@ class Video
$process->run(); $process->run();
if (!$process->isSuccessful()) { if (!$process->isSuccessful()) {
$errorOutput = trim($process->getErrorOutput()); $errorOutput = trim($process->getErrorOutput());
$exitCode = $process->getExitCode(); $exitCode = intval($process->getExitCode());
if ($errorOutput == 'ERROR: This video is protected by a password, use the --video-password option') { if ($errorOutput == 'ERROR: This video is protected by a password, use the --video-password option') {
throw new PasswordException($errorOutput, $exitCode); throw new PasswordException($errorOutput, $exitCode);
} elseif (substr($errorOutput, 0, 21) == 'ERROR: Wrong password') { } elseif (substr($errorOutput, 0, 21) == 'ERROR: Wrong password') {
@ -172,6 +174,7 @@ class Video
* @param string $prop Property * @param string $prop Property
* *
* @return string * @return string
* @throws PasswordException
*/ */
private function getProp($prop = 'dump-json') private function getProp($prop = 'dump-json')
{ {
@ -196,7 +199,9 @@ class Video
* Get all information about a video. * Get all information about a video.
* *
* @return stdClass Decoded JSON * @return stdClass Decoded JSON
* */ *
* @throws PasswordException
*/
public function getJson() public function getJson()
{ {
if (!isset($this->json)) { if (!isset($this->json)) {
@ -212,12 +217,15 @@ class Video
* @param string $name Property * @param string $name Property
* *
* @return mixed * @return mixed
* @throws PasswordException
*/ */
public function __get($name) public function __get($name)
{ {
if (isset($this->$name)) { if (isset($this->$name)) {
return $this->getJson()->$name; return $this->getJson()->$name;
} }
return null;
} }
/** /**
@ -226,6 +234,7 @@ class Video
* @param string $name Property * @param string $name Property
* *
* @return bool * @return bool
* @throws PasswordException
*/ */
public function __isset($name) public function __isset($name)
{ {
@ -240,7 +249,9 @@ class Video
* (eg. bestvideo+bestaudio). * (eg. bestvideo+bestaudio).
* *
* @return string[] URLs of video * @return string[] URLs of video
* */ * @throws EmptyUrlException
* @throws PasswordException
*/
public function getUrl() public function getUrl()
{ {
// Cache the URLs. // Cache the URLs.
@ -259,7 +270,9 @@ class Video
* Get filename of video file from URL of page. * Get filename of video file from URL of page.
* *
* @return string Filename of extracted video * @return string Filename of extracted video
* */ *
* @throws PasswordException
*/
public function getFilename() public function getFilename()
{ {
return trim($this->getProp('get-filename')); return trim($this->getProp('get-filename'));
@ -271,23 +284,17 @@ class Video
* @param string $extension New file extension * @param string $extension New file extension
* *
* @return string Filename of extracted video with specified extension * @return string Filename of extracted video with specified extension
* @throws PasswordException
*/ */
public function getFileNameWithExtension($extension) public function getFileNameWithExtension($extension)
{ {
return html_entity_decode( return str_replace('.' . $this->ext, '.' . $extension, $this->getFilename());
pathinfo(
$this->getFilename(),
PATHINFO_FILENAME
) . '.' . $extension,
ENT_COMPAT,
'ISO-8859-1'
);
} }
/** /**
* Return arguments used to run rtmp for a specific video. * Return arguments used to run rtmp for a specific video.
* *
* @return array Arguments * @return string[] Arguments
*/ */
private function getRtmpArguments() private function getRtmpArguments()
{ {
@ -296,12 +303,12 @@ class Video
if ($this->protocol == 'rtmp') { if ($this->protocol == 'rtmp') {
foreach ( foreach (
[ [
'url' => '-rtmp_tcurl', 'url' => '-rtmp_tcurl',
'webpage_url' => '-rtmp_pageurl', 'webpage_url' => '-rtmp_pageurl',
'player_url' => '-rtmp_swfverify', 'player_url' => '-rtmp_swfverify',
'flash_version' => '-rtmp_flashver', 'flash_version' => '-rtmp_flashver',
'play_path' => '-rtmp_playpath', 'play_path' => '-rtmp_playpath',
'app' => '-rtmp_app', 'app' => '-rtmp_app',
] as $property => $option ] as $property => $option
) { ) {
if (isset($this->{$property})) { if (isset($this->{$property})) {
@ -324,7 +331,7 @@ class Video
/** /**
* Check if a command runs successfully. * Check if a command runs successfully.
* *
* @param array $command Command and arguments * @param string[] $command Command and arguments
* *
* @return bool False if the command returns an error, true otherwise * @return bool False if the command returns an error, true otherwise
*/ */
@ -339,15 +346,15 @@ class Video
/** /**
* Get a process that runs avconv in order to convert a video. * Get a process that runs avconv in order to convert a video.
* *
* @param int $audioBitrate Audio bitrate of the converted file * @param int $audioBitrate Audio bitrate of the converted file
* @param string $filetype Filetype of the converted file * @param string $filetype Filetype of the converted file
* @param bool $audioOnly True to return an audio-only file * @param bool $audioOnly True to return an audio-only file
* @param string $from Start the conversion at this time * @param string $from Start the conversion at this time
* @param string $to End the conversion at this time * @param string $to End the conversion at this time
* *
* @return Process<string> Process
* @throws Exception If avconv/ffmpeg is missing * @throws Exception If avconv/ffmpeg is missing
* *
* @return Process Process
*/ */
private function getAvconvProcess( private function getAvconvProcess(
$audioBitrate, $audioBitrate,
@ -418,12 +425,12 @@ class Video
* Get audio stream of converted video. * Get audio stream of converted video.
* *
* @param string $from Start the conversion at this time * @param string $from Start the conversion at this time
* @param string $to End the conversion at this time * @param string $to End the conversion at this time
*
* @throws Exception If your try to convert an M3U8 video
* @throws Exception If the popen stream was not created correctly
* *
* @return resource popen stream * @return resource popen stream
* @throws Exception If the popen stream was not created correctly
*
* @throws Exception If your try to convert an M3U8 video
*/ */
public function getAudioStream($from = null, $to = null) public function getAudioStream($from = null, $to = null)
{ {
@ -453,10 +460,10 @@ class Video
/** /**
* Get video stream from an M3U playlist. * Get video stream from an M3U playlist.
* *
* @throws Exception If avconv/ffmpeg is missing * @return resource popen stream
* @throws Exception If the popen stream was not created correctly * @throws Exception If the popen stream was not created correctly
* *
* @return resource popen stream * @throws Exception If avconv/ffmpeg is missing
*/ */
public function getM3uStream() public function getM3uStream()
{ {
@ -495,9 +502,9 @@ class Video
/** /**
* Get an avconv stream to remux audio and video. * Get an avconv stream to remux audio and video.
* *
* @return resource popen stream
* @throws Exception If the popen stream was not created correctly * @throws Exception If the popen stream was not created correctly
* *
* @return resource popen stream
*/ */
public function getRemuxStream() public function getRemuxStream()
{ {
@ -532,9 +539,9 @@ class Video
/** /**
* Get video stream from an RTMP video. * Get video stream from an RTMP video.
* *
* @return resource popen stream
* @throws Exception If the popen stream was not created correctly * @throws Exception If the popen stream was not created correctly
* *
* @return resource popen stream
*/ */
public function getRtmpStream() public function getRtmpStream()
{ {
@ -565,13 +572,13 @@ class Video
/** /**
* Get the stream of a converted video. * Get the stream of a converted video.
* *
* @param int $audioBitrate Audio bitrate of the converted file * @param int $audioBitrate Audio bitrate of the converted file
* @param string $filetype Filetype of the converted file * @param string $filetype Filetype of the converted file
*
* @throws Exception If your try to convert and M3U8 video
* @throws Exception If the popen stream was not created correctly
* *
* @return resource popen stream * @return resource popen stream
* @throws Exception If the popen stream was not created correctly
*
* @throws Exception If your try to convert and M3U8 video
*/ */
public function getConvertedStream($audioBitrate, $filetype) public function getConvertedStream($audioBitrate, $filetype)
{ {
@ -605,21 +612,35 @@ class Video
/** /**
* Get a HTTP response containing the video. * Get a HTTP response containing the video.
* *
* @param array $headers HTTP headers of the request * @param mixed[] $headers HTTP headers of the request
* *
* @return Response * @return ResponseInterface
* @throws EmptyUrlException
* @throws PasswordException
* @link https://github.com/guzzle/guzzle/issues/2640
*/ */
public function getHttpResponse(array $headers = []) public function getHttpResponse(array $headers = [])
{ {
$client = new Client(); // IDN conversion breaks with Google hosts like https://r3---sn-25glene6.googlevideo.com/.
$client = new Client(['idn_conversion' => false]);
$urls = $this->getUrl(); $urls = $this->getUrl();
$stream_context_options = [];
if (array_key_exists('Referer', (array)$this->http_headers)) {
$stream_context_options = [
'http' => [
'header' => 'Referer: ' . $this->http_headers->Referer
]
];
}
return $client->request( return $client->request(
'GET', 'GET',
$urls[0], $urls[0],
[ [
'stream' => true, 'stream' => true,
'headers' => array_merge((array) $this->http_headers, $headers) 'stream_context' => $stream_context_options,
'headers' => array_merge((array)$this->http_headers, $headers)
] ]
); );
} }

View file

@ -10,6 +10,7 @@ use Psr\Container\ContainerInterface;
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Views\Smarty; use Slim\Views\Smarty;
use Slim\Views\SmartyPlugins; use Slim\Views\SmartyPlugins;
use SmartyException;
/** /**
* Create Smarty view object. * Create Smarty view object.
@ -20,14 +21,15 @@ class ViewFactory
* Create Smarty view object. * Create Smarty view object.
* *
* @param ContainerInterface $container Slim dependency container * @param ContainerInterface $container Slim dependency container
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* *
* @return Smarty * @return Smarty
* @throws SmartyException
*/ */
public static function create(ContainerInterface $container, Request $request = null) public static function create(ContainerInterface $container, Request $request = null)
{ {
if (!isset($request)) { if (!isset($request)) {
$request = $container['request']; $request = $container->get('request');
} }
$view = new Smarty(__DIR__ . '/../templates/'); $view = new Smarty(__DIR__ . '/../templates/');
@ -35,9 +37,10 @@ class ViewFactory
$request = $request->withUri($request->getUri()->withScheme('https')->withPort(443)); $request = $request->withUri($request->getUri()->withScheme('https')->withPort(443));
} }
$localeManager = $container['locale']; /** @var LocaleManager $localeManager */
$localeManager = $container->get('locale');
$smartyPlugins = new SmartyPlugins($container['router'], $request->getUri()->withUserInfo(null)); $smartyPlugins = new SmartyPlugins($container->get('router'), $request->getUri()->withUserInfo(null));
$view->registerPlugin('function', 'path_for', [$smartyPlugins, 'pathFor']); $view->registerPlugin('function', 'path_for', [$smartyPlugins, 'pathFor']);
$view->registerPlugin('function', 'base_url', [$smartyPlugins, 'baseUrl']); $view->registerPlugin('function', 'base_url', [$smartyPlugins, 'baseUrl']);
$view->registerPlugin('block', 't', [$localeManager, 'smartyTranslate']); $view->registerPlugin('block', 't', [$localeManager, 'smartyTranslate']);

View file

@ -7,6 +7,7 @@
namespace Alltube\Stream; namespace Alltube\Stream;
use Alltube\Video; use Alltube\Video;
use Exception;
use Slim\Http\Stream; use Slim\Http\Stream;
/** /**
@ -20,6 +21,7 @@ class ConvertedPlaylistArchiveStream extends PlaylistArchiveStream
* @param Video $video Video to stream * @param Video $video Video to stream
* *
* @return void * @return void
* @throws Exception
*/ */
protected function startVideoStream(Video $video) protected function startVideoStream(Video $video)
{ {

View file

@ -6,6 +6,8 @@
namespace Alltube\Stream; namespace Alltube\Stream;
use Alltube\Exception\EmptyUrlException;
use Alltube\Exception\PasswordException;
use Alltube\Video; use Alltube\Video;
use Barracuda\ArchiveStream\ZipArchive; use Barracuda\ArchiveStream\ZipArchive;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
@ -48,7 +50,10 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
/** /**
* PlaylistArchiveStream constructor. * PlaylistArchiveStream constructor.
* *
* We don't call the parent constructor because it messes up the output buffering.
*
* @param Video $video Video/playlist to download * @param Video $video Video/playlist to download
* @noinspection PhpMissingParentConstructorInspection
*/ */
public function __construct(Video $video) public function __construct(Video $video)
{ {
@ -86,20 +91,21 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
* *
* @param string $string The string that is to be written * @param string $string The string that is to be written
* *
* @return int * @return int|false
*/ */
public function write($string) public function write($string)
{ {
fwrite($this->buffer, $string); return fwrite($this->buffer, $string);
} }
/** /**
* Get the size of the stream if known. * Get the size of the stream if known.
* *
* @return null * @return int|null
*/ */
public function getSize() public function getSize()
{ {
return null;
} }
/** /**
@ -145,7 +151,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
/** /**
* Returns the remaining contents in a string. * Returns the remaining contents in a string.
* *
* @return string * @return string|false
*/ */
public function getContents() public function getContents()
{ {
@ -170,6 +176,8 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
if (isset($meta[$key])) { if (isset($meta[$key])) {
return $meta[$key]; return $meta[$key];
} }
return null;
} }
/** /**
@ -194,7 +202,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
{ {
$this->rewind(); $this->rewind();
return $this->getContents(); return strval($this->getContents());
} }
/** /**
@ -236,6 +244,8 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
* @param Video $video Video to stream * @param Video $video Video to stream
* *
* @return void * @return void
* @throws PasswordException
* @throws EmptyUrlException
*/ */
protected function startVideoStream(Video $video) protected function startVideoStream(Video $video)
{ {
@ -246,7 +256,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
$this->init_file_stream_transfer( $this->init_file_stream_transfer(
$video->getFilename(), $video->getFilename(),
$contentLengthHeaders[0] intval($contentLengthHeaders[0])
); );
} }
@ -256,6 +266,8 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
* @param int $count Number of bytes to read * @param int $count Number of bytes to read
* *
* @return string|false * @return string|false
* @throws EmptyUrlException
* @throws PasswordException
*/ */
public function read($count) public function read($count)
{ {

View file

@ -6,7 +6,7 @@
namespace Alltube\Stream; namespace Alltube\Stream;
use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
/** /**
@ -18,16 +18,16 @@ class YoutubeChunkStream implements StreamInterface
/** /**
* HTTP response containing the video chunk. * HTTP response containing the video chunk.
* *
* @var Response * @var ResponseInterface
*/ */
private $response; private $response;
/** /**
* YoutubeChunkStream constructor. * YoutubeChunkStream constructor.
* *
* @param Response $response HTTP response containing the video chunk * @param ResponseInterface $response HTTP response containing the video chunk
*/ */
public function __construct(Response $response) public function __construct(ResponseInterface $response)
{ {
$this->response = $response; $this->response = $response;
} }
@ -41,7 +41,7 @@ class YoutubeChunkStream implements StreamInterface
*/ */
public function read($length) public function read($length)
{ {
$size = $this->response->getHeader('Content-Length')[0]; $size = intval($this->response->getHeader('Content-Length')[0]);
if ($size - $this->tell() < $length) { if ($size - $this->tell() < $length) {
// Don't try to read further than the end of the stream. // Don't try to read further than the end of the stream.
$length = $size - $this->tell(); $length = $size - $this->tell();
@ -55,7 +55,7 @@ class YoutubeChunkStream implements StreamInterface
*/ */
public function __toString() public function __toString()
{ {
return (string) $this->response->getBody(); return (string)$this->response->getBody();
} }
/** /**
@ -124,21 +124,21 @@ class YoutubeChunkStream implements StreamInterface
* @param int $offset Stream offset * @param int $offset Stream offset
* @param int $whence Specifies how the cursor position will be calculated * @param int $whence Specifies how the cursor position will be calculated
* *
* @return mixed * @return void
*/ */
public function seek($offset, $whence = SEEK_SET) public function seek($offset, $whence = SEEK_SET)
{ {
return $this->response->getBody()->seek($offset, $whence); $this->response->getBody()->seek($offset, $whence);
} }
/** /**
* Seek to the beginning of the stream. * Seek to the beginning of the stream.
* *
* @return mixed * @return void
*/ */
public function rewind() public function rewind()
{ {
return $this->response->getBody()->rewind(); $this->response->getBody()->rewind();
} }
/** /**

View file

@ -6,6 +6,8 @@
namespace Alltube\Stream; namespace Alltube\Stream;
use Alltube\Exception\EmptyUrlException;
use Alltube\Exception\PasswordException;
use Alltube\Video; use Alltube\Video;
use GuzzleHttp\Psr7\AppendStream; use GuzzleHttp\Psr7\AppendStream;
@ -19,6 +21,8 @@ class YoutubeStream extends AppendStream
* YoutubeStream constructor. * YoutubeStream constructor.
* *
* @param Video $video Video to stream * @param Video $video Video to stream
* @throws EmptyUrlException
* @throws PasswordException
*/ */
public function __construct(Video $video) public function __construct(Video $video)
{ {
@ -31,7 +35,7 @@ class YoutubeStream extends AppendStream
while ($rangeStart < $contentLenghtHeader[0]) { while ($rangeStart < $contentLenghtHeader[0]) {
$rangeEnd = $rangeStart + $video->downloader_options->http_chunk_size; $rangeEnd = $rangeStart + $video->downloader_options->http_chunk_size;
if ($rangeEnd >= $contentLenghtHeader[0]) { if ($rangeEnd >= $contentLenghtHeader[0]) {
$rangeEnd = $contentLenghtHeader[0] - 1; $rangeEnd = intval($contentLenghtHeader[0]) - 1;
} }
$response = $video->getHttpResponse(['Range' => 'bytes=' . $rangeStart . '-' . $rangeEnd]); $response = $video->getHttpResponse(['Range' => 'bytes=' . $rangeStart . '-' . $rangeEnd]);
$this->addStream(new YoutubeChunkStream($response)); $this->addStream(new YoutubeChunkStream($response));

View file

@ -5,34 +5,35 @@
"homepage": "http://alltubedownload.net/", "homepage": "http://alltubedownload.net/",
"type": "project", "type": "project",
"require": { "require": {
"aura/session": "~2.1.0", "ext-intl": "*",
"barracudanetworks/archivestream-php": "~1.0.5", "ext-json": "*",
"guzzlehttp/guzzle": "~6.3.0", "aura/session": "^2.1",
"barracudanetworks/archivestream-php": "^1.0",
"guzzlehttp/guzzle": "^6.5",
"jawira/case-converter": "^3.4", "jawira/case-converter": "^3.4",
"mathmarques/smarty-view": "~1.1.0", "mathmarques/smarty-view": "^1.1",
"npm-asset/open-sans-fontface": "^1.4", "npm-asset/open-sans-fontface": "^1.4",
"rinvex/countries": "~3.1.0", "rinvex/countries": "^6.1",
"slim/slim": "~3.12.1",
"symfony/process": "^4.0", "symfony/process": "^4.0",
"symfony/translation": "^4.0", "symfony/translation": "^4.0",
"symfony/yaml": "^4.0", "symfony/yaml": "^4.0",
"zonuexe/http-accept-language": "~0.4.1" "zonuexe/http-accept-language": "^0.4.1"
}, },
"require-dev": { "require-dev": {
"anam/phantomjs-linux-x86-binary": "~2.1.1", "anam/phantomjs-linux-x86-binary": "^2.1",
"consolidation/robo": "^2.0", "consolidation/robo": "^2.0",
"ffmpeg/ffmpeg": "^4.1", "ffmpeg/ffmpeg": "^4.1",
"heroku/heroku-buildpack-php": "^162.0", "heroku/heroku-buildpack-php": "^162.0",
"php-mock/php-mock-mockery": "^1.3", "php-mock/php-mock-mockery": "^1.3",
"phpro/grumphp": "^0.17.0", "phpro/grumphp": "^0.18.0",
"phpstan/phpstan": "~0.9.2", "phpstan/phpstan": "^0.12.25",
"phpunit/phpunit": "^8.4", "phpunit/phpunit": "^8.4",
"roave/security-advisories": "dev-master", "roave/security-advisories": "dev-master",
"smarty-gettext/smarty-gettext": "^1.6", "smarty-gettext/smarty-gettext": "^1.6",
"squizlabs/php_codesniffer": "^3.5", "squizlabs/php_codesniffer": "^3.5",
"symfony/debug": "^4.0", "symfony/error-handler": "^5.0",
"symfony/var-dumper": "^4.0", "symfony/var-dumper": "^5.0",
"ytdl-org/youtube-dl": "^2020.02" "ytdl-org/youtube-dl": "^2020.05"
}, },
"extra": { "extra": {
"paas": { "paas": {
@ -50,10 +51,10 @@
"type": "package", "type": "package",
"package": { "package": {
"name": "ytdl-org/youtube-dl", "name": "ytdl-org/youtube-dl",
"version": "2020.02.16", "version": "2020.05.08",
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://github.com/ytdl-org/youtube-dl/archive/2020.02.16.zip" "url": "https://github.com/ytdl-org/youtube-dl/archive/2020.05.08.zip"
} }
} }
}, },

778
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -66,10 +66,12 @@ class DownloadController extends BaseController
/** /**
* Return a converted MP3 file. * Return a converted MP3 file.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
* @throws PasswordException
* @throws Exception
*/ */
private function getConvertedAudioResponse(Request $request, Response $response) private function getConvertedAudioResponse(Request $request, Response $response)
{ {
@ -100,10 +102,11 @@ class DownloadController extends BaseController
/** /**
* Return the MP3 file. * Return the MP3 file.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
* @throws PasswordException
*/ */
private function getAudioResponse(Request $request, Response $response) private function getAudioResponse(Request $request, Response $response)
{ {
@ -130,7 +133,7 @@ class DownloadController extends BaseController
return $frontController->password($request, $response); return $frontController->password($request, $response);
} catch (Exception $e) { } catch (Exception $e) {
// If MP3 is not available, we convert it. // If MP3 is not available, we convert it.
$this->video = $this->video->withFormat('bestaudio'); $this->video = $this->video->withFormat('bestaudio/best');
return $this->getConvertedAudioResponse($request, $response); return $this->getConvertedAudioResponse($request, $response);
} }
@ -139,10 +142,13 @@ class DownloadController extends BaseController
/** /**
* Get a video/audio stream piped through the server. * Get a video/audio stream piped through the server.
* *
* @param Response $response PSR-7 response * @param Request $request PSR-7 request
* @param Request $request PSR-7 request
* *
* @param Response $response PSR-7 response
* @return Response HTTP response * @return Response HTTP response
* @throws EmptyUrlException
* @throws PasswordException
* @throws Exception
*/ */
private function getStream(Request $request, Response $response) private function getStream(Request $request, Response $response)
{ {
@ -205,9 +211,11 @@ class DownloadController extends BaseController
* Get a remuxed stream piped through the server. * Get a remuxed stream piped through the server.
* *
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* *
* @return Response HTTP response * @return Response HTTP response
* @throws PasswordException
* @throws Exception
*/ */
private function getRemuxStream(Request $request, Response $response) private function getRemuxStream(Request $request, Response $response)
{ {
@ -230,10 +238,13 @@ class DownloadController extends BaseController
* Get approriate HTTP response to download query. * Get approriate HTTP response to download query.
* Depends on whether we want to stream, remux or simply redirect. * Depends on whether we want to stream, remux or simply redirect.
* *
* @param Response $response PSR-7 response * @param Request $request PSR-7 request
* @param Request $request PSR-7 request
* *
* @param Response $response PSR-7 response
* @return Response HTTP response * @return Response HTTP response
* @throws EmptyUrlException
* @throws PasswordException
* @throws Exception
*/ */
private function getDownloadResponse(Request $request, Response $response) private function getDownloadResponse(Request $request, Response $response)
{ {
@ -262,10 +273,12 @@ class DownloadController extends BaseController
/** /**
* Return a converted video file. * Return a converted video file.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
* @throws PasswordException
* @throws Exception
*/ */
private function getConvertedResponse(Request $request, Response $response) private function getConvertedResponse(Request $request, Response $response)
{ {

View file

@ -9,15 +9,15 @@ namespace Alltube\Controller;
use Alltube\Exception\PasswordException; use Alltube\Exception\PasswordException;
use Alltube\Locale; use Alltube\Locale;
use Alltube\Video; use Alltube\Video;
use Symfony\Component\ErrorHandler\ErrorHandler;
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Throwable; use Throwable;
use Exception; use Exception;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Slim\Container;
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Http\Response; use Slim\Http\Response;
use Slim\Views\Smarty; use Slim\Views\Smarty;
use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\Debug\Exception\FlattenException;
/** /**
* Main controller. * Main controller.
@ -46,7 +46,7 @@ class FrontController extends BaseController
/** /**
* Display index page. * Display index page.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
@ -58,15 +58,15 @@ class FrontController extends BaseController
$response, $response,
'index.tpl', 'index.tpl',
[ [
'config' => $this->config, 'config' => $this->config,
'class' => 'index', 'class' => 'index',
'description' => $this->localeManager->t( 'description' => $this->localeManager->t(
'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.' 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.'
), ),
'domain' => $uri->getScheme() . '://' . $uri->getAuthority(), 'domain' => $uri->getScheme() . '://' . $uri->getAuthority(),
'canonical' => $this->getCanonicalUrl($request), 'canonical' => $this->getCanonicalUrl($request),
'supportedLocales' => $this->localeManager->getSupportedLocales(), 'supportedLocales' => $this->localeManager->getSupportedLocales(),
'locale' => $this->localeManager->getLocale(), 'locale' => $this->localeManager->getLocale(),
] ]
); );
@ -76,9 +76,9 @@ class FrontController extends BaseController
/** /**
* Switch locale. * Switch locale.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* @param array $data Query parameters * @param string[] $data Query parameters
* *
* @return Response * @return Response
*/ */
@ -92,10 +92,11 @@ class FrontController extends BaseController
/** /**
* Display a list of extractors. * Display a list of extractors.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
* @throws PasswordException
*/ */
public function extractors(Request $request, Response $response) public function extractors(Request $request, Response $response)
{ {
@ -103,14 +104,14 @@ class FrontController extends BaseController
$response, $response,
'extractors.tpl', 'extractors.tpl',
[ [
'config' => $this->config, 'config' => $this->config,
'extractors' => Video::getExtractors(), 'extractors' => Video::getExtractors(),
'class' => 'extractors', 'class' => 'extractors',
'title' => $this->localeManager->t('Supported websites'), 'title' => $this->localeManager->t('Supported websites'),
'description' => $this->localeManager->t('List of all supported websites from which Alltube Download ' . 'description' => $this->localeManager->t('List of all supported websites from which Alltube Download ' .
'can extract video or audio files'), 'can extract video or audio files'),
'canonical' => $this->getCanonicalUrl($request), 'canonical' => $this->getCanonicalUrl($request),
'locale' => $this->localeManager->getLocale(), 'locale' => $this->localeManager->getLocale(),
] ]
); );
@ -120,7 +121,7 @@ class FrontController extends BaseController
/** /**
* Display a password prompt. * Display a password prompt.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
@ -131,14 +132,14 @@ class FrontController extends BaseController
$response, $response,
'password.tpl', 'password.tpl',
[ [
'config' => $this->config, 'config' => $this->config,
'class' => 'password', 'class' => 'password',
'title' => $this->localeManager->t('Password prompt'), 'title' => $this->localeManager->t('Password prompt'),
'description' => $this->localeManager->t( 'description' => $this->localeManager->t(
'You need a password in order to download this video with Alltube Download' 'You need a password in order to download this video with Alltube Download'
), ),
'canonical' => $this->getCanonicalUrl($request), 'canonical' => $this->getCanonicalUrl($request),
'locale' => $this->localeManager->getLocale(), 'locale' => $this->localeManager->getLocale(),
] ]
); );
@ -148,7 +149,7 @@ class FrontController extends BaseController
/** /**
* Return the video description page. * Return the video description page.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
@ -185,13 +186,13 @@ class FrontController extends BaseController
$response, $response,
$template, $template,
[ [
'video' => $this->video, 'video' => $this->video,
'class' => 'info', 'class' => 'info',
'title' => $title, 'title' => $title,
'description' => $description, 'description' => $description,
'config' => $this->config, 'config' => $this->config,
'canonical' => $this->getCanonicalUrl($request), 'canonical' => $this->getCanonicalUrl($request),
'locale' => $this->localeManager->getLocale(), 'locale' => $this->localeManager->getLocale(),
'defaultFormat' => $this->defaultFormat, 'defaultFormat' => $this->defaultFormat,
] ]
); );
@ -202,7 +203,7 @@ class FrontController extends BaseController
/** /**
* Dislay information about the video. * Dislay information about the video.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return Response HTTP response
@ -231,18 +232,18 @@ class FrontController extends BaseController
/** /**
* Display an error page. * Display an error page.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* @param Throwable $error Error to display * @param Throwable $error Error to display
* *
* @return Response HTTP response * @return Response HTTP response
*/ */
public function error(Request $request, Response $response, Throwable $error) public function error(Request $request, Response $response, Throwable $error)
{ {
if ($this->config->debug) { if ($this->config->debug) {
$exception = FlattenException::createFromThrowable($error); $renderer = new HtmlErrorRenderer(true);
$handler = new ExceptionHandler(); $exception = $renderer->render($error);
$response->getBody()->write($handler->getHtml($exception)); $response->getBody()->write($exception->getAsString());
return $response->withStatus($exception->getStatusCode()); return $response->withStatus($exception->getStatusCode());
} else { } else {
@ -256,12 +257,12 @@ class FrontController extends BaseController
$response, $response,
'error.tpl', 'error.tpl',
[ [
'config' => $this->config, 'config' => $this->config,
'error' => $message, 'error' => $message,
'class' => 'video', 'class' => 'video',
'title' => $this->localeManager->t('Error'), 'title' => $this->localeManager->t('Error'),
'canonical' => $this->getCanonicalUrl($request), 'canonical' => $this->getCanonicalUrl($request),
'locale' => $this->localeManager->getLocale(), 'locale' => $this->localeManager->getLocale(),
] ]
); );

View file

@ -1,17 +1,16 @@
--- ---
parameters: parameters:
ascii: ~ ascii: ~
tasks: tasks:
jsonlint: ~ jsonlint: ~
xmllint: ~ xmllint: ~
yamllint: ~ yamllint: ~
composer: ~ composer: ~
phpcs: phpcs:
standard: PSR12 standard: PSR12
ignore_patterns: ignore_patterns:
- RoboFile.php - RoboFile.php
phpstan: phpstan:
level: max level: max
configuration: phpstan.neon ignore_patterns:
ignore_patterns: - RoboFile.php
- RoboFile.php

View file

@ -1,6 +1,7 @@
<?php <?php
require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/vendor/autoload.php';
use Alltube\Config; use Alltube\Config;
use Alltube\Controller\DownloadController; use Alltube\Controller\DownloadController;
use Alltube\Controller\FrontController; use Alltube\Controller\FrontController;
@ -10,7 +11,8 @@ use Alltube\LocaleMiddleware;
use Alltube\UglyRouter; use Alltube\UglyRouter;
use Alltube\ViewFactory; use Alltube\ViewFactory;
use Slim\App; use Slim\App;
use Symfony\Component\Debug\Debug; use Slim\Container;
use Symfony\Component\ErrorHandler\Debug;
if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/index.php') !== false) { if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/index.php') !== false) {
header('Location: ' . str_ireplace('/index.php', '/', $_SERVER['REQUEST_URI'])); header('Location: ' . str_ireplace('/index.php', '/', $_SERVER['REQUEST_URI']));
@ -18,11 +20,17 @@ if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/index.ph
} }
if (is_file(__DIR__ . '/config/config.yml')) { if (is_file(__DIR__ . '/config/config.yml')) {
Config::setFile(__DIR__ . '/config/config.yml'); try {
Config::setFile(__DIR__ . '/config/config.yml');
} catch (Exception $e) {
die('Could not load config file: ' . $e->getMessage());
}
} }
// Create app. // Create app.
$app = new App(); $app = new App();
/** @var Container $container */
$container = $app->getContainer(); $container = $app->getContainer();
// Load config. // Load config.
@ -47,7 +55,11 @@ $container['locale'] = LocaleManager::getInstance();
$app->add(new LocaleMiddleware($container)); $app->add(new LocaleMiddleware($container));
// Smarty. // Smarty.
$container['view'] = ViewFactory::create($container); try {
$container['view'] = ViewFactory::create($container);
} catch (SmartyException $e) {
die('Could not load Smarty: ' . $e->getMessage());
}
// Controllers. // Controllers.
$frontController = new FrontController($container); $frontController = new FrontController($container);
@ -102,4 +114,7 @@ try {
$app->run(); $app->run();
} catch (SmartyException $e) { } catch (SmartyException $e) {
die('Smarty could not compile the template file: ' . $e->getMessage()); die('Smarty could not compile the template file: ' . $e->getMessage());
} catch (Throwable $e) {
// Last resort if the error has not been caught by the error handler for some reason.
die('Error when starting the app: ' . $e->getMessage());
} }

View file

@ -1,4 +0,0 @@
parameters:
ignoreErrors:
# The Archive constructor messes up the output buffering.
- '#Alltube\\Stream\\PlaylistArchiveStream::__construct\(\) does not call parent constructor from Barracuda\\ArchiveStream\\ZipArchive\.#'

View file

@ -1,18 +1,18 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<phpunit bootstrap="tests/bootstrap.php"> <phpunit bootstrap="tests/bootstrap.php">
<filter> <filter>
<whitelist> <whitelist>
<directory>classes/</directory> <directory>classes/</directory>
<directory>controllers/</directory> <directory>controllers/</directory>
</whitelist> </whitelist>
</filter> </filter>
<testsuites> <testsuites>
<testsuite name="Tests"> <testsuite name="Tests">
<directory>tests/</directory> <directory>tests/</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<logging> <logging>
<log type="coverage-html" target="coverage/"/> <log type="coverage-html" target="coverage/"/>
<log type="coverage-clover" target="clover.xml"/> <log type="coverage-clover" target="clover.xml"/>
</logging> </logging>
</phpunit> </phpunit>

View file

@ -1,21 +1,23 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!DOCTYPE HTML> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>AllTube Download - Maintenance</title> <title>AllTube Download - Maintenance</title>
<link rel="stylesheet" href="../dist/main.css"/> <link rel="stylesheet" href="../dist/main.css"/>
<link rel="icon" href="../img/favicon.png"/> <link rel="icon" href="../img/favicon.png"/>
</head> </head>
<body> <body>
<div class="wrapper"> <div class="wrapper">
<div class="main"> <div class="main">
<h1> <h1>
<img class="logo" src="../img/logo.png" alt="AllTube Download" width="328" height="284"/> <img class="logo" src="../img/logo.png" alt="AllTube Download" width="328" height="284"/>
</h1> </h1>
<div>An error occurred in the application and your page could not be served. Please try again in a few moments.</div> <div>An error occurred in the application and your page could not be served. Please try again in a few
</div> moments.
</div>
</div> </div>
</body> </div>
</body>
</html> </html>

View file

@ -1,21 +1,21 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!DOCTYPE HTML> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>AllTube Download - Maintenance</title> <title>AllTube Download - Maintenance</title>
<link rel="stylesheet" href="../dist/main.css"/> <link rel="stylesheet" href="../dist/main.css"/>
<link rel="icon" href="../img/favicon.png"/> <link rel="icon" href="../img/favicon.png"/>
</head> </head>
<body> <body>
<div class="wrapper"> <div class="wrapper">
<div class="main"> <div class="main">
<h1> <h1>
<img class="logo" src="../img/logo.png" alt="AllTube Download" width="328" height="284"/> <img class="logo" src="../img/logo.png" alt="AllTube Download" width="328" height="284"/>
</h1> </h1>
<div>This application is undergoing maintenance right now. Please check back later.</div> <div>This application is undergoing maintenance right now. Please check back later.</div>
</div>
</div> </div>
</body> </div>
</body>
</html> </html>

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url> <url>
<loc>https://alltubedownload.net/</loc> <loc>https://alltubedownload.net/</loc>
<changefreq>yearly</changefreq> <changefreq>yearly</changefreq>
<priority>1</priority> <priority>1</priority>
</url> </url>
<url> <url>
<loc>https://alltubedownload.net/extractors</loc> <loc>https://alltubedownload.net/extractors</loc>
<changefreq>weekly</changefreq> <changefreq>weekly</changefreq>
</url> </url>
</urlset> </urlset>

View file

@ -6,4 +6,4 @@
{t}Please check the URL of your video.{/t} {t}Please check the URL of your video.{/t}
<p><i>{$error|escape}</i></p> <p><i>{$error|escape}</i></p>
</main> </main>
{include file='inc/footer.tpl'} {include file='inc/footer.tpl'}

View file

@ -3,10 +3,10 @@
{include file='inc/logo.tpl'} {include file='inc/logo.tpl'}
<h2 class="titre">{t}Supported websites{/t}</h2> <h2 class="titre">{t}Supported websites{/t}</h2>
<div class="tripleliste"> <div class="tripleliste">
<ul> <ul>
{foreach $extractors as $extractor} {foreach $extractors as $extractor}
<li>{$extractor}</li> <li>{$extractor}</li>
{/foreach} {/foreach}
</ul> </ul>
</div> </div>
{include file='inc/footer.tpl'} {include file='inc/footer.tpl'}

View file

@ -31,7 +31,7 @@
&middot; &middot;
<a rel="noopener" target="_blank" title="{t}Donate using Liberapay{/t}" <a rel="noopener" target="_blank" title="{t}Donate using Liberapay{/t}"
href="https://liberapay.com/Rudloff/donate"> href="https://liberapay.com/Rudloff/donate">
{t}Donate{/t} {t}Donate{/t}
</a> </a>
</div> </div>

View file

@ -1,25 +1,25 @@
<!doctype html> <!doctype html>
<html {if isset($locale)}lang="{$locale->getBcp47()}"{/if}> <html {if isset($locale)}lang="{$locale->getBcp47()}"{/if}>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8"/>
<meta name=viewport content="width=device-width, initial-scale=1"> <meta name=viewport content="width=device-width, initial-scale=1">
{if isset($description)} {if isset($description)}
<meta name="description" content="{$description|escape}" /> <meta name="description" content="{$description|escape}"/>
<meta name="twitter:description" content="{$description|escape}" /> <meta name="twitter:description" content="{$description|escape}"/>
<meta property="og:description" content="{$description|escape}" /> <meta property="og:description" content="{$description|escape}"/>
{/if} {/if}
<link rel="stylesheet" href="{base_url}/css/fonts.css" /> <link rel="stylesheet" href="{base_url}/css/fonts.css"/>
<link rel="stylesheet" href="{base_url}/css/style.css" /> <link rel="stylesheet" href="{base_url}/css/style.css"/>
<title>{$config->appName}{if isset($title)} - {$title|escape}{/if}</title> <title>{$config->appName}{if isset($title)} - {$title|escape}{/if}</title>
<link rel="canonical" href="{$canonical}" /> <link rel="canonical" href="{$canonical}"/>
<link rel="icon" href="{base_url}/img/favicon.png" /> <link rel="icon" href="{base_url}/img/favicon.png"/>
<meta property="og:title" content="{$config->appName}{if isset($title)} - {$title|escape}{/if}" /> <meta property="og:title" content="{$config->appName}{if isset($title)} - {$title|escape}{/if}"/>
<meta property="og:image" content="{base_url}/img/logo.png" /> <meta property="og:image" content="{base_url}/img/logo.png"/>
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="{$config->appName}{if isset($title)} - {$title|escape}{/if}" /> <meta name="twitter:title" content="{$config->appName}{if isset($title)} - {$title|escape}{/if}"/>
<meta name="twitter:image" content="{base_url}/img/logo.png" /> <meta name="twitter:image" content="{base_url}/img/logo.png"/>
<meta name="twitter:creator" content="@Tael67" /> <meta name="twitter:creator" content="@Tael67"/>
<meta name="theme-color" content="#4F4F4F"> <meta name="theme-color" content="#4F4F4F">
<link rel="manifest" href="{base_url}/resources/manifest.json" /> <link rel="manifest" href="{base_url}/resources/manifest.json"/>
</head> </head>
<body class="{$class}"> <body class="{$class}">

View file

@ -13,8 +13,8 @@
{if $supportedLocale != $locale} {if $supportedLocale != $locale}
<li> <li>
<a hreflang="{$supportedLocale->getBcp47()}" <a hreflang="{$supportedLocale->getBcp47()}"
lang="{$supportedLocale->getBcp47()}" lang="{$supportedLocale->getBcp47()}"
href="{path_for name='locale' data=['locale'=>$supportedLocale->getIso15897()]}"> href="{path_for name='locale' data=['locale'=>$supportedLocale->getIso15897()]}">
{if $supportedLocale->getCountry()} {if $supportedLocale->getCountry()}
{$supportedLocale->getCountry()->getEmoji()} {$supportedLocale->getCountry()->getEmoji()}
{/if} {/if}

View file

@ -1,4 +1,5 @@
<h1 class="logobis"> <h1 class="logobis">
<a class="logocompatible" href="{base_url}"> <a class="logocompatible" href="{base_url}">
<span class="logocompatiblemask"><img src="{base_url}/img/logocompatiblemask.png" width="447" height="107" alt="{$config->appName}" /></span> <span class="logocompatiblemask"><img src="{base_url}/img/logocompatiblemask.png" width="447" height="107"
</a></h1> alt="{$config->appName}"/></span>
</a></h1>

View file

@ -2,41 +2,45 @@
{include file='inc/header.tpl'} {include file='inc/header.tpl'}
<main class="main"> <main class="main">
<div><img class="logo" src="{base_url}/img/logo.png" <div><img class="logo" src="{base_url}/img/logo.png"
alt="{$config->appName}" width="328" height="284"></div> alt="{$config->appName}" width="328" height="284"></div>
<form action="{path_for name="info"}"> <form action="{path_for name="info"}">
<label class="labelurl" for="url"> <label class="labelurl" for="url">
{t}Copy here the URL of your video (Youtube, Dailymotion, etc.){/t} {t}Copy here the URL of your video (Youtube, Dailymotion, etc.){/t}
</label> </label>
<div class="champs"> <div class="champs">
<span class="URLinput_wrapper"> <span class="URLinput_wrapper">
<!-- We used to have an autofocus attribute on this field but it triggerd a very specific CSS bug: https://github.com/Rudloff/alltube/issues/117 --> <!-- We used to have an autofocus attribute on this field but it triggerd a very specific CSS bug: https://github.com/Rudloff/alltube/issues/117 -->
<input class="URLinput large-font" type="url" name="url" id="url" <input class="URLinput large-font" type="url" name="url" id="url"
required placeholder="http://example.com/video" /> required placeholder="http://example.com/video"/>
</span> </span>
{if $config->uglyUrls} {if $config->uglyUrls}
<input type="hidden" name="page" value="info" /> <input type="hidden" name="page" value="info"/>
{/if} {/if}
<input class="downloadBtn large-font" type="submit" value="{t}Download{/t}" /><br/> <input class="downloadBtn large-font" type="submit" value="{t}Download{/t}"/><br/>
{if $config->convert} {if $config->convert}
<div class="mp3 small-font"> <div class="mp3 small-font">
<div class="mp3-inner"> <div class="mp3-inner">
<input type="checkbox" id="audio" class="audio" name="audio"> <input type="checkbox" id="audio" class="audio" name="audio">
<label for="audio"><span class="ui"></span> <label for="audio"><span class="ui"></span>
{t}Audio only (MP3){/t} {t}Audio only (MP3){/t}
</label> </label>
<div class="seekOptions"> <div class="seekOptions">
<label for="from">{t}From{/t}</label> <input type="text" pattern="(\d+:)?(\d+:)?\d+(\.\d+)?" placeholder="HH:MM:SS" value="" name="from" id="from" /> <label for="from">{t}From{/t}</label> <input type="text" pattern="(\d+:)?(\d+:)?\d+(\.\d+)?"
<label for="to">{t}to{/t}</label> <input type="text" pattern="(\d+:)?(\d+:)?\d+(\.\d+)?" placeholder="HH:MM:SS" value="" name="to" id="to" /> placeholder="HH:MM:SS" value="" name="from"
id="from"/>
<label for="to">{t}to{/t}</label> <input type="text" pattern="(\d+:)?(\d+:)?\d+(\.\d+)?"
placeholder="HH:MM:SS" value="" name="to" id="to"/>
</div>
</div> </div>
</div> </div>
</div> {/if}
{/if} </div>
</div>
</form> </form>
<a class="combatiblelink small-font" href="{path_for name="extractors"}">{t}See all supported websites{/t}</a> <a class="combatiblelink small-font" href="{path_for name="extractors"}">{t}See all supported websites{/t}</a>
<div id="bookmarklet" class="bookmarklet_wrapper"> <div id="bookmarklet" class="bookmarklet_wrapper">
<p> {t}Drag this to your bookmarks bar:{/t} </p> <p> {t}Drag this to your bookmarks bar:{/t} </p>
<a class="bookmarklet small-font" href="javascript:window.location='{$domain}{path_for name='info'}?url='+encodeURIComponent(location.href);">{t}Bookmarklet{/t}</a> <a class="bookmarklet small-font"
href="javascript:window.location='{$domain}{path_for name='info'}?url='+encodeURIComponent(location.href);">{t}Bookmarklet{/t}</a>
</div> </div>
</main> </main>

View file

@ -1,100 +1,105 @@
{include file="inc/head.tpl"} {include file="inc/head.tpl"}
<div class="wrapper"> <div class="wrapper">
<div itemscope itemtype="http://schema.org/VideoObject"> <div itemscope itemtype="http://schema.org/VideoObject">
<main class="main"> <main class="main">
{include file="inc/logo.tpl"} {include file="inc/logo.tpl"}
{$title="<i itemprop='name'> {$title="<i itemprop='name'>
<a itemprop='url' id='video_link' <a itemprop='url' id='video_link'
href='{$video->webpage_url}'> href='{$video->webpage_url}'>
{$video->title}</a></i>"} {$video->title}</a></i>"}
<p id="download_intro"> <p id="download_intro">
{t params=['@title' => $title]}You are going to download @title.{/t} {t params=['@title' => $title]}You are going to download @title.{/t}
</p> </p>
{if isset($video->thumbnail)} {if isset($video->thumbnail)}
<img itemprop="thumbnailUrl" class="thumb" src="{$video->thumbnail}" alt="" /> <img itemprop="thumbnailUrl" class="thumb" src="{$video->thumbnail}" alt=""/>
{/if} {/if}
{if isset($video->description)} {if isset($video->description)}
<meta itemprop="description" content="{$video->description|escape}" /> <meta itemprop="description" content="{$video->description|escape}"/>
{/if} {/if}
{if isset($video->upload_date)} {if isset($video->upload_date)}
<meta itemprop="uploadDate" content="{$video->upload_date}" /> <meta itemprop="uploadDate" content="{$video->upload_date}"/>
{/if} {/if}
<br/> <br/>
<form action="{path_for name="download"}"> <form action="{path_for name="download"}">
<input type="hidden" name="url" value="{$video->webpage_url}" /> <input type="hidden" name="url" value="{$video->webpage_url}"/>
{if $config->uglyUrls} {if $config->uglyUrls}
<input type="hidden" name="page" value="download" /> <input type="hidden" name="page" value="download"/>
{/if} {/if}
{if isset($video->formats) && count($video->formats) > 1} {if isset($video->formats) && count($video->formats) > 1}
<h3><label for="format">{t}Available formats:{/t}</label></h3> <h3><label for="format">{t}Available formats:{/t}</label></h3>
<select name="format" id="format" class="formats monospace"> <select name="format" id="format" class="formats monospace">
<optgroup label="{t}Generic formats{/t}"> <optgroup label="{t}Generic formats{/t}">
{foreach $config->genericFormats as $format => $name} {foreach $config->genericFormats as $format => $name}
<option value="{$format}">{t}{$name}{/t}</option> <option value="{$format}">{t}{$name}{/t}</option>
{/foreach} {/foreach}
</optgroup> </optgroup>
<optgroup label="{t}Detailed formats{/t}" class="monospace"> <optgroup label="{t}Detailed formats{/t}" class="monospace">
{foreach $video->formats as $format} {foreach $video->formats as $format}
{if $config->stream || $format->protocol|in_array:array('http', 'https')} {if $config->stream || $format->protocol|in_array:array('http', 'https')}
{strip} {strip}
<option value="{$format->format_id}"> <option value="{$format->format_id}">
{$format->ext} {$format->ext}
{for $foo=1 to (5 - ($format->ext|strlen))} {for $foo=1 to (5 - ($format->ext|strlen))}
&nbsp; &nbsp;
{/for} {/for}
{if isset($format->width)} {if isset($format->width)}
{$format->width}x{$format->height} {$format->width}x{$format->height}
{for $foo=1 to (10 - (("{$format->width}x{$format->height}")|strlen))} {for $foo=1 to (10 - (("{$format->width}x{$format->height}")|strlen))}
&nbsp; &nbsp;
{/for} {/for}
{else} {else}
{for $foo=1 to 10} {for $foo=1 to 10}
&nbsp; &nbsp;
{/for} {/for}
{/if} {/if}
{if isset($format->filesize)} {if isset($format->filesize)}
{($format->filesize/1000000)|round:2} MB {($format->filesize/1000000)|round:2} MB
{for $foo=1 to (7 - (($format->filesize/1000000)|round:2|strlen))} {for $foo=1 to (7 - (($format->filesize/1000000)|round:2|strlen))}
&nbsp; &nbsp;
{/for} {/for}
{else} {else}
{for $foo=1 to 10} {for $foo=1 to 10}
&nbsp; &nbsp;
{/for} {/for}
{/if} {/if}
{if isset($format->format_note)} {if isset($format->format_note)}
{$format->format_note} {$format->format_note}
{/if} {/if}
&nbsp;({$format->format_id}) &nbsp;({$format->format_id})
</option> </option>
{/strip} {/strip}
{/if} {/if}
{/foreach} {/foreach}
</optgroup> </optgroup>
</select><br/><br/> </select>
{/if} <br/>
{if $config->stream} <br/>
<input type="checkbox" {if $config->stream != 'ask'}checked{/if} name="stream" id="stream"/> {/if}
<label for="stream">{t}Stream the video through the server{/t}</label> {if $config->stream}
<br/><br/> <input type="checkbox" {if $config->stream != 'ask'}checked{/if} name="stream" id="stream"/>
{/if} <label for="stream">{t}Stream the video through the server{/t}</label>
{if $config->convertAdvanced} <br/>
<input type="checkbox" name="customConvert" id="customConvert"/> <br/>
<label for="customConvert">{t}Convert into a custom format:{/t}</label> {/if}
<select title="{t}Custom format{/t}" name="customFormat" aria-label="{t}Format to convert to{/t}"> {if $config->convertAdvanced}
{foreach $config->convertAdvancedFormats as $format} <input type="checkbox" name="customConvert" id="customConvert"/>
<option>{$format}</option> <label for="customConvert">{t}Convert into a custom format:{/t}</label>
{/foreach} <select title="{t}Custom format{/t}" name="customFormat" aria-label="{t}Format to convert to{/t}">
</select> {foreach $config->convertAdvancedFormats as $format}
{t}with{/t} <option>{$format}</option>
<label for="customBitrate" class="sr-only">{t}Bit rate{/t}</label> {/foreach}
<input type="number" value="{$config->audioBitrate}" title="{t}Custom bitrate{/t}" class="customBitrate" </select>
name="customBitrate" id="customBitrate" aria-describedby="customBitrateUnit" /> {t}with{/t}
<span id="customBitrateUnit">{t}kbit/s audio{/t}</span> <label for="customBitrate" class="sr-only">{t}Bit rate{/t}</label>
<br/><br/> <input type="number" value="{$config->audioBitrate}" title="{t}Custom bitrate{/t}"
{/if} class="customBitrate"
<input class="downloadBtn" type="submit" value="{t}Download{/t}" /><br/> name="customBitrate" id="customBitrate" aria-describedby="customBitrateUnit"/>
</form> <span id="customBitrateUnit">{t}kbit/s audio{/t}</span>
</main> <br/>
</div> <br/>
{include file="inc/footer.tpl"} {/if}
<input class="downloadBtn" type="submit" value="{t}Download{/t}"/><br/>
</form>
</main>
</div>
{include file="inc/footer.tpl"}

View file

@ -6,9 +6,9 @@
<p>{t}You need a password in order to download this video.{/t}</p> <p>{t}You need a password in order to download this video.{/t}</p>
<form action="" method="POST"> <form action="" method="POST">
<label class="sr-only" for="password">{t}Video password{/t}</label> <label class="sr-only" for="password">{t}Video password{/t}</label>
<input class="URLinput" type="password" name="password" id="password" /> <input class="URLinput" type="password" name="password" id="password"/>
<br/><br/> <br/><br/>
<input class="downloadBtn" type="submit" value="{t}Download{/t}" /> <input class="downloadBtn" type="submit" value="{t}Download{/t}"/>
</form> </form>
</main> </main>
{include file='inc/footer.tpl'} {include file='inc/footer.tpl'}

View file

@ -1,43 +1,44 @@
{include file="inc/head.tpl"} {include file="inc/head.tpl"}
<div class="wrapper"> <div class="wrapper">
<main class="main"> <main class="main">
{include file="inc/logo.tpl"} {include file="inc/logo.tpl"}
{if isset($video->title)} {if isset($video->title)}
{$title="<i> {$title="<i>
<a href='{$video->webpage_url}'> <a href='{$video->webpage_url}'>
{$video->title}</a> {$video->title}</a>
</i>"} </i>"}
<p> <p>
{t params=['@title'=>$title]}Videos extracted from @title:{/t} {t params=['@title'=>$title]}Videos extracted from @title:{/t}
</p> </p>
{/if} {/if}
{if $config->stream} {if $config->stream}
<a href="{path_for name="download"}?url={$video->webpage_url}" class="downloadBtn">Download everything</a> <a href="{path_for name="download"}?url={$video->webpage_url}" class="downloadBtn">Download everything</a>
{/if} {/if}
{foreach $video->entries as $entry} {foreach $video->entries as $entry}
<div class="playlist-entry"> <div class="playlist-entry">
<h3 class="playlist-entry-title"><a target="_blank" href="{strip} <h3 class="playlist-entry-title"><a target="_blank" href="{strip}
{if isset($entry->ie_key) and $entry->ie_key == Youtube and !filter_var($entry->url, FILTER_VALIDATE_URL)} {if isset($entry->ie_key) and $entry->ie_key == Youtube and !filter_var($entry->url, FILTER_VALIDATE_URL)}
https://www.youtube.com/watch?v= https://www.youtube.com/watch?v=
{/if} {/if}
{$entry->url} {$entry->url}
{/strip}"> {/strip}">
{if !isset($entry->title)} {if !isset($entry->title)}
{if $entry->ie_key == YoutubePlaylist} {if $entry->ie_key == YoutubePlaylist}
Playlist Playlist
{else} {else}
Video Video
{/if} {/if}
{else} {else}
{$entry->title} {$entry->title}
{/if} {/if}
</a></h3> </a></h3>
<a target="_blank" class="downloadBtn" href="{path_for name="download"}?url={$entry->url}">{t}Download{/t}</a> <a target="_blank" class="downloadBtn"
<a target="_blank" href="{path_for name="info"}?url={$entry->url}">{t}More options{/t}</a> href="{path_for name="download"}?url={$entry->url}">{t}Download{/t}</a>
</div> <a target="_blank" href="{path_for name="info"}?url={$entry->url}">{t}More options{/t}</a>
{/foreach} </div>
{/foreach}
</main> </main>
{include file="inc/footer.tpl"} {include file="inc/footer.tpl"}

View file

@ -7,6 +7,7 @@
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\Config; use Alltube\Config;
use Exception;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
/** /**
@ -32,6 +33,7 @@ abstract class BaseTest extends TestCase
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -23,6 +23,7 @@ class ConfigTest extends BaseTest
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {
@ -39,7 +40,7 @@ class ConfigTest extends BaseTest
public function testGetInstance() public function testGetInstance()
{ {
$config = Config::getInstance(); $config = Config::getInstance();
$this->assertEquals($config->convert, false); $this->assertEquals(false, $config->convert);
$this->assertConfig($config); $this->assertConfig($config);
} }
@ -53,7 +54,7 @@ class ConfigTest extends BaseTest
Config::destroyInstance(); Config::destroyInstance();
$config = Config::getInstance(); $config = Config::getInstance();
$this->assertEquals($config->convert, false); $this->assertEquals(false, $config->convert);
$this->assertConfig($config); $this->assertConfig($config);
} }
@ -81,6 +82,7 @@ class ConfigTest extends BaseTest
* Test the setFile function. * Test the setFile function.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testSetFile() public function testSetFile()
{ {
@ -103,24 +105,26 @@ class ConfigTest extends BaseTest
* Test the setOptions function. * Test the setOptions function.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testSetOptions() public function testSetOptions()
{ {
Config::setOptions(['appName' => 'foo']); Config::setOptions(['appName' => 'foo']);
$config = Config::getInstance(); $config = Config::getInstance();
$this->assertEquals($config->appName, 'foo'); $this->assertEquals('foo', $config->appName);
} }
/** /**
* Test the setOptions function. * Test the setOptions function.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testSetOptionsWithoutUpdate() public function testSetOptionsWithoutUpdate()
{ {
Config::setOptions(['appName' => 'foo'], false); Config::setOptions(['appName' => 'foo'], false);
$config = Config::getInstance(); $config = Config::getInstance();
$this->assertEquals($config->appName, 'foo'); $this->assertEquals('foo', $config->appName);
} }
/** /**
@ -149,6 +153,7 @@ class ConfigTest extends BaseTest
* Test the getInstance function with the CONVERT and PYTHON environment variables. * Test the getInstance function with the CONVERT and PYTHON environment variables.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testGetInstanceWithEnv() public function testGetInstanceWithEnv()
{ {
@ -156,7 +161,7 @@ class ConfigTest extends BaseTest
putenv('CONVERT=1'); putenv('CONVERT=1');
Config::setFile($this->getConfigFile()); Config::setFile($this->getConfigFile());
$config = Config::getInstance(); $config = Config::getInstance();
$this->assertEquals($config->convert, true); $this->assertEquals(true, $config->convert);
putenv('CONVERT'); putenv('CONVERT');
} }
} }

View file

@ -6,10 +6,12 @@
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\Controller\BaseController;
use Alltube\Controller\DownloadController; use Alltube\Controller\DownloadController;
use Alltube\Controller\FrontController; use Alltube\Controller\FrontController;
use Alltube\LocaleManager; use Alltube\LocaleManager;
use Alltube\ViewFactory; use Alltube\ViewFactory;
use Exception;
use Slim\Container; use Slim\Container;
use Slim\Http\Environment; use Slim\Http\Environment;
use Slim\Http\Request; use Slim\Http\Request;
@ -43,11 +45,13 @@ abstract class ControllerTest extends BaseTest
/** /**
* Controller instance used in tests. * Controller instance used in tests.
* @var BaseController
*/ */
protected $controller; protected $controller;
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {
@ -78,7 +82,7 @@ abstract class ControllerTest extends BaseTest
* Run controller function with custom query parameters and return the result. * Run controller function with custom query parameters and return the result.
* *
* @param string $request Controller function to call * @param string $request Controller function to call
* @param array $params Query parameters * @param mixed[] $params Query parameters
* *
* @return Response HTTP response * @return Response HTTP response
*/ */
@ -94,7 +98,7 @@ abstract class ControllerTest extends BaseTest
* Assert that calling controller function with these parameters returns a 200 HTTP response. * Assert that calling controller function with these parameters returns a 200 HTTP response.
* *
* @param string $request Controller function to call * @param string $request Controller function to call
* @param array $params Query parameters * @param mixed[] $params Query parameters
* *
* @return void * @return void
*/ */
@ -107,7 +111,7 @@ abstract class ControllerTest extends BaseTest
* Assert that calling controller function with these parameters returns an HTTP redirect. * Assert that calling controller function with these parameters returns an HTTP redirect.
* *
* @param string $request Controller function to call * @param string $request Controller function to call
* @param array $params Query parameters * @param mixed[] $params Query parameters
* *
* @return void * @return void
*/ */
@ -120,7 +124,7 @@ abstract class ControllerTest extends BaseTest
* Assert that calling controller function with these parameters returns an HTTP 500 error. * Assert that calling controller function with these parameters returns an HTTP 500 error.
* *
* @param string $request Controller function to call * @param string $request Controller function to call
* @param array $params Query parameters * @param mixed[] $params Query parameters
* *
* @return void * @return void
*/ */
@ -133,7 +137,7 @@ abstract class ControllerTest extends BaseTest
* Assert that calling controller function with these parameters returns an HTTP 400 error. * Assert that calling controller function with these parameters returns an HTTP 400 error.
* *
* @param string $request Controller function to call * @param string $request Controller function to call
* @param array $params Query parameters * @param mixed[] $params Query parameters
* *
* @return void * @return void
*/ */

View file

@ -8,6 +8,7 @@ namespace Alltube\Test;
use Alltube\Stream\ConvertedPlaylistArchiveStream; use Alltube\Stream\ConvertedPlaylistArchiveStream;
use Alltube\Video; use Alltube\Video;
use Exception;
/** /**
* Unit tests for the ConvertedPlaylistArchiveStream class. * Unit tests for the ConvertedPlaylistArchiveStream class.
@ -17,6 +18,7 @@ class ConvertedPlaylistArchiveStreamTest extends StreamTest
{ {
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -8,6 +8,7 @@ namespace Alltube\Test;
use Alltube\Config; use Alltube\Config;
use Alltube\Controller\DownloadController; use Alltube\Controller\DownloadController;
use Exception;
/** /**
* Unit tests for the FrontController class. * Unit tests for the FrontController class.
@ -17,6 +18,7 @@ class DownloadControllerTest extends ControllerTest
{ {
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {
@ -62,6 +64,7 @@ class DownloadControllerTest extends ControllerTest
* Test the download() function with streams enabled. * Test the download() function with streams enabled.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testDownloadWithStream() public function testDownloadWithStream()
{ {
@ -77,6 +80,7 @@ class DownloadControllerTest extends ControllerTest
* Test the download() function with an M3U stream. * Test the download() function with an M3U stream.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testDownloadWithM3uStream() public function testDownloadWithM3uStream()
{ {
@ -96,6 +100,7 @@ class DownloadControllerTest extends ControllerTest
* Test the download() function with an RTMP stream. * Test the download() function with an RTMP stream.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testDownloadWithRtmpStream() public function testDownloadWithRtmpStream()
{ {
@ -113,6 +118,7 @@ class DownloadControllerTest extends ControllerTest
* Test the download() function with a remuxed video. * Test the download() function with a remuxed video.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testDownloadWithRemux() public function testDownloadWithRemux()
{ {
@ -182,6 +188,7 @@ class DownloadControllerTest extends ControllerTest
* *
* @return void * @return void
* @requires OS Linux * @requires OS Linux
* @throws Exception
*/ */
public function testDownloadWithPlaylist() public function testDownloadWithPlaylist()
{ {
@ -197,6 +204,7 @@ class DownloadControllerTest extends ControllerTest
* Test the download() function with an advanced conversion. * Test the download() function with an advanced conversion.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testDownloadWithAdvancedConversion() public function testDownloadWithAdvancedConversion()
{ {

View file

@ -17,8 +17,15 @@ use Slim\Http\Request;
*/ */
class FrontControllerTest extends ControllerTest class FrontControllerTest extends ControllerTest
{ {
/**
* Controller instance used in tests.
* @var FrontController
*/
protected $controller;
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {
@ -41,6 +48,7 @@ class FrontControllerTest extends ControllerTest
* Test the constructor with streams enabled. * Test the constructor with streams enabled.
* *
* @return void * @return void
* @throws Exception
*/ */
public function testConstructorWithStream() public function testConstructorWithStream()
{ {
@ -120,6 +128,7 @@ class FrontControllerTest extends ControllerTest
* *
* @return void * @return void
* @requires download * @requires download
* @throws Exception
*/ */
public function testInfoWithAudio() public function testInfoWithAudio()
{ {
@ -136,6 +145,7 @@ class FrontControllerTest extends ControllerTest
* *
* @return void * @return void
* @requires download * @requires download
* @throws Exception
*/ */
public function testInfoWithVimeoAudio() public function testInfoWithVimeoAudio()
{ {
@ -150,6 +160,7 @@ class FrontControllerTest extends ControllerTest
* *
* @return void * @return void
* @requires download * @requires download
* @throws Exception
*/ */
public function testInfoWithUnconvertedAudio() public function testInfoWithUnconvertedAudio()
{ {
@ -197,6 +208,7 @@ class FrontControllerTest extends ControllerTest
* *
* @return void * @return void
* @requires download * @requires download
* @throws Exception
*/ */
public function testInfoWithStream() public function testInfoWithStream()
{ {

View file

@ -7,6 +7,7 @@
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\Controller\JsonController; use Alltube\Controller\JsonController;
use Exception;
/** /**
* Unit tests for the FrontController class. * Unit tests for the FrontController class.
@ -15,6 +16,7 @@ class JsonControllerTest extends ControllerTest
{ {
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -6,7 +6,6 @@
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\Locale;
use Alltube\LocaleManager; use Alltube\LocaleManager;
use Alltube\LocaleMiddleware; use Alltube\LocaleMiddleware;
use Slim\Container; use Slim\Container;

View file

@ -8,6 +8,7 @@ namespace Alltube\Test;
use Alltube\Stream\PlaylistArchiveStream; use Alltube\Stream\PlaylistArchiveStream;
use Alltube\Video; use Alltube\Video;
use Exception;
/** /**
* Unit tests for the PlaylistArchiveStream class. * Unit tests for the PlaylistArchiveStream class.
@ -17,6 +18,7 @@ class PlaylistArchiveStreamTest extends StreamTest
{ {
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -6,6 +6,7 @@
namespace Alltube\Test; namespace Alltube\Test;
use Psr\Http\Message\StreamInterface;
use RuntimeException; use RuntimeException;
/** /**
@ -15,6 +16,7 @@ abstract class StreamTest extends BaseTest
{ {
/** /**
* Stream instance. * Stream instance.
* @var StreamInterface
*/ */
protected $stream; protected $stream;
@ -36,7 +38,7 @@ abstract class StreamTest extends BaseTest
public function testWrite() public function testWrite()
{ {
if ($this->stream->isWritable()) { if ($this->stream->isWritable()) {
$this->assertNull($this->stream->write('foo')); $this->assertIsInt($this->stream->write('foo'));
} else { } else {
$this->expectException(RuntimeException::class); $this->expectException(RuntimeException::class);
$this->stream->write('foo'); $this->stream->write('foo');
@ -103,7 +105,7 @@ abstract class StreamTest extends BaseTest
*/ */
public function testEof() public function testEof()
{ {
$this->assertFalse($this->stream->eof()); $this->assertIsBool($this->stream->eof());
} }
/** /**

View file

@ -26,6 +26,7 @@ class VideoStubsTest extends BaseTest
/** /**
* Initialize properties used by test. * Initialize properties used by test.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -7,6 +7,8 @@
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\Config; use Alltube\Config;
use Alltube\Exception\EmptyUrlException;
use Alltube\Exception\PasswordException;
use Alltube\Video; use Alltube\Video;
use Exception; use Exception;
@ -20,6 +22,7 @@ class VideoTest extends BaseTest
* Test getExtractors function. * Test getExtractors function.
* *
* @return void * @return void
* @throws PasswordException
*/ */
public function testGetExtractors() public function testGetExtractors()
{ {
@ -29,13 +32,15 @@ class VideoTest extends BaseTest
/** /**
* Test getUrl function. * Test getUrl function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* @param string $filename Filename * @param string $filename Filename
* @param string $extension File extension * @param string $extension File extension
* @param string $domain Domain * @param string $domain Domain
* *
* @return void * @return void
* @throws PasswordException
* @throws EmptyUrlException
* @dataProvider urlProvider * @dataProvider urlProvider
* @dataProvider m3uUrlProvider * @dataProvider m3uUrlProvider
* @dataProvider remuxUrlProvider * @dataProvider remuxUrlProvider
@ -57,6 +62,8 @@ class VideoTest extends BaseTest
* Test getUrl function with a protected video. * Test getUrl function with a protected video.
* *
* @return void * @return void
* @throws EmptyUrlException
* @throws PasswordException
*/ */
public function testgetUrlWithPassword() public function testgetUrlWithPassword()
{ {
@ -70,6 +77,8 @@ class VideoTest extends BaseTest
* Test getUrl function with a protected video and no password. * Test getUrl function with a protected video and no password.
* *
* @return void * @return void
* @throws EmptyUrlException
* @throws PasswordException
*/ */
public function testgetUrlWithMissingPassword() public function testgetUrlWithMissingPassword()
{ {
@ -82,6 +91,8 @@ class VideoTest extends BaseTest
* Test getUrl function with a protected video and a wrong password. * Test getUrl function with a protected video and a wrong password.
* *
* @return void * @return void
* @throws EmptyUrlException
* @throws PasswordException
*/ */
public function testgetUrlWithWrongPassword() public function testgetUrlWithWrongPassword()
{ {
@ -96,6 +107,8 @@ class VideoTest extends BaseTest
* @param string $url URL * @param string $url URL
* *
* @return void * @return void
* @throws EmptyUrlException
* @throws PasswordException
* @dataProvider ErrorUrlProvider * @dataProvider ErrorUrlProvider
*/ */
public function testgetUrlError($url) public function testgetUrlError($url)
@ -112,7 +125,7 @@ class VideoTest extends BaseTest
*/ */
public function urlProvider() public function urlProvider()
{ {
$videos = [ return [
[ [
'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'best[protocol^=http]', 'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'best[protocol^=http]',
'It_s_Not_Me_It_s_You_-_Hearts_Under_Fire-M7IpKCZ47pU', 'It_s_Not_Me_It_s_You_-_Hearts_Under_Fire-M7IpKCZ47pU',
@ -136,11 +149,9 @@ class VideoTest extends BaseTest
'https://vimeo.com/24195442', 'http-720p', 'https://vimeo.com/24195442', 'http-720p',
'Carving_the_Mountains-24195442', 'Carving_the_Mountains-24195442',
'mp4', 'mp4',
'gcs-vimeo.akamaized.net', 'akamaized.net',
] ]
]; ];
return $videos;
} }
/** /**
@ -167,7 +178,7 @@ class VideoTest extends BaseTest
*/ */
public function m3uUrlProvider() public function m3uUrlProvider()
{ {
$videos = [ return [
[ [
'https://twitter.com/verge/status/813055465324056576/video/1', 'hls-2176', 'https://twitter.com/verge/status/813055465324056576/video/1', 'hls-2176',
'The_Verge_-_This_tiny_origami_robot_can_self-fold_and_complete_tasks-813055465324056576', 'The_Verge_-_This_tiny_origami_robot_can_self-fold_and_complete_tasks-813055465324056576',
@ -175,8 +186,6 @@ class VideoTest extends BaseTest
'video.twimg.com', 'video.twimg.com',
] ]
]; ];
return $videos;
} }
/** /**
@ -211,12 +220,13 @@ class VideoTest extends BaseTest
/** /**
* Test getJSON function. * Test getJSON function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* *
* @return void * @return void
* @dataProvider urlProvider * @dataProvider urlProvider
* @dataProvider m3uUrlProvider * @dataProvider m3uUrlProvider
* @throws PasswordException
*/ */
public function testGetJson($url, $format) public function testGetJson($url, $format)
{ {
@ -237,6 +247,7 @@ class VideoTest extends BaseTest
* *
* @return void * @return void
* @dataProvider ErrorURLProvider * @dataProvider ErrorURLProvider
* @throws PasswordException
*/ */
public function testGetJsonError($url) public function testGetJsonError($url)
{ {
@ -248,15 +259,16 @@ class VideoTest extends BaseTest
/** /**
* Test getFilename function. * Test getFilename function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* @param string $filename Filename * @param string $filename Filename
* @param string $extension File extension * @param string $extension File extension
* *
* @return void * @return void
* @dataProvider urlProvider * @dataProvider urlProvider
* @dataProvider m3uUrlProvider * @dataProvider m3uUrlProvider
* @dataProvider remuxUrlProvider * @dataProvider remuxUrlProvider
* @throws PasswordException
*/ */
public function testGetFilename($url, $format, $filename, $extension) public function testGetFilename($url, $format, $filename, $extension)
{ {
@ -271,6 +283,7 @@ class VideoTest extends BaseTest
* *
* @return void * @return void
* @dataProvider ErrorUrlProvider * @dataProvider ErrorUrlProvider
* @throws PasswordException
*/ */
public function testGetFilenameError($url) public function testGetFilenameError($url)
{ {
@ -282,11 +295,12 @@ class VideoTest extends BaseTest
/** /**
* Test getAudioStream function. * Test getAudioStream function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* *
* @return void * @return void
* @dataProvider urlProvider * @dataProvider urlProvider
* @throws Exception
*/ */
public function testGetAudioStream($url, $format) public function testGetAudioStream($url, $format)
{ {
@ -371,11 +385,12 @@ class VideoTest extends BaseTest
/** /**
* Test getM3uStream function. * Test getM3uStream function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* *
* @return void * @return void
* @dataProvider m3uUrlProvider * @dataProvider m3uUrlProvider
* @throws Exception
*/ */
public function testGetM3uStream($url, $format) public function testGetM3uStream($url, $format)
{ {
@ -386,11 +401,12 @@ class VideoTest extends BaseTest
/** /**
* Test getRemuxStream function. * Test getRemuxStream function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* *
* @return void * @return void
* @dataProvider remuxUrlProvider * @dataProvider remuxUrlProvider
* @throws Exception
*/ */
public function testGetRemuxStream($url, $format) public function testGetRemuxStream($url, $format)
{ {
@ -417,11 +433,12 @@ class VideoTest extends BaseTest
/** /**
* Test getRtmpStream function. * Test getRtmpStream function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* *
* @return void * @return void
* @dataProvider rtmpUrlProvider * @dataProvider rtmpUrlProvider
* @throws Exception
*/ */
public function testGetRtmpStream($url, $format) public function testGetRtmpStream($url, $format)
{ {
@ -453,11 +470,12 @@ class VideoTest extends BaseTest
/** /**
* Test getConvertedStream function without avconv. * Test getConvertedStream function without avconv.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* *
* @return void * @return void
* @dataProvider urlProvider * @dataProvider urlProvider
* @throws Exception
*/ */
public function testGetConvertedStream($url, $format) public function testGetConvertedStream($url, $format)
{ {

View file

@ -12,6 +12,7 @@ use Slim\Container;
use Slim\Http\Environment; use Slim\Http\Environment;
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Views\Smarty; use Slim\Views\Smarty;
use SmartyException;
/** /**
* Unit tests for the ViewFactory class. * Unit tests for the ViewFactory class.
@ -22,6 +23,7 @@ class ViewFactoryTest extends BaseTest
* Test the create() function. * Test the create() function.
* *
* @return void * @return void
* @throws SmartyException
*/ */
public function testCreate() public function testCreate()
{ {
@ -35,6 +37,7 @@ class ViewFactoryTest extends BaseTest
* Test the create() function with a X-Forwarded-Proto header. * Test the create() function with a X-Forwarded-Proto header.
* *
* @return void * @return void
* @throws SmartyException
*/ */
public function testCreateWithXForwardedProto() public function testCreateWithXForwardedProto()
{ {

View file

@ -8,6 +8,7 @@ namespace Alltube\Test;
use Alltube\Stream\YoutubeChunkStream; use Alltube\Stream\YoutubeChunkStream;
use Alltube\Video; use Alltube\Video;
use Exception;
/** /**
* Unit tests for the YoutubeChunkStream class. * Unit tests for the YoutubeChunkStream class.
@ -17,6 +18,7 @@ class YoutubeChunkStreamTest extends StreamTest
{ {
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -8,6 +8,7 @@ namespace Alltube\Test;
use Alltube\Stream\YoutubeStream; use Alltube\Stream\YoutubeStream;
use Alltube\Video; use Alltube\Video;
use Exception;
/** /**
* Unit tests for the YoutubeStream class. * Unit tests for the YoutubeStream class.
@ -17,6 +18,7 @@ class YoutubeStreamTest extends StreamTest
{ {
/** /**
* Prepare tests. * Prepare tests.
* @throws Exception
*/ */
protected function setUp(): void protected function setUp(): void
{ {

View file

@ -9,7 +9,7 @@ use phpmock\mockery\PHPMockery;
// Composer autoload. // Composer autoload.
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
ini_set('session.use_cookies', 0); ini_set('session.use_cookies', '0');
session_cache_limiter(''); session_cache_limiter('');
session_start(); session_start();