Laravel version update

Laravel version update
This commit is contained in:
Manish Verma
2018-08-06 18:48:58 +05:30
parent d143048413
commit 126fbb0255
13678 changed files with 1031482 additions and 778530 deletions

View File

@@ -1,4 +1,4 @@
Copyright (c) 2013-2016 Frank de Jonge
Copyright (c) 2013-2018 Frank de Jonge
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env bash
if [[ "$#" -eq 1 ]]; then
echo "Handling \"$1\" brew package..."
else
echo "Brew failed - invalid $0 call"
exit 1;
fi
if [[ $(brew ls --versions "$1") ]]; then
if brew outdated "$1"; then
echo "Package upgrade is not required, skipping"
else
echo "Updating package...";
brew upgrade "$1"
if [ $? -ne 0 ]; then
echo "Upgrade failed"
exit 1
fi
fi
else
echo "Package not available - installing..."
brew install "$1"
if [ $? -ne 0 ]; then
echo "Install failed"
exit 1
fi
fi
echo "Linking installed package..."
brew link "$1"

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
sudo php composer-setup.php --install-dir=/usr/local/bin/ --filename=composer
rm composer-setup.php

View File

@@ -1,19 +0,0 @@
#!/usr/bin/env bash
echo "Here's the OSX environment:"
sw_vers
brew --version
echo "Updating brew..."
brew update
if [[ "${_PHP}" == "hhvm" ]]; then
echo "Adding brew HHVM dependencies..."
brew tap hhvm/hhvm
else
echo "Adding brew PHP dependencies..."
brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/homebrew-php
fi

View File

