Laravel version update
Laravel version update
This commit is contained in:
8
vendor/flowjs/flow-php-server/.gitignore
vendored
Normal file
8
vendor/flowjs/flow-php-server/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Ide
|
||||
.idea
|
||||
|
||||
# Composer
|
||||
composer.lock
|
||||
/vendor
|
||||
|
||||
/build
|
13
vendor/flowjs/flow-php-server/.travis.yml
vendored
Normal file
13
vendor/flowjs/flow-php-server/.travis.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
|
||||
before_script:
|
||||
- composer install --dev --no-interaction --prefer-source
|
||||
|
||||
script:
|
||||
- mkdir -p build
|
||||
- phpunit --configuration travis.phpunit.xml
|
5
vendor/flowjs/flow-php-server/CHANGELOG.md
vendored
Normal file
5
vendor/flowjs/flow-php-server/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# 1.0.0
|
||||
## Breaking Changes
|
||||
* Flow\Exception was replaced by Flow\FileOpenException and Flow\FileLockException
|
||||
* php requirement was changed to >=5.4
|
||||
* if chunk was not found, 204 status is returned instead of 404
|
20
vendor/flowjs/flow-php-server/LICENSE
vendored
Normal file
20
vendor/flowjs/flow-php-server/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Aidas Klimas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
98
vendor/flowjs/flow-php-server/README.md
vendored
Normal file
98
vendor/flowjs/flow-php-server/README.md
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
flow.js php server [](https://travis-ci.org/flowjs/flow-php-server) [](https://coveralls.io/r/flowjs/flow-php-server?branch=master)
|
||||
=======================
|
||||
|
||||
PHP library for handling chunk uploads. Library contains helper methods for:
|
||||
* Testing if uploaded file chunk exists.
|
||||
* Validating file chunk
|
||||
* Creating separate chunks folder
|
||||
* Validating uploaded chunks
|
||||
* Merging all chunks to a single file
|
||||
|
||||
This library is compatible with HTML5 file upload library: https://github.com/flowjs/flow.js
|
||||
|
||||
How to get started?
|
||||
--------------
|
||||
Setup Composer: https://getcomposer.org/doc/00-intro.md
|
||||
|
||||
Run this command in your project:
|
||||
```
|
||||
composer require flowjs/flow-php-server
|
||||
```
|
||||
This will create a vendor directory for you, which contains an autoload.php file.
|
||||
|
||||
Create a new php file named `upload.php`:
|
||||
```php
|
||||
//Path to autoload.php from current location
|
||||
require_once './vendor/autoload.php';
|
||||
|
||||
$config = new \Flow\Config();
|
||||
$config->setTempDir('./chunks_temp_folder');
|
||||
$request = new \Flow\Request();
|
||||
if (\Flow\Basic::save('./' . $request->getIdentifier(), $config, $request)) {
|
||||
// file saved successfully and can be accessed at './final_file_destination'
|
||||
} else {
|
||||
// This is not a final chunk or request is invalid, continue to upload.
|
||||
}
|
||||
```
|
||||
|
||||
Make sure that `./chunks_temp_folder` path exists and is writable. All chunks will be saved in this folder.
|
||||
|
||||
If you are stuck with this example, please read this issue: [How to use the flow-php-server](https://github.com/flowjs/flow-php-server/issues/3#issuecomment-46979467)
|
||||
|
||||
Advanced Usage
|
||||
--------------
|
||||
|
||||
```php
|
||||
$config = new \Flow\Config();
|
||||
$config->setTempDir('./chunks_temp_folder');
|
||||
$file = new \Flow\File($config);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
if ($file->checkChunk()) {
|
||||
header("HTTP/1.1 200 Ok");
|
||||
} else {
|
||||
header("HTTP/1.1 204 No Content");
|
||||
return ;
|
||||
}
|
||||
} else {
|
||||
if ($file->validateChunk()) {
|
||||
$file->saveChunk();
|
||||
} else {
|
||||
// error, invalid chunk upload request, retry
|
||||
header("HTTP/1.1 400 Bad Request");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if ($file->validateFile() && $file->save('./final_file_name')) {
|
||||
// File upload was completed
|
||||
} else {
|
||||
// This is not a final chunk, continue to upload
|
||||
}
|
||||
```
|
||||
|
||||
Delete unfinished files
|
||||
-----------------------
|
||||
|
||||
For this you should setup cron, which would check each chunk upload time.
|
||||
If chunk is uploaded long time ago, then chunk should be deleted.
|
||||
|
||||
Helper method for checking this:
|
||||
```php
|
||||
\Flow\Uploader::pruneChunks('./chunks_folder');
|
||||
```
|
||||
|
||||
Cron task can be avoided by using random function execution.
|
||||
```php
|
||||
if (1 == mt_rand(1, 100)) {
|
||||
\Flow\Uploader::pruneChunks('./chunks_folder');
|
||||
}
|
||||
```
|
||||
|
||||
Contribution
|
||||
------------
|
||||
|
||||
Your participation in development is very welcome!
|
||||
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
* All features or bug fixes must be tested by one or more specs.
|
||||
* Your code should follow [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) coding style guide
|
35
vendor/flowjs/flow-php-server/composer.json
vendored
Normal file
35
vendor/flowjs/flow-php-server/composer.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "flowjs/flow-php-server",
|
||||
"description": "PHP library for handling chunk uploads. Works with flow.js html5 file uploads.",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Aidas Klimas",
|
||||
"email": "aidaskk@gmail.com"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"flow.js",
|
||||
"flow",
|
||||
"resumable.js",
|
||||
"resumable",
|
||||
"upload",
|
||||
"file upload",
|
||||
"html5 file upload",
|
||||
"chunks"
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsStream": "v1.2.0",
|
||||
"league/phpunit-coverage-listener": "~1.1",
|
||||
"fabpot/php-cs-fixer": "dev-master",
|
||||
"phpunit/phpunit": "4.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Flow": "src"
|
||||
}
|
||||
}
|
||||
}
|
4
vendor/flowjs/flow-php-server/phpunit
vendored
Normal file
4
vendor/flowjs/flow-php-server/phpunit
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
php ./vendor/phpunit/phpunit/phpunit "$@"
|
||||
|
29
vendor/flowjs/flow-php-server/phpunit.xml
vendored
Normal file
29
vendor/flowjs/flow-php-server/phpunit.xml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Flow Test Suite">
|
||||
<directory>./test/Unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./src/Flow/</directory>
|
||||
<exclude>
|
||||
<file>./src/Flow/Basic.php</file>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
67
vendor/flowjs/flow-php-server/src/Flow/Autoloader.php
vendored
Normal file
67
vendor/flowjs/flow-php-server/src/Flow/Autoloader.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class Autoloader
|
||||
{
|
||||
/**
|
||||
* Directory path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $dir;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string|null $dir
|
||||
*/
|
||||
public function __construct($dir = null)
|
||||
{
|
||||
if (is_null($dir)) {
|
||||
$dir = __DIR__.'/..';
|
||||
}
|
||||
|
||||
$this->dir = $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return directory path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDir()
|
||||
{
|
||||
return $this->dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string|null $dir
|
||||
*/
|
||||
public static function register($dir = null)
|
||||
{
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
spl_autoload_register(array(new self($dir), 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles autoloading of classes
|
||||
*
|
||||
* @param string $class A class name
|
||||
*
|
||||
* @return boolean Returns true if the class has been loaded
|
||||
*/
|
||||
public function autoload($class)
|
||||
{
|
||||
if (0 !== strpos($class, 'Flow')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_exists($file = $this->dir.'/'.str_replace('\\', '/', $class).'.php')) {
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
}
|
54
vendor/flowjs/flow-php-server/src/Flow/Basic.php
vendored
Normal file
54
vendor/flowjs/flow-php-server/src/Flow/Basic.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
/**
|
||||
* Class Basic
|
||||
*
|
||||
* Example for handling basic uploads
|
||||
*
|
||||
* @package Flow
|
||||
*/
|
||||
class Basic
|
||||
{
|
||||
/**
|
||||
* @param string $destination where to save file
|
||||
* @param string|ConfigInterface $config
|
||||
* @param RequestInterface $request optional
|
||||
* @return bool
|
||||
*/
|
||||
public static function save($destination, $config, RequestInterface $request = null)
|
||||
{
|
||||
if (!$config instanceof ConfigInterface) {
|
||||
$config = new Config(array(
|
||||
'tempDir' => $config,
|
||||
));
|
||||
}
|
||||
|
||||
$file = new File($config, $request);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
if ($file->checkChunk()) {
|
||||
header("HTTP/1.1 200 Ok");
|
||||
} else {
|
||||
// The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
|
||||
header("HTTP/1.1 204 No Content");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ($file->validateChunk()) {
|
||||
$file->saveChunk();
|
||||
} else {
|
||||
// error, invalid chunk upload request, retry
|
||||
header("HTTP/1.1 400 Bad Request");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($file->validateFile() && $file->save($destination)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
115
vendor/flowjs/flow-php-server/src/Flow/Config.php
vendored
Normal file
115
vendor/flowjs/flow-php-server/src/Flow/Config.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class Config implements ConfigInterface
|
||||
{
|
||||
/**
|
||||
* Config
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Controller
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set path to temporary directory for chunks storage
|
||||
*
|
||||
* @param $path
|
||||
*/
|
||||
public function setTempDir($path)
|
||||
{
|
||||
$this->config['tempDir'] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to temporary directory for chunks storage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTempDir()
|
||||
{
|
||||
return isset($this->config['tempDir']) ? $this->config['tempDir'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set chunk identifier
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function setHashNameCallback($callback)
|
||||
{
|
||||
$this->config['hashNameCallback'] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate chunk identifier
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getHashNameCallback()
|
||||
{
|
||||
return isset($this->config['hashNameCallback']) ? $this->config['hashNameCallback'] : '\Flow\Config::hashNameCallback';
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to pre-process chunk
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function setPreprocessCallback($callback)
|
||||
{
|
||||
$this->config['preprocessCallback'] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to pre-process chunk
|
||||
*
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getPreprocessCallback()
|
||||
{
|
||||
return isset($this->config['preprocessCallback']) ? $this->config['preprocessCallback'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete chunks on save
|
||||
*
|
||||
* @param bool $delete
|
||||
*/
|
||||
public function setDeleteChunksOnSave($delete)
|
||||
{
|
||||
$this->config['deleteChunksOnSave'] = $delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete chunks on save
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDeleteChunksOnSave()
|
||||
{
|
||||
return isset($this->config['deleteChunksOnSave']) ? $this->config['deleteChunksOnSave'] : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate chunk identifier
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function hashNameCallback(RequestInterface $request)
|
||||
{
|
||||
return sha1($request->getIdentifier());
|
||||
}
|
||||
}
|
48
vendor/flowjs/flow-php-server/src/Flow/ConfigInterface.php
vendored
Normal file
48
vendor/flowjs/flow-php-server/src/Flow/ConfigInterface.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
interface ConfigInterface
|
||||
{
|
||||
/**
|
||||
* Get path to temporary directory for chunks storage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTempDir();
|
||||
|
||||
/**
|
||||
* Generate chunk identifier
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getHashNameCallback();
|
||||
|
||||
/**
|
||||
* Callback to pre-process chunk
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function setPreprocessCallback($callback);
|
||||
|
||||
/**
|
||||
* Callback to preprocess chunk
|
||||
*
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getPreprocessCallback();
|
||||
|
||||
/**
|
||||
* Delete chunks on save
|
||||
*
|
||||
* @param bool $delete
|
||||
*/
|
||||
public function setDeleteChunksOnSave($delete);
|
||||
|
||||
/**
|
||||
* Delete chunks on save
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDeleteChunksOnSave();
|
||||
}
|
233
vendor/flowjs/flow-php-server/src/Flow/File.php
vendored
Normal file
233
vendor/flowjs/flow-php-server/src/Flow/File.php
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class File
|
||||
{
|
||||
/**
|
||||
* @var RequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var ConfigInterface
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* File hashed unique identifier
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $identifier;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ConfigInterface $config
|
||||
* @param RequestInterface $request
|
||||
*/
|
||||
public function __construct(ConfigInterface $config, RequestInterface $request = null)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
if ($request === null) {
|
||||
$request = new Request();
|
||||
}
|
||||
|
||||
$this->request = $request;
|
||||
$this->identifier = call_user_func($this->config->getHashNameCallback(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file identifier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return chunk path
|
||||
*
|
||||
* @param int $index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getChunkPath($index)
|
||||
{
|
||||
return $this->config->getTempDir().DIRECTORY_SEPARATOR.basename($this->identifier).'_'. (int) $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if chunk exist
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkChunk()
|
||||
{
|
||||
return file_exists($this->getChunkPath($this->request->getCurrentChunkNumber()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate file request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validateChunk()
|
||||
{
|
||||
$file = $this->request->getFile();
|
||||
|
||||
if (!$file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($file['tmp_name']) || !isset($file['size']) || !isset($file['error'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->request->getCurrentChunkSize() != $file['size']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save chunk
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveChunk()
|
||||
{
|
||||
$file = $this->request->getFile();
|
||||
|
||||
return $this->_move_uploaded_file($file['tmp_name'], $this->getChunkPath($this->request->getCurrentChunkNumber()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if file upload is complete
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validateFile()
|
||||
{
|
||||
$totalChunks = $this->request->getTotalChunks();
|
||||
$totalChunksSize = 0;
|
||||
|
||||
for ($i = $totalChunks; $i >= 1; $i--) {
|
||||
$file = $this->getChunkPath($i);
|
||||
if (!file_exists($file)) {
|
||||
return false;
|
||||
}
|
||||
$totalChunksSize += filesize($file);
|
||||
}
|
||||
|
||||
return $this->request->getTotalSize() == $totalChunksSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge all chunks to single file
|
||||
*
|
||||
* @param string $destination final file location
|
||||
*
|
||||
*
|
||||
* @throws FileLockException
|
||||
* @throws FileOpenException
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return bool indicates if file was saved
|
||||
*/
|
||||
public function save($destination)
|
||||
{
|
||||
$fh = fopen($destination, 'wb');
|
||||
if (!$fh) {
|
||||
throw new FileOpenException('failed to open destination file: '.$destination);
|
||||
}
|
||||
|
||||
if (!flock($fh, LOCK_EX | LOCK_NB, $blocked)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($blocked) {
|
||||
// Concurrent request has requested a lock.
|
||||
// File is being processed at the moment.
|
||||
// Warning: lock is not checked in windows.
|
||||
return false;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
throw new FileLockException('failed to lock file: '.$destination);
|
||||
}
|
||||
|
||||
$totalChunks = $this->request->getTotalChunks();
|
||||
|
||||
try {
|
||||
$preProcessChunk = $this->config->getPreprocessCallback();
|
||||
|
||||
for ($i = 1; $i <= $totalChunks; $i++) {
|
||||
$file = $this->getChunkPath($i);
|
||||
$chunk = fopen($file, "rb");
|
||||
|
||||
if (!$chunk) {
|
||||
throw new FileOpenException('failed to open chunk: '.$file);
|
||||
}
|
||||
|
||||
if ($preProcessChunk !== null) {
|
||||
call_user_func($preProcessChunk, $chunk);
|
||||
}
|
||||
|
||||
stream_copy_to_stream($chunk, $fh);
|
||||
fclose($chunk);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
flock($fh, LOCK_UN);
|
||||
fclose($fh);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($this->config->getDeleteChunksOnSave()) {
|
||||
$this->deleteChunks();
|
||||
}
|
||||
|
||||
flock($fh, LOCK_UN);
|
||||
fclose($fh);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete chunks dir
|
||||
*/
|
||||
public function deleteChunks()
|
||||
{
|
||||
$totalChunks = $this->request->getTotalChunks();
|
||||
|
||||
for ($i = 1; $i <= $totalChunks; $i++) {
|
||||
$path = $this->getChunkPath($i);
|
||||
if (file_exists($path)) {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used only for testing
|
||||
*
|
||||
* @private
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param string $destinationPath
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function _move_uploaded_file($filePath, $destinationPath)
|
||||
{
|
||||
return move_uploaded_file($filePath, $destinationPath);
|
||||
}
|
||||
}
|
7
vendor/flowjs/flow-php-server/src/Flow/FileLockException.php
vendored
Normal file
7
vendor/flowjs/flow-php-server/src/Flow/FileLockException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class FileLockException extends \Exception
|
||||
{
|
||||
}
|
7
vendor/flowjs/flow-php-server/src/Flow/FileOpenException.php
vendored
Normal file
7
vendor/flowjs/flow-php-server/src/Flow/FileOpenException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class FileOpenException extends \Exception
|
||||
{
|
||||
}
|
39
vendor/flowjs/flow-php-server/src/Flow/FustyRequest.php
vendored
Normal file
39
vendor/flowjs/flow-php-server/src/Flow/FustyRequest.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
/**
|
||||
* Class FustyRequest
|
||||
*
|
||||
* Imitates single file request as a single chunk file upload
|
||||
*
|
||||
* @package Flow
|
||||
*/
|
||||
class FustyRequest extends Request
|
||||
{
|
||||
private $isFusty = false;
|
||||
|
||||
public function __construct($params = null, $file = null)
|
||||
{
|
||||
parent::__construct($params, $file);
|
||||
|
||||
$this->isFusty = $this->getTotalSize() === null && $this->getFileName() && $this->getFile();
|
||||
|
||||
if ($this->isFusty) {
|
||||
$this->params['flowTotalSize'] = isset($this->file['size']) ? $this->file['size'] : 0;
|
||||
$this->params['flowTotalChunks'] = 1;
|
||||
$this->params['flowChunkNumber'] = 1;
|
||||
$this->params['flowChunkSize'] = $this->params['flowTotalSize'];
|
||||
$this->params['flowCurrentChunkSize'] = $this->params['flowTotalSize'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if request is formed by fusty flow
|
||||
* @return bool
|
||||
*/
|
||||
public function isFustyFlowRequest()
|
||||
{
|
||||
return $this->isFusty;
|
||||
}
|
||||
}
|
31
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoConfig.php
vendored
Normal file
31
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoConfig.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Flow\Mongo;
|
||||
|
||||
use Flow\Config;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class MongoConfig extends Config implements MongoConfigInterface
|
||||
{
|
||||
private $gridFs;
|
||||
|
||||
/**
|
||||
* @param \MongoGridFS $gridFS storage of the upload (and chunks)
|
||||
*/
|
||||
function __construct(\MongoGridFS $gridFS)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->gridFs = $gridFS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \MongoGridFS
|
||||
*/
|
||||
public function getGridFs()
|
||||
{
|
||||
return $this->gridFs;
|
||||
}
|
||||
}
|
18
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoConfigInterface.php
vendored
Normal file
18
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoConfigInterface.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Flow\Mongo;
|
||||
|
||||
use Flow\ConfigInterface;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
interface MongoConfigInterface extends ConfigInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return \MongoGridFS
|
||||
*/
|
||||
public function getGridFs();
|
||||
|
||||
}
|
181
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoFile.php
vendored
Normal file
181
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoFile.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
namespace Flow\Mongo;
|
||||
|
||||
use Flow\File;
|
||||
use Flow\Request;
|
||||
use Flow\RequestInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Notes:
|
||||
*
|
||||
* - One should ensure indices on the gridfs collection on the property 'flowIdentifier'.
|
||||
* - Chunk preprocessor not supported (must not modify chunks size)!
|
||||
* - Must use 'forceChunkSize=true' on client side.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class MongoFile extends File
|
||||
{
|
||||
private $uploadGridFsFile;
|
||||
|
||||
/**
|
||||
* @var MongoConfigInterface
|
||||
*/
|
||||
private $config;
|
||||
|
||||
function __construct(MongoConfigInterface $config, RequestInterface $request = null)
|
||||
{
|
||||
if ($request === null) {
|
||||
$request = new Request();
|
||||
}
|
||||
parent::__construct($config, $request);
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* return array
|
||||
*/
|
||||
protected function getGridFsFile()
|
||||
{
|
||||
if (!$this->uploadGridFsFile) {
|
||||
$gridFsFileQuery = $this->getGridFsFileQuery();
|
||||
$changed = $gridFsFileQuery;
|
||||
$changed['flowUpdated'] = new \MongoDate();
|
||||
$this->uploadGridFsFile = $this->config->getGridFs()->findAndModify($gridFsFileQuery, $changed, null,
|
||||
['upsert' => true, 'new' => true]);
|
||||
}
|
||||
|
||||
return $this->uploadGridFsFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $index int|string 1-based
|
||||
* @return bool
|
||||
*/
|
||||
public function chunkExists($index)
|
||||
{
|
||||
return $this->config->getGridFs()->chunks->find([
|
||||
'files_id' => $this->getGridFsFile()['_id'],
|
||||
'n' => (intval($index) - 1)
|
||||
])->limit(1)->hasNext();
|
||||
}
|
||||
|
||||
public function checkChunk()
|
||||
{
|
||||
return $this->chunkExists($this->request->getCurrentChunkNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save chunk
|
||||
* @return bool
|
||||
* @throws \Exception if upload size is invalid or some other unexpected error occurred.
|
||||
*/
|
||||
public function saveChunk()
|
||||
{
|
||||
try {
|
||||
$file = $this->request->getFile();
|
||||
|
||||
$chunkQuery = [
|
||||
'files_id' => $this->getGridFsFile()['_id'],
|
||||
'n' => intval($this->request->getCurrentChunkNumber()) - 1,
|
||||
];
|
||||
$chunk = $chunkQuery;
|
||||
$data = file_get_contents($file['tmp_name']);
|
||||
$actualChunkSize = strlen($data);
|
||||
if ($actualChunkSize > $this->request->getDefaultChunkSize() ||
|
||||
($actualChunkSize < $this->request->getDefaultChunkSize() &&
|
||||
$this->request->getCurrentChunkNumber() != $this->request->getTotalChunks())
|
||||
) {
|
||||
throw new \Exception("Invalid upload! (size: {$actualChunkSize})");
|
||||
}
|
||||
$chunk['data'] = new \MongoBinData($data, 0); // \MongoBinData::GENERIC is not defined for older mongo drivers
|
||||
$this->config->getGridFs()->chunks->findAndModify($chunkQuery, $chunk, [], ['upsert' => true]);
|
||||
unlink($file['tmp_name']);
|
||||
|
||||
$this->ensureIndices();
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
// try to remove a possibly (partly) stored chunk:
|
||||
if (isset($chunkQuery)) {
|
||||
$this->config->getGridFs()->chunks->remove($chunkQuery);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function validateFile()
|
||||
{
|
||||
$totalChunks = $this->request->getTotalChunks();
|
||||
|
||||
for ($i = 1; $i <= $totalChunks; $i++) {
|
||||
if (!$this->chunkExists($i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge all chunks to single file
|
||||
* @param $metadata array additional metadata for final file
|
||||
* @return \MongoId|bool of saved file or false if file was already saved
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function saveToGridFs($metadata = null)
|
||||
{
|
||||
$file = $this->getGridFsFile();
|
||||
$file['flowStatus'] = 'finished';
|
||||
$file['metadata'] = $metadata;
|
||||
$result = $this->config->getGridFs()->findAndModify($this->getGridFsFileQuery(), $file);
|
||||
// on second invocation no more file can be found, as the flowStatus changed:
|
||||
if (is_null($result)) {
|
||||
return false;
|
||||
} else {
|
||||
return $file['_id'];
|
||||
}
|
||||
}
|
||||
|
||||
public function save($destination)
|
||||
{
|
||||
throw new \Exception("Must not use 'save' on MongoFile - use 'saveToGridFs'!");
|
||||
}
|
||||
|
||||
public function deleteChunks()
|
||||
{
|
||||
// nothing to do, as chunks are directly part of the final file
|
||||
}
|
||||
|
||||
public function ensureIndices()
|
||||
{
|
||||
$chunksCollection = $this->config->getGridFs()->chunks;
|
||||
$indexKeys = ['files_id' => 1, 'n' => 1];
|
||||
$indexOptions = ['unique' => true, 'background' => true];
|
||||
if(method_exists($chunksCollection, 'createIndex')) { // only available for PECL mongo >= 1.5.0
|
||||
$chunksCollection->createIndex($indexKeys, $indexOptions);
|
||||
} else {
|
||||
$chunksCollection->ensureIndex($indexKeys, $indexOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getGridFsFileQuery()
|
||||
{
|
||||
return [
|
||||
'flowIdentifier' => $this->request->getIdentifier(),
|
||||
'flowStatus' => 'uploading',
|
||||
'filename' => $this->request->getFileName(),
|
||||
'chunkSize' => intval($this->request->getDefaultChunkSize()),
|
||||
'length' => intval($this->request->getTotalSize())
|
||||
];
|
||||
}
|
||||
}
|
31
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoUploader.php
vendored
Normal file
31
vendor/flowjs/flow-php-server/src/Flow/Mongo/MongoUploader.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Flow\Mongo;
|
||||
|
||||
use Flow\FileOpenException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class MongoUploader
|
||||
{
|
||||
/**
|
||||
* Delete chunks older than expiration time.
|
||||
*
|
||||
* @param \MongoGridFS $gridFs
|
||||
* @param int $expirationTime seconds
|
||||
*
|
||||
* @throws FileOpenException
|
||||
*/
|
||||
public static function pruneChunks($gridFs, $expirationTime = 172800)
|
||||
{
|
||||
$result = $gridFs->remove([
|
||||
'flowUpdated' => ['$lt' => new \MongoDate(time() - $expirationTime)],
|
||||
'flowStatus' => 'uploading'
|
||||
]);
|
||||
|
||||
if (!$result) {
|
||||
throw new FileOpenException("Could not remove chunks!");
|
||||
}
|
||||
}
|
||||
}
|
50
vendor/flowjs/flow-php-server/src/Flow/Mongo/README.md
vendored
Normal file
50
vendor/flowjs/flow-php-server/src/Flow/Mongo/README.md
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
Usage
|
||||
--------------
|
||||
|
||||
* Must use 'forceChunkSize=true' on client side.
|
||||
* Chunk preprocessor not supported.
|
||||
* One should ensure indices on the gridfs collection on the property 'flowIdentifier'.
|
||||
|
||||
Besides the points above, the usage is analogous to the 'normal' flow-php:
|
||||
|
||||
```php
|
||||
$config = new \Flow\Mongo\MongoConfig($yourGridFs);
|
||||
$file = new \Flow\Mongo\MongoFile($config);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
if ($file->checkChunk()) {
|
||||
header("HTTP/1.1 200 Ok");
|
||||
} else {
|
||||
header("HTTP/1.1 204 No Content");
|
||||
return ;
|
||||
}
|
||||
} else {
|
||||
if ($file->validateChunk()) {
|
||||
$file->saveChunk();
|
||||
} else {
|
||||
// error, invalid chunk upload request, retry
|
||||
header("HTTP/1.1 400 Bad Request");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if ($file->validateFile()) {
|
||||
// File upload was completed
|
||||
$id = $file->saveToGridFs(['your metadata'=>'value']);
|
||||
if($id) {
|
||||
//do custom post processing here, $id is the MongoId of the gridfs file
|
||||
}
|
||||
} else {
|
||||
// This is not a final chunk, continue to upload
|
||||
}
|
||||
```
|
||||
|
||||
Delete unfinished files
|
||||
-----------------------
|
||||
|
||||
For this you should setup cron, which would check each chunk upload time.
|
||||
If chunk is uploaded long time ago, then chunk should be deleted.
|
||||
|
||||
Helper method for checking this:
|
||||
```php
|
||||
\Flow\Mongo\MongoUploader::pruneChunks($yourGridFs);
|
||||
```
|
152
vendor/flowjs/flow-php-server/src/Flow/Request.php
vendored
Normal file
152
vendor/flowjs/flow-php-server/src/Flow/Request.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class Request implements RequestInterface
|
||||
{
|
||||
/**
|
||||
* Request parameters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* File
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array|null $params
|
||||
* @param array|null $file
|
||||
*/
|
||||
public function __construct($params = null, $file = null)
|
||||
{
|
||||
if ($params === null) {
|
||||
$params = $_REQUEST;
|
||||
}
|
||||
|
||||
if ($file === null && isset($_FILES['file'])) {
|
||||
$file = $_FILES['file'];
|
||||
}
|
||||
|
||||
$this->params = $params;
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameter value
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string|int|null
|
||||
*/
|
||||
public function getParam($name)
|
||||
{
|
||||
return isset($this->params[$name]) ? $this->params[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get uploaded file name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFileName()
|
||||
{
|
||||
return $this->getParam('flowFilename');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total file size in bytes
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTotalSize()
|
||||
{
|
||||
return $this->getParam('flowTotalSize');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file unique identifier
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->getParam('flowIdentifier');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file relative path
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRelativePath()
|
||||
{
|
||||
return $this->getParam('flowRelativePath');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total chunks number
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTotalChunks()
|
||||
{
|
||||
return $this->getParam('flowTotalChunks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default chunk size
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getDefaultChunkSize()
|
||||
{
|
||||
return $this->getParam('flowChunkSize');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current uploaded chunk number, starts with 1
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCurrentChunkNumber()
|
||||
{
|
||||
return $this->getParam('flowChunkNumber');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current uploaded chunk size
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCurrentChunkSize()
|
||||
{
|
||||
return $this->getParam('flowCurrentChunkSize');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return $_FILES request
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getFile()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if request is formed by fusty flow
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFustyFlowRequest()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
76
vendor/flowjs/flow-php-server/src/Flow/RequestInterface.php
vendored
Normal file
76
vendor/flowjs/flow-php-server/src/Flow/RequestInterface.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
interface RequestInterface
|
||||
{
|
||||
/**
|
||||
* Get uploaded file name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName();
|
||||
|
||||
/**
|
||||
* Get total file size in bytes
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalSize();
|
||||
|
||||
/**
|
||||
* Get file unique identifier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
|
||||
/**
|
||||
* Get file relative path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelativePath();
|
||||
|
||||
/**
|
||||
* Get total chunks number
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalChunks();
|
||||
|
||||
/**
|
||||
* Get default chunk size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDefaultChunkSize();
|
||||
|
||||
/**
|
||||
* Get current uploaded chunk number, starts with 1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCurrentChunkNumber();
|
||||
|
||||
/**
|
||||
* Get current uploaded chunk size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCurrentChunkSize();
|
||||
|
||||
/**
|
||||
* Return $_FILES request
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getFile();
|
||||
|
||||
/**
|
||||
* Checks if request is formed by fusty flow
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFustyFlowRequest();
|
||||
}
|
41
vendor/flowjs/flow-php-server/src/Flow/Uploader.php
vendored
Normal file
41
vendor/flowjs/flow-php-server/src/Flow/Uploader.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Flow;
|
||||
|
||||
class Uploader
|
||||
{
|
||||
/**
|
||||
* Delete chunks older than expiration time.
|
||||
*
|
||||
* @param string $chunksFolder
|
||||
* @param int $expirationTime seconds
|
||||
*
|
||||
* @throws FileOpenException
|
||||
*/
|
||||
public static function pruneChunks($chunksFolder, $expirationTime = 172800)
|
||||
{
|
||||
$handle = opendir($chunksFolder);
|
||||
|
||||
if (!$handle) {
|
||||
throw new FileOpenException('failed to open folder: '.$chunksFolder);
|
||||
}
|
||||
|
||||
while (false !== ($entry = readdir($handle))) {
|
||||
if ($entry == "." || $entry == ".." || $entry == ".gitignore") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $chunksFolder.DIRECTORY_SEPARATOR.$entry;
|
||||
|
||||
if (is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (time() - filemtime($path) > $expirationTime) {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
}
|
||||
}
|
55
vendor/flowjs/flow-php-server/test/Unit/AutoloadTest.php
vendored
Normal file
55
vendor/flowjs/flow-php-server/test/Unit/AutoloadTest.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
/**
|
||||
* Autoload unit tests
|
||||
*
|
||||
* @coversDefaultClass \Flow\Autoloader
|
||||
*
|
||||
* @package Unit
|
||||
*/
|
||||
class AutoloadTest extends FlowUnitCase
|
||||
{
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getDir
|
||||
*/
|
||||
public function testAutoloader_construct_default()
|
||||
{
|
||||
$expDir = realpath(__DIR__ . '/../../src/Flow') . '/..';
|
||||
$autoloader = new \Flow\Autoloader();
|
||||
|
||||
$this->assertSame($expDir, $autoloader->getDir());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getDir
|
||||
*/
|
||||
public function testAutoloader_construct_custom()
|
||||
{
|
||||
$expDir = __DIR__;
|
||||
$autoloader = new \Flow\Autoloader($expDir);
|
||||
|
||||
$this->assertSame($expDir, $autoloader->getDir());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::autoload
|
||||
*/
|
||||
public function testClassesExist()
|
||||
{
|
||||
$autoloader = new \Flow\Autoloader();
|
||||
|
||||
$autoloader->autoload('noclass');
|
||||
$this->assertFalse(class_exists('noclass', false));
|
||||
|
||||
$autoloader->autoload('Flow\NoClass');
|
||||
$this->assertFalse(class_exists('Flow\NoClass', false));
|
||||
|
||||
$autoloader->autoload('Flow\File');
|
||||
$this->assertTrue(class_exists('Flow\File'));
|
||||
}
|
||||
}
|
117
vendor/flowjs/flow-php-server/test/Unit/ConfigTest.php
vendored
Normal file
117
vendor/flowjs/flow-php-server/test/Unit/ConfigTest.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
use Flow\Config;
|
||||
use Flow\Request;
|
||||
|
||||
/**
|
||||
* Config unit tests
|
||||
*
|
||||
* @coversDefaultClass \Flow\Config
|
||||
*
|
||||
* @package Unit
|
||||
*/
|
||||
class ConfigTest extends FlowUnitCase
|
||||
{
|
||||
/**
|
||||
* @covers ::getTempDir
|
||||
* @covers ::getDeleteChunksOnSave
|
||||
* @covers ::getHashNameCallback
|
||||
* @covers ::getPreprocessCallback
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConfig_construct_config()
|
||||
{
|
||||
$exampleConfig = array(
|
||||
'tempDir' => '/some/dir',
|
||||
'deleteChunksOnSave' => TRUE,
|
||||
'hashNameCallback' => '\SomeNs\SomeClass::someMethod',
|
||||
'preprocessCallback' => '\SomeNs\SomeClass::preProcess'
|
||||
);
|
||||
|
||||
$config = new Config($exampleConfig);
|
||||
|
||||
$this->assertSame($exampleConfig['tempDir'], $config->getTempDir());
|
||||
$this->assertSame($exampleConfig['deleteChunksOnSave'], $config->getDeleteChunksOnSave());
|
||||
$this->assertSame($exampleConfig['hashNameCallback'], $config->getHashNameCallback());
|
||||
$this->assertSame($exampleConfig['preprocessCallback'], $config->getPreprocessCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTempDir
|
||||
* @covers ::getDeleteChunksOnSave
|
||||
* @covers ::getHashNameCallback
|
||||
* @covers ::getPreprocessCallback
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConfig_construct_default()
|
||||
{
|
||||
$config = new Config();
|
||||
|
||||
$this->assertSame('', $config->getTempDir());
|
||||
$this->assertSame(true, $config->getDeleteChunksOnSave());
|
||||
$this->assertSame('\Flow\Config::hashNameCallback', $config->getHashNameCallback());
|
||||
$this->assertSame(null, $config->getPreprocessCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTempDir
|
||||
* @covers ::getTempDir
|
||||
*/
|
||||
public function testConfig_setTempDir()
|
||||
{
|
||||
$dir = '/some/dir';
|
||||
$config = new Config();
|
||||
|
||||
$config->setTempDir($dir);
|
||||
$this->assertSame($dir, $config->getTempDir());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setHashNameCallback
|
||||
* @covers ::getHashNameCallback
|
||||
*/
|
||||
public function testConfig_setHashNameCallback()
|
||||
{
|
||||
$callback = '\SomeNs\SomeClass::someMethod';
|
||||
$config = new Config();
|
||||
|
||||
$config->setHashNameCallback($callback);
|
||||
$this->assertSame($callback, $config->getHashNameCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setPreprocessCallback
|
||||
* @covers ::getPreprocessCallback
|
||||
*/
|
||||
public function testConfig_setPreprocessCallback()
|
||||
{
|
||||
$callback = '\SomeNs\SomeClass::someOtherMethod';
|
||||
$config = new Config();
|
||||
|
||||
$config->setPreprocessCallback($callback);
|
||||
$this->assertSame($callback, $config->getPreprocessCallback());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setDeleteChunksOnSave
|
||||
* @covers ::getDeleteChunksOnSave
|
||||
*/
|
||||
public function testConfig_setDeleteChunksOnSave()
|
||||
{
|
||||
$config = new Config();
|
||||
|
||||
$config->setDeleteChunksOnSave(false);
|
||||
$this->assertFalse($config->getDeleteChunksOnSave());
|
||||
}
|
||||
|
||||
public function testConfig_hashNameCallback()
|
||||
{
|
||||
$request = new Request($this->requestArr);
|
||||
|
||||
$expHash = sha1($request->getIdentifier());
|
||||
$this->assertSame($expHash, Config::hashNameCallback($request));
|
||||
}
|
||||
}
|
428
vendor/flowjs/flow-php-server/test/Unit/FileTest.php
vendored
Normal file
428
vendor/flowjs/flow-php-server/test/Unit/FileTest.php
vendored
Normal file
@@ -0,0 +1,428 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
use Flow\File;
|
||||
use Flow\Config;
|
||||
use Flow\FileLockException;
|
||||
use Flow\FileOpenException;
|
||||
use Flow\Request;
|
||||
use \org\bovigo\vfs\vfsStreamWrapper;
|
||||
use \org\bovigo\vfs\vfsStreamDirectory;
|
||||
use \org\bovigo\vfs\vfsStream;
|
||||
|
||||
/**
|
||||
* File unit tests
|
||||
*
|
||||
* @coversDefaultClass \Flow\File
|
||||
*
|
||||
* @package Unit
|
||||
*/
|
||||
class FileTest extends FlowUnitCase
|
||||
{
|
||||
/**
|
||||
* Config
|
||||
*
|
||||
* @var Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Virtual file system
|
||||
*
|
||||
* @var vfsStreamDirectory
|
||||
*/
|
||||
protected $vfs;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Setup virtual file system
|
||||
vfsStreamWrapper::register();
|
||||
$this->vfs = new vfsStreamDirectory('chunks');
|
||||
vfsStreamWrapper::setRoot($this->vfs);
|
||||
|
||||
// Setup Config
|
||||
$this->config = new Config();
|
||||
$this->config->setTempDir($this->vfs->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getIdentifier
|
||||
*/
|
||||
public function testFile_construct_withRequest()
|
||||
{
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$expIdentifier = sha1($this->requestArr['flowIdentifier']);
|
||||
$this->assertSame($expIdentifier, $file->getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getIdentifier
|
||||
*/
|
||||
public function testFile_construct_noRequest()
|
||||
{
|
||||
$_REQUEST = $this->requestArr;
|
||||
|
||||
$file = new File($this->config);
|
||||
|
||||
$expIdentifier = sha1($this->requestArr['flowIdentifier']);
|
||||
$this->assertSame($expIdentifier, $file->getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getChunkPath
|
||||
*/
|
||||
public function testFile_construct_getChunkPath()
|
||||
{
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$expPath = $this->vfs->url() . DIRECTORY_SEPARATOR . sha1($this->requestArr['flowIdentifier']) . '_1';
|
||||
$this->assertSame($expPath, $file->getChunkPath(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkChunk
|
||||
*/
|
||||
public function testFile_construct_checkChunk()
|
||||
{
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$this->assertFalse($file->checkChunk());
|
||||
|
||||
$chunkName = sha1($request->getIdentifier()) . '_' . $request->getCurrentChunkNumber();
|
||||
$firstChunk = vfsStream::newFile($chunkName);
|
||||
$this->vfs->addChild($firstChunk);
|
||||
|
||||
$this->assertTrue($file->checkChunk());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::validateChunk
|
||||
*/
|
||||
public function testFile_validateChunk()
|
||||
{
|
||||
// No $_FILES
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$this->assertFalse($file->validateChunk());
|
||||
|
||||
// No 'file' key $_FILES
|
||||
$fileInfo = new \ArrayObject();
|
||||
$request = new Request($this->requestArr, $fileInfo);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$this->assertFalse($file->validateChunk());
|
||||
|
||||
// Upload OK
|
||||
$fileInfo->exchangeArray(array(
|
||||
'size' => 10,
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'tmp_name' => ''
|
||||
));
|
||||
$this->assertTrue($file->validateChunk());
|
||||
|
||||
// Chunk size doesn't match
|
||||
$fileInfo->exchangeArray(array(
|
||||
'size' => 9,
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'tmp_name' => ''
|
||||
));
|
||||
$this->assertFalse($file->validateChunk());
|
||||
|
||||
// Upload error
|
||||
$fileInfo->exchangeArray(array(
|
||||
'size' => 10,
|
||||
'error' => UPLOAD_ERR_EXTENSION,
|
||||
'tmp_name' => ''
|
||||
));
|
||||
$this->assertFalse($file->validateChunk());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::validateFile
|
||||
*/
|
||||
public function testFile_validateFile()
|
||||
{
|
||||
$this->requestArr['flowTotalSize'] = 10;
|
||||
$this->requestArr['flowTotalChunks'] = 3;
|
||||
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
$chunkPrefix = sha1($request->getIdentifier()) . '_';
|
||||
|
||||
// No chunks uploaded yet
|
||||
$this->assertFalse($file->validateFile());
|
||||
|
||||
// First chunk
|
||||
$firstChunk = vfsStream::newFile($chunkPrefix . '1');
|
||||
$firstChunk->setContent('123');
|
||||
$this->vfs->addChild($firstChunk);
|
||||
|
||||
// Uploaded not yet complete
|
||||
$this->assertFalse($file->validateFile());
|
||||
|
||||
// Second chunk
|
||||
$secondChunk = vfsStream::newFile($chunkPrefix . '2');
|
||||
$secondChunk->setContent('456');
|
||||
$this->vfs->addChild($secondChunk);
|
||||
|
||||
// Uploaded not yet complete
|
||||
$this->assertFalse($file->validateFile());
|
||||
|
||||
// Third chunk
|
||||
$lastChunk = vfsStream::newFile($chunkPrefix . '3');
|
||||
$lastChunk->setContent('7890');
|
||||
$this->vfs->addChild($lastChunk);
|
||||
|
||||
// All chunks uploaded
|
||||
$this->assertTrue($file->validateFile());
|
||||
|
||||
//// Test false values
|
||||
|
||||
// File size doesn't match
|
||||
$lastChunk->setContent('789');
|
||||
$this->assertFalse($file->validateFile());
|
||||
|
||||
// Correct file size and expect true
|
||||
$this->requestArr['flowTotalSize'] = 9;
|
||||
$this->assertTrue($file->validateFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteChunks
|
||||
*/
|
||||
public function testFile_deleteChunks()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$this->requestArr['flowTotalChunks'] = 4;
|
||||
|
||||
$fileInfo = new \ArrayObject();
|
||||
$request = new Request($this->requestArr, $fileInfo);
|
||||
$file = new File($this->config, $request);
|
||||
$chunkPrefix = sha1($request->getIdentifier()) . '_';
|
||||
|
||||
$firstChunk = vfsStream::newFile($chunkPrefix . 1);
|
||||
$this->vfs->addChild($firstChunk);
|
||||
|
||||
$secondChunk = vfsStream::newFile($chunkPrefix . 3);
|
||||
$this->vfs->addChild($secondChunk);
|
||||
|
||||
$thirdChunk = vfsStream::newFile('other');
|
||||
$this->vfs->addChild($thirdChunk);
|
||||
|
||||
//// Actual test
|
||||
|
||||
$this->assertTrue(file_exists($firstChunk->url()));
|
||||
$this->assertTrue(file_exists($secondChunk->url()));
|
||||
$this->assertTrue(file_exists($thirdChunk->url()));
|
||||
|
||||
$file->deleteChunks();
|
||||
$this->assertFalse(file_exists($firstChunk->url()));
|
||||
$this->assertFalse(file_exists($secondChunk->url()));
|
||||
$this->assertTrue(file_exists($thirdChunk->url()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::saveChunk
|
||||
*/
|
||||
public function testFile_saveChunk()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
// Setup temporary file
|
||||
$tmpDir = new vfsStreamDirectory('tmp');
|
||||
$tmpFile = vfsStream::newFile('tmpFile');
|
||||
$tmpFile->setContent('1234567890');
|
||||
$tmpDir->addChild($tmpFile);
|
||||
$this->vfs->addChild($tmpDir);
|
||||
$this->filesArr['file']['tmp_name'] = $tmpFile->url();
|
||||
|
||||
// Mock File to use rename instead of move_uploaded_file
|
||||
$request = new Request($this->requestArr, $this->filesArr['file']);
|
||||
$file = $this->getMock('Flow\File', array('_move_uploaded_file'), array($this->config, $request));
|
||||
$file->expects($this->once())
|
||||
->method('_move_uploaded_file')
|
||||
->will($this->returnCallback(function ($filename, $destination) {
|
||||
return rename($filename, $destination);
|
||||
}));
|
||||
|
||||
// Expected destination file
|
||||
$expDstFile = $this->vfs->url() . DIRECTORY_SEPARATOR . sha1($request->getIdentifier()) . '_1';
|
||||
|
||||
//// Accrual test
|
||||
|
||||
$this->assertFalse(file_exists($expDstFile));
|
||||
$this->assertTrue(file_exists($tmpFile->url()));
|
||||
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$this->assertTrue($file->saveChunk());
|
||||
|
||||
$this->assertTrue(file_exists($expDstFile));
|
||||
//$this->assertFalse(file_exists($tmpFile->url()));
|
||||
|
||||
$this->assertSame('1234567890', file_get_contents($expDstFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
*/
|
||||
public function testFile_save()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$this->requestArr['flowTotalChunks'] = 3;
|
||||
$this->requestArr['flowTotalSize'] = 10;
|
||||
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$chunkPrefix = sha1($request->getIdentifier()) . '_';
|
||||
|
||||
$chunk = vfsStream::newFile($chunkPrefix . '1', 0777);
|
||||
$chunk->setContent('0123');
|
||||
$this->vfs->addChild($chunk);
|
||||
|
||||
$chunk = vfsStream::newFile($chunkPrefix . '2', 0777);
|
||||
$chunk->setContent('456');
|
||||
$this->vfs->addChild($chunk);
|
||||
|
||||
$chunk = vfsStream::newFile($chunkPrefix . '3', 0777);
|
||||
$chunk->setContent('789');
|
||||
$this->vfs->addChild($chunk);
|
||||
|
||||
$filePath = $this->vfs->url() . DIRECTORY_SEPARATOR . 'file';
|
||||
|
||||
//// Actual test
|
||||
|
||||
$this->assertTrue($file->save($filePath));
|
||||
$this->assertTrue(file_exists($filePath));
|
||||
$this->assertEquals($request->getTotalSize(), filesize($filePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
*/
|
||||
public function testFile_save_lock()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$dstFile = $this->vfs->url() . DIRECTORY_SEPARATOR . 'file';
|
||||
|
||||
// Lock file
|
||||
$fh = fopen($dstFile, 'wb');
|
||||
$this->assertTrue(flock($fh, LOCK_EX));
|
||||
|
||||
//// Actual test
|
||||
|
||||
try {
|
||||
// practically on a normal file system exception would not be thrown, this happens
|
||||
// because vfsStreamWrapper does not support locking with block
|
||||
$file->save($dstFile);
|
||||
$this->fail();
|
||||
} catch (FileLockException $e) {
|
||||
$this->assertEquals('failed to lock file: ' . $dstFile, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
*/
|
||||
public function testFile_save_FileOpenException()
|
||||
{
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
try {
|
||||
@$file->save('not/existing/path');
|
||||
$this->fail();
|
||||
} catch (FileOpenException $e) {
|
||||
$this->assertEquals('failed to open destination file: not/existing/path', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
*/
|
||||
public function testFile_save_chunk_FileOpenException()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$this->requestArr['flowTotalChunks'] = 3;
|
||||
$this->requestArr['flowTotalSize'] = 10;
|
||||
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$chunkPrefix = sha1($request->getIdentifier()) . '_';
|
||||
|
||||
$chunk = vfsStream::newFile($chunkPrefix . '1', 0777);
|
||||
$chunk->setContent('0123');
|
||||
$this->vfs->addChild($chunk);
|
||||
|
||||
$chunk = vfsStream::newFile($chunkPrefix . '2', 0777);
|
||||
$chunk->setContent('456');
|
||||
$this->vfs->addChild($chunk);
|
||||
|
||||
$missingChunk = $this->vfs->url() . DIRECTORY_SEPARATOR . $chunkPrefix . '3';
|
||||
$filePath = $this->vfs->url() . DIRECTORY_SEPARATOR . 'file';
|
||||
|
||||
//// Actual test
|
||||
|
||||
try {
|
||||
@$file->save($filePath);
|
||||
} catch (FileOpenException $e) {
|
||||
$this->assertEquals('failed to open chunk: ' . $missingChunk, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save
|
||||
*/
|
||||
public function testFile_save_preProcess()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$this->requestArr['flowTotalChunks'] = 1;
|
||||
$this->requestArr['flowTotalSize'] = 10;
|
||||
$processCalled = false;
|
||||
|
||||
$process = function($chunk) use (&$processCalled)
|
||||
{
|
||||
$processCalled = true;
|
||||
};
|
||||
|
||||
$this->config->setPreprocessCallback($process);
|
||||
|
||||
$request = new Request($this->requestArr);
|
||||
$file = new File($this->config, $request);
|
||||
|
||||
$chunkPrefix = sha1($request->getIdentifier()) . '_';
|
||||
|
||||
$chunk = vfsStream::newFile($chunkPrefix . '1', 0777);
|
||||
$chunk->setContent('1234567890');
|
||||
$this->vfs->addChild($chunk);
|
||||
|
||||
$filePath = $this->vfs->url() . DIRECTORY_SEPARATOR . 'file';
|
||||
|
||||
//// Actual test
|
||||
|
||||
$this->assertTrue($file->save($filePath));
|
||||
$this->assertTrue(file_exists($filePath));
|
||||
$this->assertEquals($request->getTotalSize(), filesize($filePath));
|
||||
$this->assertTrue($processCalled);
|
||||
}
|
||||
}
|
53
vendor/flowjs/flow-php-server/test/Unit/FlowUnitCase.php
vendored
Normal file
53
vendor/flowjs/flow-php-server/test/Unit/FlowUnitCase.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
use ArrayObject;
|
||||
|
||||
class FlowUnitCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test request
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $requestArr;
|
||||
|
||||
/**
|
||||
* $_FILES
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filesArr;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->requestArr = new ArrayObject(array(
|
||||
'flowChunkNumber' => 1,
|
||||
'flowChunkSize' => 1048576,
|
||||
'flowCurrentChunkSize' => 10,
|
||||
'flowTotalSize' => 100,
|
||||
'flowIdentifier' => '13632-prettifyjs',
|
||||
'flowFilename' => 'prettify.js',
|
||||
'flowRelativePath' => 'home/prettify.js',
|
||||
'flowTotalChunks' => 42
|
||||
));
|
||||
|
||||
$this->filesArr = array(
|
||||
'file' => array(
|
||||
'name' => 'someFile.gif',
|
||||
'type' => 'image/gif',
|
||||
'size' => '10',
|
||||
'tmp_name' => '/tmp/abc1234',
|
||||
'error' => UPLOAD_ERR_OK
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$_REQUEST = array();
|
||||
$_FILES = array();
|
||||
}
|
||||
}
|
121
vendor/flowjs/flow-php-server/test/Unit/FustyRequestTest.php
vendored
Normal file
121
vendor/flowjs/flow-php-server/test/Unit/FustyRequestTest.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
use Flow\File;
|
||||
use Flow\FustyRequest;
|
||||
use Flow\Config;
|
||||
use org\bovigo\vfs\vfsStreamWrapper;
|
||||
use org\bovigo\vfs\vfsStreamDirectory;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
|
||||
/**
|
||||
* FustyRequest unit tests
|
||||
*
|
||||
* @coversDefaultClass \Flow\FustyRequest
|
||||
*
|
||||
* @package Unit
|
||||
*/
|
||||
class FustyRequestTest extends FlowUnitCase
|
||||
{
|
||||
/**
|
||||
* Virtual file system
|
||||
*
|
||||
* @var vfsStreamDirectory
|
||||
*/
|
||||
protected $vfs;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
vfsStreamWrapper::register();
|
||||
$this->vfs = new vfsStreamDirectory('chunks');
|
||||
vfsStreamWrapper::setRoot($this->vfs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::isFustyFlowRequest
|
||||
*/
|
||||
public function testFustyRequest_construct()
|
||||
{
|
||||
$firstChunk = vfsStream::newFile('temp_file');
|
||||
$firstChunk->setContent('1234567890');
|
||||
$this->vfs->addChild($firstChunk);
|
||||
|
||||
$fileInfo = new \ArrayObject(array(
|
||||
'size' => 10,
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'tmp_name' => $firstChunk->url()
|
||||
));
|
||||
|
||||
$request = new \ArrayObject(array(
|
||||
'flowIdentifier' => '13632-prettifyjs',
|
||||
'flowFilename' => 'prettify.js',
|
||||
'flowRelativePath' => 'home/prettify.js'
|
||||
));
|
||||
|
||||
$fustyRequest = new FustyRequest($request, $fileInfo);
|
||||
|
||||
$this->assertSame('prettify.js', $fustyRequest->getFileName());
|
||||
$this->assertSame('13632-prettifyjs', $fustyRequest->getIdentifier());
|
||||
$this->assertSame('home/prettify.js', $fustyRequest->getRelativePath());
|
||||
$this->assertSame(1, $fustyRequest->getCurrentChunkNumber());
|
||||
$this->assertTrue($fustyRequest->isFustyFlowRequest());
|
||||
$this->assertSame(10, $fustyRequest->getTotalSize());
|
||||
$this->assertSame(10, $fustyRequest->getDefaultChunkSize());
|
||||
$this->assertSame(10, $fustyRequest->getCurrentChunkSize());
|
||||
$this->assertSame(1, $fustyRequest->getTotalChunks());
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testFustyRequest_ValidateUpload()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$firstChunk = vfsStream::newFile('temp_file');
|
||||
$firstChunk->setContent('1234567890');
|
||||
$this->vfs->addChild($firstChunk);
|
||||
|
||||
$fileInfo = new \ArrayObject(array(
|
||||
'size' => 10,
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'tmp_name' => $firstChunk->url()
|
||||
));
|
||||
|
||||
$request = new \ArrayObject(array(
|
||||
'flowIdentifier' => '13632-prettifyjs',
|
||||
'flowFilename' => 'prettify.js',
|
||||
'flowRelativePath' => 'home/prettify.js'
|
||||
));
|
||||
|
||||
$fustyRequest = new FustyRequest($request, $fileInfo);
|
||||
|
||||
$config = new Config();
|
||||
$config->setTempDir($this->vfs->url());
|
||||
|
||||
/** @var File $file */
|
||||
$file = $this->getMock('Flow\File', array('_move_uploaded_file'), array($config, $fustyRequest));
|
||||
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$file->expects($this->once())
|
||||
->method('_move_uploaded_file')
|
||||
->will($this->returnCallback(function ($filename, $destination) {
|
||||
return rename($filename, $destination);
|
||||
}));
|
||||
|
||||
//// Actual test
|
||||
|
||||
$this->assertTrue($file->validateChunk());
|
||||
$this->assertFalse($file->validateFile());
|
||||
|
||||
$this->assertTrue($file->saveChunk());
|
||||
$this->assertTrue($file->validateFile());
|
||||
$path = $this->vfs->url() . DIRECTORY_SEPARATOR . 'new';
|
||||
$this->assertTrue($file->save($path));
|
||||
$this->assertEquals(10, filesize($path));
|
||||
}
|
||||
}
|
86
vendor/flowjs/flow-php-server/test/Unit/RequestTest.php
vendored
Normal file
86
vendor/flowjs/flow-php-server/test/Unit/RequestTest.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
use Flow\Request;
|
||||
|
||||
/**
|
||||
* Request unit tests
|
||||
*
|
||||
* @coversDefaultClass \Flow\Request
|
||||
*
|
||||
* @package Unit
|
||||
*/
|
||||
class RequestTest extends FlowUnitCase
|
||||
{
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testRequest_construct_withREQUEST()
|
||||
{
|
||||
$_REQUEST = $this->requestArr;
|
||||
|
||||
$request = new Request();
|
||||
$this->assertSame('prettify.js', $request->getFileName());
|
||||
$this->assertSame(100, $request->getTotalSize());
|
||||
$this->assertSame('13632-prettifyjs', $request->getIdentifier());
|
||||
$this->assertSame('home/prettify.js', $request->getRelativePath());
|
||||
$this->assertSame(42, $request->getTotalChunks());
|
||||
$this->assertSame(1048576, $request->getDefaultChunkSize());
|
||||
$this->assertSame(1, $request->getCurrentChunkNumber());
|
||||
$this->assertSame(10, $request->getCurrentChunkSize());
|
||||
$this->assertSame(null, $request->getFile());
|
||||
$this->assertFalse($request->isFustyFlowRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getParam
|
||||
* @covers ::getFileName
|
||||
* @covers ::getTotalSize
|
||||
* @covers ::getIdentifier
|
||||
* @covers ::getRelativePath
|
||||
* @covers ::getTotalChunks
|
||||
* @covers ::getDefaultChunkSize
|
||||
* @covers ::getCurrentChunkNumber
|
||||
* @covers ::getCurrentChunkSize
|
||||
* @covers ::getFile
|
||||
* @covers ::isFustyFlowRequest
|
||||
*/
|
||||
public function testRequest_construct_withCustomRequest()
|
||||
{
|
||||
$request = new Request($this->requestArr);
|
||||
|
||||
$this->assertSame('prettify.js', $request->getFileName());
|
||||
$this->assertSame(100, $request->getTotalSize());
|
||||
$this->assertSame('13632-prettifyjs', $request->getIdentifier());
|
||||
$this->assertSame('home/prettify.js', $request->getRelativePath());
|
||||
$this->assertSame(42, $request->getTotalChunks());
|
||||
$this->assertSame(1048576, $request->getDefaultChunkSize());
|
||||
$this->assertSame(1, $request->getCurrentChunkNumber());
|
||||
$this->assertSame(10, $request->getCurrentChunkSize());
|
||||
$this->assertSame(null, $request->getFile());
|
||||
$this->assertFalse($request->isFustyFlowRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testRequest_construct_withFILES()
|
||||
{
|
||||
$_FILES = $this->filesArr;
|
||||
|
||||
$request = new Request();
|
||||
$this->assertSame($this->filesArr['file'], $request->getFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testRequest_construct_withCustFiles()
|
||||
{
|
||||
$request = new Request(null, $this->filesArr['file']);
|
||||
$this->assertSame($this->filesArr['file'], $request->getFile());
|
||||
}
|
||||
}
|
77
vendor/flowjs/flow-php-server/test/Unit/UploaderTest.php
vendored
Normal file
77
vendor/flowjs/flow-php-server/test/Unit/UploaderTest.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
|
||||
use Flow\FileOpenException;
|
||||
use org\bovigo\vfs\vfsStreamWrapper;
|
||||
use org\bovigo\vfs\vfsStreamDirectory;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use Flow\Uploader;
|
||||
|
||||
/**
|
||||
* Uploader unit tests
|
||||
*
|
||||
* @coversDefaultClass \Flow\Uploader
|
||||
*
|
||||
* @package Unit
|
||||
*/
|
||||
class UploaderTest extends FlowUnitCase
|
||||
{
|
||||
/**
|
||||
* Virtual file system
|
||||
*
|
||||
* @var vfsStreamDirectory
|
||||
*/
|
||||
protected $vfs;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
vfsStreamWrapper::register();
|
||||
$this->vfs = new vfsStreamDirectory('chunks');
|
||||
vfsStreamWrapper::setRoot($this->vfs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::pruneChunks
|
||||
*/
|
||||
public function testUploader_pruneChunks()
|
||||
{
|
||||
//// Setup test
|
||||
|
||||
$newDir = vfsStream::newDirectory('1');
|
||||
$newDir->lastModified(time()-31);
|
||||
$newDir->lastModified(time());
|
||||
|
||||
$fileFirst = vfsStream::newFile('file31');
|
||||
$fileFirst->lastModified(time()-31);
|
||||
$fileSecond = vfsStream::newFile('random_file');
|
||||
$fileSecond->lastModified(time()-30);
|
||||
$upDir = vfsStream::newFile('..');
|
||||
|
||||
$this->vfs->addChild($newDir);
|
||||
$this->vfs->addChild($fileFirst);
|
||||
$this->vfs->addChild($fileSecond);
|
||||
$this->vfs->addChild($upDir);
|
||||
|
||||
//// Actual test
|
||||
|
||||
Uploader::pruneChunks($this->vfs->url(), 30);
|
||||
$this->assertTrue(file_exists($newDir->url()));
|
||||
$this->assertFalse(file_exists($fileFirst->url()));
|
||||
$this->assertTrue(file_exists($fileSecond->url()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::pruneChunks
|
||||
*/
|
||||
public function testUploader_exception()
|
||||
{
|
||||
try {
|
||||
@Uploader::pruneChunks('not/existing/dir', 30);
|
||||
$this->fail();
|
||||
} catch (FileOpenException $e) {
|
||||
$this->assertSame('failed to open folder: not/existing/dir', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
7
vendor/flowjs/flow-php-server/test/bootstrap.php
vendored
Normal file
7
vendor/flowjs/flow-php-server/test/bootstrap.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once(__DIR__ . '/../vendor/autoload.php');
|
||||
require_once(__DIR__ . '/../src/Flow/Autoloader.php');
|
||||
require_once(__DIR__ . '/Unit/FlowUnitCase.php');
|
||||
|
||||
Flow\Autoloader::register();
|
60
vendor/flowjs/flow-php-server/travis.phpunit.xml
vendored
Normal file
60
vendor/flowjs/flow-php-server/travis.phpunit.xml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Flow Test Suite">
|
||||
<directory>./test/Unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./src/Flow/</directory>
|
||||
<exclude>
|
||||
<file>./src/Flow/Basic.php</file>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<logging>
|
||||
<log type="coverage-clover" target="build/coverage.xml"/>
|
||||
<log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
|
||||
</logging>
|
||||
|
||||
<listeners>
|
||||
<listener class="League\PHPUnitCoverageListener\Listener">
|
||||
<arguments>
|
||||
<array>
|
||||
<element key="printer">
|
||||
<object class="League\PHPUnitCoverageListener\Printer\StdOut"/>
|
||||
</element>
|
||||
<element key="hook">
|
||||
<object class="League\PHPUnitCoverageListener\Hook\Travis"/>
|
||||
</element>
|
||||
<element key="namespace">
|
||||
<string>Flow</string>
|
||||
</element>
|
||||
<element key="repo_token">
|
||||
<string>TtscpSyNYUnuG2LkxtWCQmAtBk8vWAMsI</string>
|
||||
</element>
|
||||
<element key="target_url">
|
||||
<string>https://coveralls.io/api/v1/jobs</string>
|
||||
</element>
|
||||
<element key="coverage_dir">
|
||||
<string>build</string>
|
||||
</element>
|
||||
</array>
|
||||
</arguments>
|
||||
</listener>
|
||||
</listeners>
|
||||
</phpunit>
|
Reference in New Issue
Block a user