@@ -14,13 +14,12 @@
}
],
"require": {
"php": ">=5.4.0"
"php": ">=5.5.9"
},
"require-dev": {
"ext-fileinfo": "*",
"phpunit/phpunit": "~4.8",
"mockery/mockery": "~0.9",
"phpspec/phpspec": "^2.2"
"phpspec/phpspec": "^3.4",
"phpunit/phpunit": "^5.7"
},
"autoload": {
"psr-4": {
@@ -30,19 +29,24 @@
"autoload-dev": {
"psr-4": {
"League\\Flysystem\\Stub\\": "stub/"
}
},
"files": [
"tests/PHPUnitHacks.php"
]
},
"suggest": {
"ext-fileinfo": "Required for MimeType",
"league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
"league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
"league/flysystem-copy": "Allows you to use Copy.com storage",
"league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
"league/flysystem-webdav": "Allows you to use WebDAV storage",
"league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
"league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
"league/flysystem-dropbox": "Allows you to use Dropbox storage",
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
"srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications",
"league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
"ext-ftp": "Allows you to use FTP server storage",
"ext-openssl": "Allows you to use FTPS server storage",
"league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter"
},

View File

@@ -7,7 +7,7 @@ use League\Flysystem\AdapterInterface;
abstract class AbstractAdapter implements AdapterInterface
{
/**
* @var string path prefix
* @var string|null path prefix
*/
protected $pathPrefix;
@@ -21,23 +21,24 @@ abstract class AbstractAdapter implements AdapterInterface
*
* @param string $prefix
*
* @return self
* @return void
*/
public function setPathPrefix($prefix)
{
$is_empty = empty($prefix);
$prefix = (string) $prefix;
if ( ! $is_empty) {
$prefix = rtrim($prefix, $this->pathSeparator) . $this->pathSeparator;
if ($prefix === '') {
$this->pathPrefix = null;
return;
}
$this->pathPrefix = $is_empty ? null : $prefix;
$this->pathPrefix = rtrim($prefix, '\\/') . $this->pathSeparator;
}
/**
* Get the path prefix.
*
* @return string path prefix
* @return string|null path prefix or null if pathPrefix is empty
*/
public function getPathPrefix()
{
@@ -53,17 +54,7 @@ abstract class AbstractAdapter implements AdapterInterface
*/
public function applyPathPrefix($path)
{
$path = ltrim($path, '\\/');
if (strlen($path) === 0) {
return $this->getPathPrefix() ?: '';
}
if ($prefix = $this->getPathPrefix()) {
$path = $prefix . $path;
}
return $path;
return $this->getPathPrefix() . ltrim($path, '\\/');
}
/**
@@ -75,12 +66,6 @@ abstract class AbstractAdapter implements AdapterInterface
*/
public function removePathPrefix($path)
{
$pathPrefix = $this->getPathPrefix();
if ($pathPrefix === null) {
return $path;
}
return substr($path, strlen($pathPrefix));
return substr($path, strlen($this->getPathPrefix()));
}
}

View File

@@ -6,6 +6,7 @@ use DateTime;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
use League\Flysystem\NotSupportedException;
use League\Flysystem\SafeStorage;
use RuntimeException;
abstract class AbstractFtpAdapter extends AbstractAdapter
@@ -25,16 +26,6 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
protected $port = 21;
/**
* @var string|null
*/
protected $username;
/**
* @var string|null
*/
protected $password;
/**
* @var bool
*/
@@ -85,6 +76,11 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
protected $alternativeRecursion = false;
/**
* @var SafeStorage
*/
protected $safeStorage;
/**
* Constructor.
*
@@ -92,6 +88,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function __construct(array $config)
{
$this->safeStorage = new SafeStorage();
$this->setConfig($config);
}
@@ -226,7 +223,9 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function getUsername()
{
return empty($this->username) ? 'anonymous' : $this->username;
$username = $this->safeStorage->retrieveSafely('username');
return $username !== null ? $username : 'anonymous';
}
/**
@@ -238,7 +237,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function setUsername($username)
{
$this->username = $username;
$this->safeStorage->storeSafely('username', $username);
return $this;
}
@@ -250,7 +249,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function getPassword()
{
return $this->password;
return $this->safeStorage->retrieveSafely('password');
}
/**
@@ -262,7 +261,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function setPassword($password)
{
$this->password = $password;
$this->safeStorage->storeSafely('password', $password);
return $this;
}
@@ -341,7 +340,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
while ($item = array_shift($listing)) {
if (preg_match('#^.*:$#', $item)) {
$base = trim($item, ':');
$base = preg_replace('~^\./*|:$~', '', $item);
continue;
}
@@ -410,7 +409,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
list($permissions, /* $number */, /* $owner */, /* $group */, $size, /* $month */, /* $day */, /* $time*/, $name) = explode(' ', $item, 9);
$type = $this->detectType($permissions);
$path = empty($base) ? $name : $base . $this->separator . $name;
$path = $base === '' ? $name : $base . $this->separator . $name;
if ($type === 'dir') {
return compact('type', 'path');
@@ -440,7 +439,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
}
list($date, $time, $size, $name) = explode(' ', $item, 4);
$path = empty($base) ? $name : $base . $this->separator . $name;
$path = $base === '' ? $name : $base . $this->separator . $name;
// Check for the correct date/time format
$format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';
@@ -508,8 +507,8 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
return array_sum(str_split($part));
};
// get the sum of the groups
return array_sum(array_map($mapper, $parts));
// converts to decimal number
return octdec(implode('', array_map($mapper, $parts)));
}
/**
@@ -522,11 +521,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
public function removeDotDirectories(array $list)
{
$filter = function ($line) {
if ( ! empty($line) && ! preg_match('#.* \.(\.)?$|^total#', $line)) {
return true;
}
return false;
return $line !== '' && ! preg_match('#.* \.(\.)?$|^total#', $line);
};
return array_filter($list, $filter);
@@ -563,7 +558,9 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function ensureDirectory($dirname)
{
if ( ! empty($dirname) && ! $this->has($dirname)) {
$dirname = (string) $dirname;
if ($dirname !== '' && ! $this->has($dirname)) {
$this->createDir($dirname, new Config());
}
}
@@ -573,7 +570,10 @@ abstract class AbstractFtpAdapter extends AbstractAdapter
*/
public function getConnection()
{
if ( ! $this->isConnected()) {
$tries = 0;
while ( ! $this->isConnected() && $tries < 3) {
$tries++;
$this->disconnect();
$this->connect();
}

View File

@@ -0,0 +1,10 @@
<?php
namespace League\Flysystem\Adapter;
/**
* Adapters that implement this interface let the Filesystem know that it files can be overwritten using the write
* functions and don't need the update function to be called. This can help improve performance when asserts are disabled.
*/
interface CanOverwriteFiles {}

View File

@@ -29,6 +29,11 @@ class Ftp extends AbstractFtpAdapter
*/
protected $recurseManually = false;
/**
* @var bool
*/
protected $utf8 = false;
/**
* @var array
*/
@@ -47,8 +52,14 @@ class Ftp extends AbstractFtpAdapter
'systemType',
'ignorePassiveAddress',
'recurseManually',
'utf8',
];
/**
* @var bool
*/
protected $isPureFtpd;
/**
* Set the transfer mode.
*
@@ -103,6 +114,14 @@ class Ftp extends AbstractFtpAdapter
$this->recurseManually = $recurseManually;
}
/**
* @param bool $utf8
*/
public function setUtf8($utf8)
{
$this->utf8 = (bool) $utf8;
}
/**
* Connect to the FTP server.
*/
@@ -119,8 +138,25 @@ class Ftp extends AbstractFtpAdapter
}
$this->login();
$this->setUtf8Mode();
$this->setConnectionPassiveMode();
$this->setConnectionRoot();
$this->isPureFtpd = $this->isPureFtpdServer();
}
/**
* Set the connection to UTF-8 mode.
*/
protected function setUtf8Mode()
{
if ($this->utf8) {
$response = ftp_raw($this->connection, "OPTS UTF8 ON");
if (substr($response[0], 0, 3) !== '200') {
throw new RuntimeException(
'Could not set UTF-8 mode for connection: ' . $this->getHost() . '::' . $this->getPort()
);
}
}
}
/**
@@ -149,7 +185,7 @@ class Ftp extends AbstractFtpAdapter
$root = $this->getRoot();
$connection = $this->connection;
if (empty($root) === false && ! ftp_chdir($connection, $root)) {
if ($root && ! ftp_chdir($connection, $root)) {
throw new RuntimeException('Root is invalid or does not exist: ' . $this->getRoot());
}
@@ -167,11 +203,12 @@ class Ftp extends AbstractFtpAdapter
*/
protected function login()
{
set_error_handler(
function () {
}
set_error_handler(function () {});
$isLoggedIn = ftp_login(
$this->connection,
$this->getUsername(),
$this->getPassword()
);
$isLoggedIn = ftp_login($this->connection, $this->getUsername(), $this->getPassword());
restore_error_handler();
if ( ! $isLoggedIn) {
@@ -188,7 +225,7 @@ class Ftp extends AbstractFtpAdapter
*/
public function disconnect()
{
if ($this->isConnected()) {
if (is_resource($this->connection)) {
ftp_close($this->connection);
}
@@ -231,7 +268,9 @@ class Ftp extends AbstractFtpAdapter
$this->setVisibility($path, $visibility);
}
return compact('path', 'visibility');
$type = 'file';
return compact('type', 'path', 'visibility');
}
/**
@@ -272,14 +311,14 @@ class Ftp extends AbstractFtpAdapter
public function deleteDir($dirname)
{
$connection = $this->getConnection();
$contents = array_reverse($this->listDirectoryContents($dirname));
$contents = array_reverse($this->listDirectoryContents($dirname, false));
foreach ($contents as $object) {
if ($object['type'] === 'file') {
if ( ! ftp_delete($connection, $object['path'])) {
return false;
}
} elseif ( ! ftp_rmdir($connection, $object['path'])) {
} elseif ( ! $this->deleteDir($object['path'])) {
return false;
}
}
@@ -307,7 +346,7 @@ class Ftp extends AbstractFtpAdapter
$this->setConnectionRoot();
return ['path' => $dirname];
return ['type' => 'dir', 'path' => $dirname];
}
/**
@@ -329,7 +368,7 @@ class Ftp extends AbstractFtpAdapter
}
}
if (in_array($directory, $listing)) {
if (in_array($directory, $listing, true)) {
return true;
}
@@ -353,9 +392,9 @@ class Ftp extends AbstractFtpAdapter
return ['type' => 'dir', 'path' => $path];
}
$listing = ftp_rawlist($connection, '-A ' . str_replace('*', '\\*', $path));
$listing = $this->ftpRawlist('-A', str_replace('*', '\\*', $path));
if (empty($listing)) {
if (empty($listing) || in_array('total 0', $listing, true)) {
return false;
}
@@ -391,7 +430,7 @@ class Ftp extends AbstractFtpAdapter
{
$timestamp = ftp_mdtm($this->getConnection(), $path);
return ($timestamp !== -1) ? ['timestamp' => $timestamp] : false;
return ($timestamp !== -1) ? ['path' => $path, 'timestamp' => $timestamp] : false;
}
/**
@@ -425,7 +464,7 @@ class Ftp extends AbstractFtpAdapter
return false;
}
return compact('stream');
return ['type' => 'file', 'path' => $path, 'stream' => $stream];
}
/**
@@ -439,7 +478,7 @@ class Ftp extends AbstractFtpAdapter
return false;
}
return compact('visibility');
return compact('path', 'visibility');
}
/**
@@ -456,7 +495,7 @@ class Ftp extends AbstractFtpAdapter
}
$options = $recursive ? '-alnR' : '-aln';
$listing = ftp_rawlist($this->getConnection(), $options . ' ' . $directory);
$listing = $this->ftpRawlist($options, $directory);
return $listing ? $this->normalizeListing($listing, $directory) : [];
}
@@ -468,14 +507,13 @@ class Ftp extends AbstractFtpAdapter
*/
protected function listDirectoryContentsRecursive($directory)
{
$listing = $this->normalizeListing(ftp_rawlist($this->getConnection(), '-aln' . ' ' . $directory) ?: []);
$listing = $this->normalizeListing($this->ftpRawlist('-aln', $directory) ?: [], $directory);
$output = [];
foreach ($listing as $directory) {
$output[] = $directory;
if ($directory['type'] !== 'dir') continue;
$output = array_merge($output, $this->listDirectoryContentsRecursive($directory['path']));
foreach ($listing as $item) {
$output[] = $item;
if ($item['type'] !== 'dir') continue;
$output = array_merge($output, $this->listDirectoryContentsRecursive($item['path']));
}
return $output;
@@ -490,11 +528,8 @@ class Ftp extends AbstractFtpAdapter
public function isConnected()
{
try {
return is_resource($this->connection) && ftp_rawlist($this->connection, '/') !== false;
return is_resource($this->connection) && ftp_rawlist($this->connection, $this->getRoot()) !== false;
} catch (ErrorException $e) {
fclose($this->connection);
$this->connection = null;
if (strpos($e->getMessage(), 'ftp_rawlist') === false) {
throw $e;
}
@@ -502,4 +537,32 @@ class Ftp extends AbstractFtpAdapter
return false;
}
}
/**
* @return bool
*/
protected function isPureFtpdServer()
{
$response = ftp_raw($this->connection, 'HELP');
return stripos(implode(' ', $response), 'Pure-FTPd') !== false;
}
/**
* The ftp_rawlist function with optional escaping.
*
* @param string $options
* @param string $path
*
* @return array
*/
protected function ftpRawlist($options, $path)
{
$connection = $this->getConnection();
if ($this->isPureFtpd) {
$path = str_replace(' ', '\ ', $path);
}
return ftp_rawlist($connection, $options . ' ' . $path);
}
}

View File

@@ -9,7 +9,11 @@ class Ftpd extends Ftp
*/
public function getMetadata($path)
{
if (empty($path) || ! ($object = ftp_raw($this->getConnection(), 'STAT ' . $path)) || count($object) < 3) {
if ($path === '') {
return ['type' => 'dir', 'path' => ''];
}
if ( ! ($object = ftp_raw($this->getConnection(), 'STAT ' . $path)) || count($object) < 3) {
return false;
}

View File

@@ -68,18 +68,20 @@ class Local extends AbstractAdapter
* @param int $writeFlags
* @param int $linkHandling
* @param array $permissions
*
* @throws LogicException
*/
public function __construct($root, $writeFlags = LOCK_EX, $linkHandling = self::DISALLOW_LINKS, array $permissions = [])
{
$root = is_link($root) ? realpath($root) : $root;
$this->permissionMap = array_replace_recursive(static::$permissions, $permissions);
$realRoot = $this->ensureDirectory($root);
$this->ensureDirectory($root);
if ( ! is_dir($realRoot) || ! is_readable($realRoot)) {
if ( ! is_dir($root) || ! is_readable($root)) {
throw new LogicException('The root path ' . $root . ' is not readable.');
}
$this->setPathPrefix($realRoot);
$this->setPathPrefix($root);
$this->writeFlags = $writeFlags;
$this->linkHandling = $linkHandling;
}
@@ -89,7 +91,7 @@ class Local extends AbstractAdapter
*
* @param string $root root directory path
*
* @return string real path to root
* @return void
*
* @throws Exception in case the root directory can not be created
*/
@@ -104,8 +106,6 @@ class Local extends AbstractAdapter
throw new Exception(sprintf('Impossible to create the root directory "%s".', $root));
}
}
return realpath($root);
}
/**
@@ -160,11 +160,16 @@ class Local extends AbstractAdapter
return false;
}
$type = 'file';
$result = compact('type', 'path');
if ($visibility = $config->get('visibility')) {
$this->setVisibility($path, $visibility);
$result['visibility'] = $visibility;
}
return compact('path', 'visibility');
return $result;
}
/**
@@ -175,7 +180,7 @@ class Local extends AbstractAdapter
$location = $this->applyPathPrefix($path);
$stream = fopen($location, 'rb');
return compact('stream', 'path');
return ['type' => 'file', 'path' => $path, 'stream' => $stream];
}
/**
@@ -192,14 +197,21 @@ class Local extends AbstractAdapter
public function update($path, $contents, Config $config)
{
$location = $this->applyPathPrefix($path);
$mimetype = Util::guessMimeType($path, $contents);
$size = file_put_contents($location, $contents, $this->writeFlags);
if ($size === false) {
return false;
}
return compact('path', 'size', 'contents', 'mimetype');
$type = 'file';
$result = compact('type', 'path', 'size', 'contents');
if ($mimetype = Util::guessMimeType($path, $contents)) {
$result['mimetype'] = $mimetype;
}
return $result;
}
/**
@@ -214,7 +226,7 @@ class Local extends AbstractAdapter
return false;
}
return compact('contents', 'path');
return ['type' => 'file', 'path' => $path, 'contents' => $contents];
}
/**
@@ -258,7 +270,7 @@ class Local extends AbstractAdapter
public function listContents($directory = '', $recursive = false)
{
$result = [];
$location = $this->applyPathPrefix($directory) . $this->pathSeparator;
$location = $this->applyPathPrefix($directory);
if ( ! is_dir($location)) {
return [];
@@ -311,7 +323,7 @@ class Local extends AbstractAdapter
$mimetype = Util\MimeType::detectByFilename($location);
}
return ['mimetype' => $mimetype];
return ['path' => $path, 'type' => 'file', 'mimetype' => $mimetype];
}
/**
@@ -332,7 +344,7 @@ class Local extends AbstractAdapter
$permissions = octdec(substr(sprintf('%o', fileperms($location)), -4));
$visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
return compact('visibility');
return compact('path', 'visibility');
}
/**
@@ -348,7 +360,7 @@ class Local extends AbstractAdapter
return false;
}
return compact('visibility');
return compact('path', 'visibility');
}
/**
@@ -415,7 +427,9 @@ class Local extends AbstractAdapter
*
* @param SplFileInfo $file
*
* @return array
* @return array|void
*
* @throws NotSupportedException
*/
protected function normalizeFileInfo(SplFileInfo $file)
{
@@ -490,16 +504,6 @@ class Local extends AbstractAdapter
return $normalized;
}
/**
* @inheritdoc
*/
public function applyPathPrefix($path)
{
$prefixedPath = parent::applyPathPrefix($path);
return str_replace('/', DIRECTORY_SEPARATOR, $prefixedPath);
}
/**
* @param SplFileInfo $file
*

View File

@@ -34,12 +34,16 @@ trait StreamedCopyTrait
// Required abstract method
/**
* @param string $path
* @param string $path
* @return resource
*/
abstract public function readStream($path);
/**
* @param string $path
* @param string $path
* @param resource $resource
* @param Config $config
* @return resource
*/
abstract public function writeStream($path, $resource, Config $config);
}

View File

@@ -2,6 +2,9 @@
namespace League\Flysystem;
/**
* @deprecated
*/
class Directory extends Handler
{
/**

View File

@@ -2,6 +2,9 @@
namespace League\Flysystem;
/**
* @deprecated
*/
class File extends Handler
{
/**
@@ -17,7 +20,7 @@ class File extends Handler
/**
* Read the file.
*
* @return string file contents
* @return string|false file contents
*/
public function read()
{
@@ -27,7 +30,7 @@ class File extends Handler
/**
* Read the file as a stream.
*
* @return resource file stream
* @return resource|false file stream
*/
public function readStream()
{
@@ -143,7 +146,7 @@ class File extends Handler
/**
* Get the file's timestamp.
*
* @return int unix timestamp
* @return string|false The timestamp or false on failure.
*/
public function getTimestamp()
{
@@ -153,7 +156,7 @@ class File extends Handler
/**
* Get the file's mimetype.
*
* @return string mimetime
* @return string|false The file mime-type or false on failure.
*/
public function getMimetype()
{
@@ -163,7 +166,7 @@ class File extends Handler
/**
* Get the file's visibility.
*
* @return string visibility
* @return string|false The visibility (public|private) or false on failure.
*/
public function getVisibility()
{
@@ -173,7 +176,7 @@ class File extends Handler
/**
* Get the file's metadata.
*
* @return array
* @return array|false The file metadata or false on failure.
*/
public function getMetadata()
{
@@ -183,7 +186,7 @@ class File extends Handler
/**
* Get the file size.
*
* @return int file size
* @return int|false The file size or false on failure.
*/
public function getSize()
{

View File

@@ -3,6 +3,7 @@
namespace League\Flysystem;
use InvalidArgumentException;
use League\Flysystem\Adapter\CanOverwriteFiles;
use League\Flysystem\Plugin\PluggableTrait;
use League\Flysystem\Util\ContentListingFormatter;
@@ -94,7 +95,7 @@ class Filesystem implements FilesystemInterface
$path = Util::normalizePath($path);
$config = $this->prepareConfig($config);
if ($this->has($path)) {
if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {
return (bool) $this->getAdapter()->update($path, $contents, $config);
}
@@ -114,7 +115,7 @@ class Filesystem implements FilesystemInterface
$config = $this->prepareConfig($config);
Util::rewindStream($resource);
if ($this->has($path)) {
if ( ! $this->getAdapter() instanceof CanOverwriteFiles &&$this->has($path)) {
return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
}
@@ -280,7 +281,7 @@ class Filesystem implements FilesystemInterface
$path = Util::normalizePath($path);
$this->assertPresent($path);
if ( ! $object = $this->getAdapter()->getMimetype($path)) {
if (( ! $object = $this->getAdapter()->getMimetype($path)) || ! array_key_exists('mimetype', $object)) {
return false;
}
@@ -295,7 +296,7 @@ class Filesystem implements FilesystemInterface
$path = Util::normalizePath($path);
$this->assertPresent($path);
if ( ! $object = $this->getAdapter()->getTimestamp($path)) {
if (( ! $object = $this->getAdapter()->getTimestamp($path)) || ! array_key_exists('timestamp', $object)) {
return false;
}
@@ -310,7 +311,7 @@ class Filesystem implements FilesystemInterface
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (($object = $this->getAdapter()->getVisibility($path)) === false) {
if (( ! $object = $this->getAdapter()->getVisibility($path)) || ! array_key_exists('visibility', $object)) {
return false;
}
@@ -323,8 +324,9 @@ class Filesystem implements FilesystemInterface
public function getSize($path)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
if (($object = $this->getAdapter()->getSize($path)) === false || ! isset($object['size'])) {
if (( ! $object = $this->getAdapter()->getSize($path)) || ! array_key_exists('size', $object)) {
return false;
}
@@ -337,6 +339,7 @@ class Filesystem implements FilesystemInterface
public function setVisibility($path, $visibility)
{
$path = Util::normalizePath($path);
$this->assertPresent($path);
return (bool) $this->getAdapter()->setVisibility($path, $visibility);
}

View File

@@ -2,6 +2,8 @@
namespace League\Flysystem;
use InvalidArgumentException;
interface FilesystemInterface
{
/**
@@ -61,6 +63,8 @@ interface FilesystemInterface
*
* @param string $path The path to the file.
*
* @throws FileNotFoundException
*
* @return int|false The file size or false on failure.
*/
public function getSize($path);
@@ -216,6 +220,8 @@ interface FilesystemInterface
* @param string $path The path to the file.
* @param string $visibility One of 'public' or 'private'.
*
* @throws FileNotFoundException
*
* @return bool True on success, false on failure.
*/
public function setVisibility($path, $visibility);
@@ -258,6 +264,8 @@ interface FilesystemInterface
/**
* Get a file/directory handler.
*
* @deprecated
*
* @param string $path The path to the file.
* @param Handler $handler An optional existing handler to populate.
*

View File

@@ -0,0 +1,12 @@
<?php
namespace League\Flysystem;
use LogicException;
/**
* Thrown when the MountManager cannot find a filesystem.
*/
class FilesystemNotFoundException extends LogicException
{
}

View File

@@ -4,6 +4,9 @@ namespace League\Flysystem;
use BadMethodCallException;
/**
* @deprecated
*/
abstract class Handler
{
/**

View File

@@ -3,9 +3,9 @@
namespace League\Flysystem;
use InvalidArgumentException;
use League\Flysystem\FilesystemNotFoundException;
use League\Flysystem\Plugin\PluggableTrait;
use League\Flysystem\Plugin\PluginNotFoundException;
use LogicException;
/**
* Class MountManager.
@@ -32,7 +32,7 @@ use LogicException;
* @method array listPaths($directory = '', $recursive = false)
* @method array getWithMetadata($path, array $metadata)
* @method string|false getMimetype($path)
* @method string|false getTimestamp($path)
* @method int|false getTimestamp($path)
* @method string|false getVisibility($path)
* @method int|false getSize($path);
* @method bool setVisibility($path, $visibility)
@@ -48,14 +48,16 @@ class MountManager
use PluggableTrait;
/**
* @var array
* @var FilesystemInterface[]
*/
protected $filesystems = [];
/**
* Constructor.
*
* @param array $filesystems
* @param FilesystemInterface[] $filesystems [:prefix => Filesystem,]
*
* @throws InvalidArgumentException
*/
public function __construct(array $filesystems = [])
{
@@ -65,7 +67,9 @@ class MountManager
/**
* Mount filesystems.
*
* @param array $filesystems [:prefix => Filesystem,]
* @param FilesystemInterface[] $filesystems [:prefix => Filesystem,]
*
* @throws InvalidArgumentException
*
* @return $this
*/
@@ -84,6 +88,8 @@ class MountManager
* @param string $prefix
* @param FilesystemInterface $filesystem
*
* @throws InvalidArgumentException
*
* @return $this
*/
public function mountFilesystem($prefix, FilesystemInterface $filesystem)
@@ -102,14 +108,14 @@ class MountManager
*
* @param string $prefix
*
* @throws LogicException
* @throws FilesystemNotFoundException
*
* @return FilesystemInterface
*/
public function getFilesystem($prefix)
{
if ( ! isset($this->filesystems[$prefix])) {
throw new LogicException('No filesystem mounted with prefix ' . $prefix);
throw new FilesystemNotFoundException('No filesystem mounted with prefix ' . $prefix);
}
return $this->filesystems[$prefix];
@@ -120,12 +126,14 @@ class MountManager
*
* @param array $arguments
*
* @throws InvalidArgumentException
*
* @return array [:prefix, :arguments]
*/
public function filterPrefix(array $arguments)
{
if (empty($arguments)) {
throw new LogicException('At least one argument needed');
throw new InvalidArgumentException('At least one argument needed');
}
$path = array_shift($arguments);
@@ -134,11 +142,7 @@ class MountManager
throw new InvalidArgumentException('First argument should be a string');
}
if ( ! preg_match('#^.+\:\/\/.*#', $path)) {
throw new InvalidArgumentException('No prefix detected in path: ' . $path);
}
list($prefix, $path) = explode('://', $path, 2);
list($prefix, $path) = $this->getPrefixAndPath($path);
array_unshift($arguments, $path);
return [$prefix, $arguments];
@@ -148,13 +152,15 @@ class MountManager
* @param string $directory
* @param bool $recursive
*
* @throws InvalidArgumentException
* @throws FilesystemNotFoundException
*
* @return array
*/
public function listContents($directory = '', $recursive = false)
{
list($prefix, $arguments) = $this->filterPrefix([$directory]);
list($prefix, $directory) = $this->getPrefixAndPath($directory);
$filesystem = $this->getFilesystem($prefix);
$directory = array_shift($arguments);
$result = $filesystem->listContents($directory, $recursive);
foreach ($result as &$file) {
@@ -170,6 +176,9 @@ class MountManager
* @param string $method
* @param array $arguments
*
* @throws InvalidArgumentException
* @throws FilesystemNotFoundException
*
* @return mixed
*/
public function __call($method, $arguments)
@@ -180,27 +189,28 @@ class MountManager
}
/**
* @param $from
* @param $to
* @param array $config
* @param string $from
* @param string $to
* @param array $config
*
* @throws InvalidArgumentException
* @throws FilesystemNotFoundException
*
* @return bool
*/
public function copy($from, $to, array $config = [])
{
list($prefixFrom, $arguments) = $this->filterPrefix([$from]);
list($prefixFrom, $from) = $this->getPrefixAndPath($from);
$fsFrom = $this->getFilesystem($prefixFrom);
$buffer = call_user_func_array([$fsFrom, 'readStream'], $arguments);
$buffer = $this->getFilesystem($prefixFrom)->readStream($from);
if ($buffer === false) {
return false;
}
list($prefixTo, $arguments) = $this->filterPrefix([$to]);
list($prefixTo, $to) = $this->getPrefixAndPath($to);
$fsTo = $this->getFilesystem($prefixTo);
$result = call_user_func_array([$fsTo, 'writeStream'], array_merge($arguments, [$buffer, $config]));
$result = $this->getFilesystem($prefixTo)->writeStream($to, $buffer, $config);
if (is_resource($buffer)) {
fclose($buffer);
@@ -215,11 +225,15 @@ class MountManager
* @param array $keys
* @param string $directory
* @param bool $recursive
*
* @throws InvalidArgumentException
* @throws FilesystemNotFoundException
*
* @return array
*/
public function listWith(array $keys = [], $directory = '', $recursive = false)
{
list($prefix, $arguments) = $this->filterPrefix([$directory]);
$directory = $arguments[0];
list($prefix, $directory) = $this->getPrefixAndPath($directory);
$arguments = [$keys, $directory, $recursive];
return $this->invokePluginOnFilesystem('listWith', $arguments, $prefix);
@@ -228,14 +242,31 @@ class MountManager
/**
* Move a file.
*
* @param $from
* @param $to
* @param array $config
* @param string $from
* @param string $to
* @param array $config
*
* @throws InvalidArgumentException
* @throws FilesystemNotFoundException
*
* @return bool
*/
public function move($from, $to, array $config = [])
{
list($prefixFrom, $pathFrom) = $this->getPrefixAndPath($from);
list($prefixTo, $pathTo) = $this->getPrefixAndPath($to);
if ($prefixFrom === $prefixTo) {
$filesystem = $this->getFilesystem($prefixFrom);
$renamed = $filesystem->rename($pathFrom, $pathTo);
if ($renamed && isset($config['visibility'])) {
return $filesystem->setVisibility($pathTo, $config['visibility']);
}
return $renamed;
}
$copied = $this->copy($from, $to, $config);
if ($copied) {
@@ -248,9 +279,11 @@ class MountManager
/**
* Invoke a plugin on a filesystem mounted on a given prefix.
*
* @param $method
* @param $arguments
* @param $prefix
* @param string $method
* @param array $arguments
* @param string $prefix
*
* @throws FilesystemNotFoundException
*
* @return mixed
*/
@@ -268,4 +301,20 @@ class MountManager
return call_user_func_array($callback, $arguments);
}
/**
* @param string $path
*
* @throws InvalidArgumentException
*
* @return string[] [:prefix, :path]
*/
protected function getPrefixAndPath($path)
{
if (strpos($path, '://') < 1) {
throw new InvalidArgumentException('No prefix detected in path: ' . $path);
}
return explode('://', $path, 2);
}
}

View File

@@ -17,7 +17,7 @@ class EmptyDir extends AbstractPlugin
/**
* Empty a directory's contents.
*
* @param $dirname
* @param string $dirname
*/
public function handle($dirname)
{

View File

@@ -2,6 +2,7 @@
namespace League\Flysystem\Plugin;
use League\Flysystem\FileExistsException;
use League\Flysystem\FileNotFoundException;
class ForcedCopy extends AbstractPlugin
@@ -20,6 +21,7 @@ class ForcedCopy extends AbstractPlugin
* @param string $path Path to the existing file.
* @param string $newpath The new path of the file.
*
* @throws FileExistsException
* @throws FileNotFoundException Thrown if $path does not exist.
*
* @return bool True on success, false on failure.

View File

@@ -2,6 +2,7 @@
namespace League\Flysystem\Plugin;
use League\Flysystem\FileExistsException;
use League\Flysystem\FileNotFoundException;
class ForcedRename extends AbstractPlugin
@@ -21,6 +22,7 @@ class ForcedRename extends AbstractPlugin
* @param string $newpath The new path of the file.
*
* @throws FileNotFoundException Thrown if $path does not exist.
* @throws FileExistsException
*
* @return bool True on success, false on failure.
*/

View File

@@ -3,6 +3,7 @@
namespace League\Flysystem\Plugin;
use InvalidArgumentException;
use League\Flysystem\FileNotFoundException;
class GetWithMetadata extends AbstractPlugin
{
@@ -23,8 +24,9 @@ class GetWithMetadata extends AbstractPlugin
* @param array $metadata metadata keys
*
* @throws InvalidArgumentException
* @throws FileNotFoundException
*
* @return array metadata
* @return array|false metadata
*/
public function handle($path, array $metadata)
{

View File

@@ -40,8 +40,8 @@ class ListWith extends AbstractPlugin
/**
* Get a meta-data value by key name.
*
* @param array $object
* @param $key
* @param array $object
* @param string $key
*
* @return array
*/

View File

@@ -19,10 +19,16 @@ trait PluggableTrait
*
* @param PluginInterface $plugin
*
* @throws LogicException
*
* @return $this
*/
public function addPlugin(PluginInterface $plugin)
{
if ( ! method_exists($plugin, 'handle')) {
throw new LogicException(get_class($plugin) . ' does not have a handle method.');
}
$this->plugins[$plugin->getMethod()] = $plugin;
return $this;
@@ -33,9 +39,9 @@ trait PluggableTrait
*
* @param string $method
*
* @throws LogicException
* @throws PluginNotFoundException
*
* @return PluginInterface $plugin
* @return PluginInterface
*/
protected function findPlugin($method)
{
@@ -43,18 +49,17 @@ trait PluggableTrait
throw new PluginNotFoundException('Plugin not found for method: ' . $method);
}
if ( ! method_exists($this->plugins[$method], 'handle')) {
throw new LogicException(get_class($this->plugins[$method]) . ' does not have a handle method.');
}
return $this->plugins[$method];
}
/**
* Invoke a plugin by method name.
*
* @param string $method
* @param array $arguments
* @param string $method
* @param array $arguments
* @param FilesystemInterface $filesystem
*
* @throws PluginNotFoundException
*
* @return mixed
*/

View File

@@ -51,7 +51,7 @@ interface ReadInterface
public function getMetadata($path);
/**
* Get all the meta data of a file or directory.
* Get the size of a file.
*
* @param string $path
*
@@ -69,7 +69,7 @@ interface ReadInterface
public function getMimetype($path);
/**
* Get the timestamp of a file.
* Get the last modified time of a file as a timestamp.
*
* @param string $path
*

View File

@@ -0,0 +1,39 @@
<?php
namespace League\Flysystem;
final class SafeStorage
{
/**
* @var string
*/
private $hash;
/**
* @var array
*/
protected static $safeStorage = [];
public function __construct()
{
$this->hash = spl_object_hash($this);
static::$safeStorage[$this->hash] = [];
}
public function storeSafely($key, $value)
{
static::$safeStorage[$this->hash][$key] = $value;
}
public function retrieveSafely($key)
{
if (array_key_exists($key, static::$safeStorage[$this->hash])) {
return static::$safeStorage[$this->hash][$key];
}
}
public function __destruct()
{
unset(static::$safeStorage[$this->hash]);
}
}

View File

@@ -16,11 +16,17 @@ class Util
*/
public static function pathinfo($path)
{
$pathinfo = pathinfo($path) + compact('path');
$pathinfo['dirname'] = array_key_exists('dirname', $pathinfo)
? static::normalizeDirname($pathinfo['dirname']) : '';
$pathinfo = compact('path');
return $pathinfo;
if ('' !== $dirname = dirname($path)) {
$pathinfo['dirname'] = static::normalizeDirname($dirname);
}
$pathinfo['basename'] = static::basename($path);
$pathinfo += pathinfo($pathinfo['basename']);
return $pathinfo + ['dirname' => ''];
}
/**
@@ -81,20 +87,7 @@ class Util
*/
public static function normalizePath($path)
{
// Remove any kind of funky unicode whitespace
$normalized = preg_replace('#\p{C}+|^\./#u', '', $path);
$normalized = static::normalizeRelativePath($normalized);
if (preg_match('#/\.{2}|^\.{2}/|^\.{2}$#', $normalized)) {
throw new LogicException(
'Path is outside of the defined root, path: [' . $path . '], resolved: [' . $normalized . ']'
);
}
$normalized = preg_replace('#\\\{2,}#', '\\', trim($normalized, '\\'));
$normalized = preg_replace('#/{2,}#', '/', trim($normalized, '/'));
return $normalized;
return static::normalizeRelativePath($path);
}
/**
@@ -102,18 +95,53 @@ class Util
*
* @param string $path
*
* @throws LogicException
*
* @return string
*/
public static function normalizeRelativePath($path)
{
// Path remove self referring paths ("/./").
$path = preg_replace('#/\.(?=/)|^\./|(/|^)\./?$#', '', $path);
$path = str_replace('\\', '/', $path);
$path = static::removeFunkyWhiteSpace($path);
// Regex for resolving relative paths
$regex = '#/*[^/\.]+/\.\.#Uu';
$parts = [];
while (preg_match($regex, $path)) {
$path = preg_replace($regex, '', $path);
foreach (explode('/', $path) as $part) {
switch ($part) {
case '':
case '.':
break;
case '..':
if (empty($parts)) {
throw new LogicException(
'Path is outside of the defined root, path: [' . $path . ']'
);
}
array_pop($parts);
break;
default:
$parts[] = $part;
break;
}
}
return implode('/', $parts);
}
/**
* Removes unprintable characters and invalid unicode characters.
*
* @param string $path
*
* @return string $path
*/
protected static function removeFunkyWhiteSpace($path) {
// We do this check in a loop, since removing invalid unicode characters
// can lead to new characters being created.
while (preg_match('#\p{C}+|^\./#u', $path)) {
$path = preg_replace('#\p{C}+|^\./#u', '', $path);
}
return $path;
@@ -176,11 +204,7 @@ class Util
$listedDirectories = [];
foreach ($listing as $object) {
list($directories, $listedDirectories) = static::emulateObjectDirectories(
$object,
$directories,
$listedDirectories
);
list($directories, $listedDirectories) = static::emulateObjectDirectories($object, $directories, $listedDirectories);
}
$directories = array_diff(array_unique($directories), array_unique($listedDirectories));
@@ -285,4 +309,40 @@ class Util
return [$directories, $listedDirectories];
}
/**
* Returns the trailing name component of the path.
*
* @param string $path
*
* @return string
*/
private static function basename($path)
{
$separators = DIRECTORY_SEPARATOR === '/' ? '/' : '\/';
$path = rtrim($path, $separators);
$basename = preg_replace('#.*?([^' . preg_quote($separators, '#') . ']+$)#', '$1', $path);
if (DIRECTORY_SEPARATOR === '/') {
return $basename;
}
// @codeCoverageIgnoreStart
// Extra Windows path munging. This is tested via AppVeyor, but code
// coverage is not reported.
// Handle relative paths with drive letters. c:file.txt.
while (preg_match('#^[a-zA-Z]{1}:[^\\\/]#', $basename)) {
$basename = substr($basename, 2);
}
// Remove colon for standalone drive letter names.
if (preg_match('#^[a-zA-Z]{1}:$#', $basename)) {
$basename = rtrim($basename, ':');
}
return $basename;
// @codeCoverageIgnoreEnd
}
}

View File

@@ -75,7 +75,7 @@ class ContentListingFormatter
/**
* Check if the entry resides within the parent directory.
*
* @param $entry
* @param array $entry
*
* @return bool
*/
@@ -91,7 +91,7 @@ class ContentListingFormatter
/**
* Check if the entry is a direct child of the directory.
*
* @param $entry
* @param array $entry
*
* @return bool
*/
@@ -107,12 +107,9 @@ class ContentListingFormatter
*/
private function sortListing(array $listing)
{
usort(
$listing,
function ($a, $b) {
return strcasecmp($a['path'], $b['path']);
}
);
usort($listing, function ($a, $b) {
return strcasecmp($a['path'], $b['path']);
});
return $listing;
}

View File

@@ -2,7 +2,8 @@
namespace League\Flysystem\Util;
use Finfo;
use finfo;
use ErrorException;
/**
* @internal
@@ -18,15 +19,18 @@ class MimeType
*/
public static function detectByContent($content)
{
if ( ! class_exists('Finfo') || ! is_string($content)) {
return;
if ( ! class_exists('finfo') || ! is_string($content)) {
return null;
}
try {
$finfo = new finfo(FILEINFO_MIME_TYPE);
$finfo = new Finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->buffer($content);
return $mimeType ?: null;
}
return $finfo->buffer($content) ?: null;
// @codeCoverageIgnoreStart
} catch( ErrorException $e ) {
// This is caused by an array to string conversion error.
}
} // @codeCoverageIgnoreEnd
/**
* Detects MIME Type based on file extension.
@@ -53,11 +57,11 @@ class MimeType
/**
* @param string $filename
*
* @return string
* @return string|null MIME Type or NULL if no extension detected
*/
public static function detectByFilename($filename)
{
$extension = pathinfo($filename, PATHINFO_EXTENSION);
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
return empty($extension) ? 'text/plain' : static::detectByFileExtension($extension);
}
@@ -150,6 +154,8 @@ class MimeType
'rtf' => 'text/rtf',
'xml' => 'application/xml',
'xsl' => 'application/xml',
'dmn' => 'application/octet-stream',
'bpmn' => 'application/octet-stream',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
@@ -159,6 +165,7 @@ class MimeType
'movie' => 'video/x-sgi-movie',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'docm' => 'application/vnd.ms-word.template.macroEnabled.12',
'dot' => 'application/msword',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
@@ -208,6 +215,18 @@ class MimeType
'cdr' => 'application/cdr',
'wma' => 'audio/x-ms-wma',
'jar' => 'application/java-archive',
'tex' => 'application/x-tex',
'latex' => 'application/x-latex',
'odt' => 'application/vnd.oasis.opendocument.text',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'odg' => 'application/vnd.oasis.opendocument.graphics',
'odc' => 'application/vnd.oasis.opendocument.chart',
'odf' => 'application/vnd.oasis.opendocument.formula',
'odi' => 'application/vnd.oasis.opendocument.image',
'odm' => 'application/vnd.oasis.opendocument.text-master',
'odb' => 'application/vnd.oasis.opendocument.database',
'ott' => 'application/vnd.oasis.opendocument.text-template',
];
}
}

View File

@@ -20,7 +20,7 @@ class StreamHasher
}
/**
* @param $resource
* @param resource $resource
*
* @return string
*/

View File

@@ -17,16 +17,20 @@
"role": "Developer"
}
],
"config": {
"sort-packages": true
},
"require": {
"php": ">=5.4"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"mockery/mockery": "~0.9",
"doctrine/orm": "^2.5",
"illuminate/contracts": "~5.0",
"squizlabs/php_codesniffer": "~1.5",
"mockery/mockery": "~0.9",
"pagerfanta/pagerfanta": "~1.0.0",
"zendframework/zend-paginator":"~2.3"
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5",
"zendframework/zend-paginator": "~2.3"
},
"suggest": {
"illuminate/pagination": "The Illuminate Pagination component.",

View File

@@ -38,6 +38,13 @@ class Manager
*/
protected $requestedExcludes = [];
/**
* Array of requested fieldsets.
*
* @var array
*/
protected $requestedFieldsets = [];
/**
* Array containing modifiers as keys and an array value of params.
*
@@ -66,6 +73,18 @@ class Manager
*/
protected $serializer;
/**
* Factory used to create new configured scopes.
*
* @var ScopeFactoryInterface
*/
private $scopeFactory;
public function __construct(ScopeFactoryInterface $scopeFactory = null)
{
$this->scopeFactory = $scopeFactory ?: new ScopeFactory();
}
/**
* Create Data.
*
@@ -79,18 +98,11 @@ class Manager
*/
public function createData(ResourceInterface $resource, $scopeIdentifier = null, Scope $parentScopeInstance = null)
{
$scopeInstance = new Scope($this, $resource, $scopeIdentifier);
// Update scope history
if ($parentScopeInstance !== null) {
// This will be the new children list of parents (parents parents, plus the parent)
$scopeArray = $parentScopeInstance->getParentScopes();
$scopeArray[] = $parentScopeInstance->getScopeIdentifier();
$scopeInstance->setParentScopes($scopeArray);
return $this->scopeFactory->createChildScopeFor($this, $parentScopeInstance, $resource, $scopeIdentifier);
}
return $scopeInstance;
return $this->scopeFactory->createScopeFor($this, $resource, $scopeIdentifier);
}
/**
@@ -208,6 +220,49 @@ class Manager
return $this;
}
/**
* Parse field parameter.
*
* @param array $fieldsets Array of fields to include. It must be an array
* whose keys are resource types and values a string
* of the fields to return, separated by a comma
*
* @return $this
*/
public function parseFieldsets(array $fieldsets)
{
$this->requestedFieldsets = [];
foreach ($fieldsets as $type => $fields) {
//Remove empty and repeated fields
$this->requestedFieldsets[$type] = array_unique(array_filter(explode(',', $fields)));
}
return $this;
}
/**
* Get requested fieldsets.
*
* @return array
*/
public function getRequestedFieldsets()
{
return $this->requestedFieldsets;
}
/**
* Get fieldset params for the specified type.
*
* @param string $type
*
* @return \League\Fractal\ParamBag|null
*/
public function getFieldset($type)
{
return !isset($this->requestedFieldsets[$type]) ?
null :
new ParamBag($this->requestedFieldsets[$type]);
}
/**
* Parse Exclude String.
*

View File

@@ -0,0 +1,118 @@
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
use Doctrine\ORM\Tools\Pagination\Paginator;
/**
* A paginator adapter for doctrine pagination.
*
* @author Fraser Stockley <fraser.stockley@gmail.com>
*/
class DoctrinePaginatorAdapter implements PaginatorInterface
{
/**
* The paginator instance.
* @var Paginator
*/
private $paginator;
/**
* The route generator.
*
* @var callable
*/
private $routeGenerator;
/**
* Create a new DoctrinePaginatorAdapter.
* @param Paginator $paginator
* @param callable $routeGenerator
*
*/
public function __construct(Paginator $paginator, callable $routeGenerator)
{
$this->paginator = $paginator;
$this->routeGenerator = $routeGenerator;
}
/**
* Get the current page.
*
* @return int
*/
public function getCurrentPage()
{
return ($this->paginator->getQuery()->getFirstResult() / $this->paginator->getQuery()->getMaxResults()) + 1;
}
/**
* Get the last page.
*
* @return int
*/
public function getLastPage()
{
return (int) ceil($this->getTotal() / $this->paginator->getQuery()->getMaxResults());
}
/**
* Get the total.
*
* @return int
*/
public function getTotal()
{
return count($this->paginator);
}
/**
* Get the count.
*
* @return int
*/
public function getCount()
{
return $this->paginator->getIterator()->count();
}
/**
* Get the number per page.
*
* @return int
*/
public function getPerPage()
{
return $this->paginator->getQuery()->getMaxResults();
}
/**
* Get the url for the given page.
*
* @param int $page
*
* @return string
*/
public function getUrl($page)
{
return call_user_func($this->getRouteGenerator(), $page);
}
/**
* Get the the route generator.
*
* @return callable
*/
private function getRouteGenerator()
{
return $this->routeGenerator;
}
}

View File

@@ -0,0 +1,108 @@
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
/**
* A paginator adapter for PhalconPHP/pagination.
*
* @author Thien Tran <fcduythien@gmail.com>
*
*/
class PhalconFrameworkPaginatorAdapter implements PaginatorInterface
{
/**
* A slice of the result set to show in the pagination
*
* @var \Phalcon\Paginator\AdapterInterface
*/
private $paginator;
public function __construct($paginator)
{
$this->paginator = $paginator->getPaginate();
}
/**
* Get the current page.
*
* @return int
*/
public function getCurrentPage()
{
return $this->paginator->current;
}
/**
* Get the last page.
*
* @return int
*/
public function getLastPage()
{
return $this->paginator->last;
}
/**
* Get the total.
*
* @return int
*/
public function getTotal()
{
return $this->paginator->total_items;
}
/**
* Get the count.
*
* @return int
*/
public function getCount()
{
return $this->paginator->total_pages;
}
/**
* Get the number per page.
*
* @return int
*/
public function getPerPage()
{
// $this->paginator->items->count()
// Because when we use raw sql have not this method
return count($this->paginator->items);
}
/**
* Get the next.
*
* @return int
*/
public function getNext()
{
return $this->paginator->next;
}
/**
* Get the url for the given page.
*
* @param int $page
*
* @return string
*/
public function getUrl($page)
{
return $page;
}
}

View File

@@ -31,7 +31,7 @@ class Collection extends ResourceAbstract
protected $data;
/**
* A the paginator instance.
* The paginator instance.
*
* @var PaginatorInterface
*/

View File

@@ -14,7 +14,7 @@ namespace League\Fractal\Resource;
/**
* Item Resource
*
* The Item Resource can stored any mixed data, usually an ORM, ODM or
* The Item Resource can store any mixed data, usually an ORM, ODM or
* other sort of intelligent result, DataMapper model, etc but could
* be a basic array, object, or whatever you like.
*/

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Resource;
/**
* Primitive Resource
*
* The Primitive Resource can store any primitive data, like a string, integer,
* float, double etc.
*/
class Primitive extends ResourceAbstract
{
//
}

View File

@@ -127,7 +127,7 @@ abstract class ResourceAbstract implements ResourceInterface
* Set the transformer.
*
* @param callable|TransformerAbstract $transformer
*
*
* @return $this
*/
public function setTransformer($transformer)

View File

@@ -14,6 +14,7 @@ namespace League\Fractal;
use InvalidArgumentException;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
use League\Fractal\Resource\NullResource;
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Serializer\SerializerAbstract;
@@ -240,6 +241,9 @@ class Scope
// If the serializer wants the includes to be side-loaded then we'll
// serialize the included data and merge it with the data.
if ($serializer->sideloadIncludes()) {
//Filter out any relation that wasn't requested
$rawIncludedData = array_map(array($this, 'filterFieldsets'), $rawIncludedData);
$includedData = $serializer->includedData($this->resource, $rawIncludedData);
// If the serializer wants to inject additional information
@@ -273,17 +277,55 @@ class Scope
// Pull out all of OUR metadata and any custom meta data to merge with the main level data
$meta = $serializer->meta($this->resource->getMeta());
// in case of returning NullResource we should return null and not to go with array_merge
if (is_null($data)) {
if (!empty($meta)) {
return $meta;
}
return null;
}
return array_merge($data, $meta);
}
/**
* Convert the current data for this scope to JSON.
*
* @param int $options
*
* @return string
*/
public function toJson()
public function toJson($options = 0)
{
return json_encode($this->toArray());
return json_encode($this->toArray(), $options);
}
/**
* Transformer a primitive resource
*
* @return mixed
*/
public function transformPrimitiveResource()
{
if (! ($this->resource instanceof Primitive)) {
throw new InvalidArgumentException(
'Argument $resource should be an instance of League\Fractal\Resource\Primitive'
);
}
$transformer = $this->resource->getTransformer();
$data = $this->resource->getData();
if (null === $transformer) {
$transformedData = $data;
} elseif (is_callable($transformer)) {
$transformedData = call_user_func($transformer, $data);
} else {
$transformer->setCurrentScope($this);
$transformedData = $transformer->transform($data);
}
return $transformedData;
}
/**
@@ -370,6 +412,9 @@ class Scope
$transformedData = $this->manager->getSerializer()->mergeIncludes($transformedData, $includedData);
}
//Stick only with requested fields
$transformedData = $this->filterFieldsets($transformedData);
return [$transformedData, $includedData];
}
@@ -420,4 +465,67 @@ class Scope
{
return empty($this->parentScopes);
}
/**
* Filter the provided data with the requested filter fieldset for
* the scope resource
*
* @internal
*
* @param array $data
*
* @return array
*/
protected function filterFieldsets(array $data)
{
if (!$this->hasFilterFieldset()) {
return $data;
}
$serializer = $this->manager->getSerializer();
$requestedFieldset = iterator_to_array($this->getFilterFieldset());
//Build the array of requested fieldsets with the mandatory serializer fields
$filterFieldset = array_flip(
array_merge(
$serializer->getMandatoryFields(),
$requestedFieldset
)
);
return array_intersect_key($data, $filterFieldset);
}
/**
* Return the requested filter fieldset for the scope resource
*
* @internal
*
* @return \League\Fractal\ParamBag|null
*/
protected function getFilterFieldset()
{
return $this->manager->getFieldset($this->getResourceType());
}
/**
* Check if there are requested filter fieldsets for the scope resource.
*
* @internal
*
* @return bool
*/
protected function hasFilterFieldset()
{
return $this->getFilterFieldset() !== null;
}
/**
* Return the scope resource type.
*
* @internal
*
* @return string
*/
protected function getResourceType()
{
return $this->resource->getResourceKey();
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal;
use League\Fractal\Resource\ResourceInterface;
class ScopeFactory implements ScopeFactoryInterface
{
/**
* @param Manager $manager
* @param ResourceInterface $resource
* @param string|null $scopeIdentifier
* @return Scope
*/
public function createScopeFor(Manager $manager, ResourceInterface $resource, $scopeIdentifier = null)
{
return new Scope($manager, $resource, $scopeIdentifier);
}
/**
* @param Manager $manager
* @param Scope $parentScopeInstance
* @param ResourceInterface $resource
* @param string|null $scopeIdentifier
* @return Scope
*/
public function createChildScopeFor(Manager $manager, Scope $parentScopeInstance, ResourceInterface $resource, $scopeIdentifier = null)
{
$scopeInstance = $this->createScopeFor($manager, $resource, $scopeIdentifier);
// This will be the new children list of parents (parents parents, plus the parent)
$scopeArray = $parentScopeInstance->getParentScopes();
$scopeArray[] = $parentScopeInstance->getScopeIdentifier();
$scopeInstance->setParentScopes($scopeArray);
return $scopeInstance;
}
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal;
use League\Fractal\Resource\ResourceInterface;
/**
* ScopeFactoryInterface
*
* Creates Scope Instances for resources
*/
interface ScopeFactoryInterface
{
/**
* @param Manager $manager
* @param ResourceInterface $resource
* @param string|null $scopeIdentifier
* @return Scope
*/
public function createScopeFor(Manager $manager, ResourceInterface $resource, $scopeIdentifier = null);
/**
* @param Manager $manager
* @param Scope $parentScope
* @param ResourceInterface $resource
* @param string|null $scopeIdentifier
* @return Scope
*/
public function createChildScopeFor(Manager $manager, Scope $parentScope, ResourceInterface $resource, $scopeIdentifier = null);
}

View File

@@ -72,10 +72,23 @@ class JsonApiSerializer extends ArraySerializer
unset($resource['data']['attributes']['id']);
if(isset($resource['data']['attributes']['links'])) {
$custom_links = $data['links'];
unset($resource['data']['attributes']['links']);
}
if (isset($resource['data']['attributes']['meta'])){
$resource['data']['meta'] = $data['meta'];
unset($resource['data']['attributes']['meta']);
}
if ($this->shouldIncludeLinks()) {
$resource['data']['links'] = [
'self' => "{$this->baseUrl}/$resourceKey/$id",
];
if(isset($custom_links)) {
$resource['data']['links'] = array_merge($custom_links, $resource['data']['links']);
}
}
return $resource;
@@ -171,16 +184,7 @@ class JsonApiSerializer extends ArraySerializer
}
$includeObjects = $this->createIncludeObjects($includeObject);
foreach ($includeObjects as $object) {
$includeType = $object['type'];
$includeId = $object['id'];
$cacheKey = "$includeType:$includeId";
if (!array_key_exists($cacheKey, $linkedIds)) {
$serializedData[] = $object;
$linkedIds[$cacheKey] = $object;
}
}
list($serializedData, $linkedIds) = $this->serializeIncludedObjectsWithCacheKey($includeObjects, $linkedIds, $serializedData);
}
}
@@ -244,6 +248,16 @@ class JsonApiSerializer extends ArraySerializer
return $includedData;
}
/**
* Get the mandatory fields for the serializer
*
* @return array
*/
public function getMandatoryFields()
{
return ['id'];
}
/**
* Filter function to delete root objects from array.
*
@@ -381,16 +395,7 @@ class JsonApiSerializer extends ArraySerializer
foreach ($data as $value) {
foreach ($value as $includeObject) {
if (isset($includeObject['included'])) {
foreach ($includeObject['included'] as $object) {
$includeType = $object['type'];
$includeId = $object['id'];
$cacheKey = "$includeType:$includeId";
if (!array_key_exists($cacheKey, $linkedIds)) {
$includedData[] = $object;
$linkedIds[$cacheKey] = $object;
}
}
list($includedData, $linkedIds) = $this->serializeIncludedObjectsWithCacheKey($includeObject['included'], $linkedIds, $includedData);
}
}
}
@@ -564,4 +569,25 @@ class JsonApiSerializer extends ArraySerializer
return $relationship;
}
/**
* @param $includeObjects
* @param $linkedIds
* @param $serializedData
*
* @return array
*/
private function serializeIncludedObjectsWithCacheKey($includeObjects, $linkedIds, $serializedData)
{
foreach ($includeObjects as $object) {
$includeType = $object['type'];
$includeId = $object['id'];
$cacheKey = "$includeType:$includeId";
if (!array_key_exists($cacheKey, $linkedIds)) {
$serializedData[] = $object;
$linkedIds[$cacheKey] = $object;
}
}
return [$serializedData, $linkedIds];
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace League\Fractal\Serializer;
use League\Fractal\Pagination\CursorInterface;
use League\Fractal\Pagination\PaginatorInterface;
use League\Fractal\Resource\ResourceInterface;
interface Serializer
{
/**
* Serialize a collection.
*
* @param string $resourceKey
* @param array $data
*
* @return array
*/
public function collection($resourceKey, array $data);
/**
* Serialize an item.
*
* @param string $resourceKey
* @param array $data
*
* @return array
*/
public function item($resourceKey, array $data);
/**
* Serialize null resource.
*
* @return array
*/
public function null();
/**
* Serialize the included data.
*
* @param ResourceInterface $resource
* @param array $data
*
* @return array
*/
public function includedData(ResourceInterface $resource, array $data);
/**
* Serialize the meta.
*
* @param array $meta
*
* @return array
*/
public function meta(array $meta);
/**
* Serialize the paginator.
*
* @param PaginatorInterface $paginator
*
* @return array
*/
public function paginator(PaginatorInterface $paginator);
/**
* Serialize the cursor.
*
* @param CursorInterface $cursor
*
* @return array
*/
public function cursor(CursorInterface $cursor);
public function mergeIncludes($transformedData, $includedData);
/**
* Indicates if includes should be side-loaded.
*
* @return bool
*/
public function sideloadIncludes();
/**
* Hook for the serializer to inject custom data based on the relationships of the resource.
*
* @param array $data
* @param array $rawIncludedData
*
* @return array
*/
public function injectData($data, $rawIncludedData);
/**
* Hook for the serializer to modify the final list of includes.
*
* @param array $includedData
* @param array $data
*
* @return array
*/
public function filterIncludes($includedData, $data);
}

View File

@@ -15,7 +15,7 @@ use League\Fractal\Pagination\CursorInterface;
use League\Fractal\Pagination\PaginatorInterface;
use League\Fractal\Resource\ResourceInterface;
abstract class SerializerAbstract
abstract class SerializerAbstract implements Serializer
{
/**
* Serialize a collection.
@@ -127,4 +127,14 @@ abstract class SerializerAbstract
{
return $includedData;
}
/**
* Get the mandatory fields for the serializer
*
* @return array
*/
public function getMandatoryFields()
{
return [];
}
}

View File

@@ -14,6 +14,7 @@ namespace League\Fractal;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\NullResource;
use League\Fractal\Resource\Primitive;
use League\Fractal\Resource\ResourceInterface;
/**
@@ -98,7 +99,7 @@ abstract class TransformerAbstract
foreach ($includes as $include) {
if ($scope->isExcluded($include)) {
$includes = array_diff($includes, [$include]);
$includes = array_diff($includes, [$include]);
}
}
@@ -155,7 +156,11 @@ abstract class TransformerAbstract
if ($resource = $this->callIncludeMethod($scope, $include, $data)) {
$childScope = $scope->embedChildScope($include, $resource);
$includedData[$include] = $childScope->toArray();
if ($childScope->getResource() instanceof Primitive) {
$includedData[$include] = $childScope->transformPrimitiveResource();
} else {
$includedData[$include] = $childScope->toArray();
}
}
return $includedData;
@@ -243,6 +248,20 @@ abstract class TransformerAbstract
return $this;
}
/**
* Create a new primitive resource object.
*
* @param mixed $data
* @param callable|null $transformer
* @param string $resourceKey
*
* @return Primitive
*/
protected function primitive($data, $transformer = null, $resourceKey = null)
{
return new Primitive($data, $transformer, $resourceKey);
}
/**
* Create a new item resource object.
*