<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Common\Internal\ConnectionStringSource;

/**
 * Configuration manager for accessing Windows Azure settings.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class CloudConfigurationManager
{
    private static $_isInitialized = false;
    private static $_sources;

    /**
     * Restrict users from creating instances from this class
     */
    private function __construct()
    {
    }

    /**
     * Initializes the connection string source providers.
     *
     * @return void
     */
    private static function _init()
    {
        if (!self::$_isInitialized) {
            self::$_sources = array();

            // Get list of default connection string sources.
            $default = ConnectionStringSource::getDefaultSources();
            foreach ($default as $name => $provider) {
                self::$_sources[$name] = $provider;
            }

            self::$_isInitialized = true;
        }
    }

    /**
     * Gets a connection string from all available sources.
     *
     * @param string $key The connection string key name.
     *
     * @return string If the key does not exist return null.
     */
    public static function getConnectionString($key)
    {
        Validate::canCastAsString($key, 'key');

        self::_init();
        $value = null;

        foreach (self::$_sources as $source) {
            $value = call_user_func_array($source, array($key));

            if (!empty($value)) {
                break;
            }
        }

        return $value;
    }

    /**
     * Registers a new connection string source provider. If the source to get
     * registered is a default source, only the name of the source is required.
     *
     * @param string   $name     The source name.
     * @param callable $provider The source callback.
     * @param boolean  $prepend  When true, the $provider is processed first when
     * calling getConnectionString. When false (the default) the $provider is
     * processed after the existing callbacks.
     *
     * @return void
     */
    public static function registerSource($name, $provider = null, $prepend = false)
    {
        Validate::canCastAsString($name, 'name');
        Validate::notNullOrEmpty($name, 'name');

        self::_init();
        $default = ConnectionStringSource::getDefaultSources();

        // Try to get callback if the user is trying to register a default source.
        $provider = Utilities::tryGetValue($default, $name, $provider);

        Validate::notNullOrEmpty($provider, 'callback');

        if ($prepend) {
            self::$_sources = array_merge(
                array($name => $provider),
                self::$_sources
            );
        } else {
            self::$_sources[$name] = $provider;
        }
    }

    /**
     * Unregisters a connection string source.
     *
     * @param string $name The source name.
     *
     * @return callable
     */
    public static function unregisterSource($name)
    {
        Validate::canCastAsString($name, 'name');
        Validate::notNullOrEmpty($name, 'name');

        self::_init();

        $sourceCallback = Utilities::tryGetValue(self::$_sources, $name);

        if (!is_null($sourceCallback)) {
            unset(self::$_sources[$name]);
        }

        return $sourceCallback;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @ignore
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Internal;

use MicrosoftAzure\Storage\Common\Exceptions\InvalidArgumentTypeException;

/**
 * Validates against a condition and throws an exception in case of failure.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class Validate
{
    /**
     * Throws exception if the provided variable type is not array.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws InvalidArgumentTypeException.
     *
     * @return void
     */
    public static function isArray($var, $name)
    {
        if (!is_array($var)) {
            throw new InvalidArgumentTypeException(gettype(array()), $name);
        }
    }

    /**
     * Throws exception if the provided variable can not convert to a string.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws InvalidArgumentTypeException
     *
     * @return void
     */
    public static function canCastAsString($var, $name)
    {
        try {
            (string)$var;
        } catch (\Exception $e) {
            throw new InvalidArgumentTypeException(gettype(''), $name);
        }
    }

    /**
     * Throws exception if the provided variable type is not boolean.
     *
     * @param mixed $var variable to check against.
     *
     * @throws InvalidArgumentTypeException
     *
     * @return void
     */
    public static function isBoolean($var)
    {
        (bool)$var;
    }

    /**
     * Throws exception if the provided variable is set to null.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public static function notNullOrEmpty($var, $name)
    {
        if (is_null($var) || (empty($var) && $var != '0')) {
            throw new \InvalidArgumentException(
                sprintf(Resources::NULL_OR_EMPTY_MSG, $name)
            );
        }
    }

    /**
     * Throws exception if the provided variable is not double.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public static function isDouble($var, $name)
    {
        if (!is_numeric($var)) {
            throw new InvalidArgumentTypeException('double', $name);
        }
    }

    /**
     * Throws exception if the provided variable type is not integer.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws InvalidArgumentTypeException
     *
     * @return void
     */
    public static function isInteger($var, $name)
    {
        try {
            (int)$var;
        } catch (\Exception $e) {
            throw new InvalidArgumentTypeException(gettype(123), $name);
        }
    }

    /**
     * Returns whether the variable is an empty or null string.
     *
     * @param string $var value.
     *
     * @return boolean
     */
    public static function isNullOrEmptyString($var)
    {
        try {
            (string)$var;
        } catch (\Exception $e) {
            return false;
        }

        return (!isset($var) || trim($var)==='');
    }

    /**
     * Throws exception if the provided condition is not satisfied.
     *
     * @param bool   $isSatisfied    condition result.
     * @param string $failureMessage the exception message
     *
     * @throws \Exception
     *
     * @return void
     */
    public static function isTrue($isSatisfied, $failureMessage)
    {
        if (!$isSatisfied) {
            throw new \InvalidArgumentException($failureMessage);
        }
    }

    /**
     * Throws exception if the provided $date is not of type \DateTime
     *
     * @param mixed $date variable to check against.
     *
     * @throws InvalidArgumentTypeException
     *
     * @return void
     */
    public static function isDate($date)
    {
        if (gettype($date) != 'object' || get_class($date) != 'DateTime') {
            throw new InvalidArgumentTypeException('DateTime');
        }
    }

    /**
     * Throws exception if the provided variable is set to null.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public static function notNull($var, $name)
    {
        if (is_null($var)) {
            throw new \InvalidArgumentException(sprintf(Resources::NULL_MSG, $name));
        }
    }

    /**
     * Throws exception if the object is not of the specified class type.
     *
     * @param mixed  $objectInstance An object that requires class type validation.
     * @param mixed  $classInstance  The instance of the class the the
     * object instance should be.
     * @param string $name           The name of the object.
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public static function isInstanceOf($objectInstance, $classInstance, $name)
    {
        Validate::notNull($classInstance, 'classInstance');
        if (is_null($objectInstance)) {
            return true;
        }

        $objectType = gettype($objectInstance);
        $classType  = gettype($classInstance);

        if ($objectType === $classType) {
            return true;
        } else {
            throw new \InvalidArgumentException(
                sprintf(
                    Resources::INSTANCE_TYPE_VALIDATION_MSG,
                    $name,
                    $objectType,
                    $classType
                )
            );
        }
    }

    /**
     * Creates an anonymous function that checks if the given hostname is valid or not.
     *
     * @return callable
     */
    public static function getIsValidHostname()
    {
        return function ($hostname) {
            return Validate::isValidHostname($hostname);
        };
    }

    /**
     * Throws an exception if the string is not of a valid hostname.
     *
     * @param string $hostname String to check.
     *
     * @throws \InvalidArgumentException
     *
     * @return boolean
     */
    public static function isValidHostname($hostname)
    {
        if (defined('FILTER_VALIDATE_DOMAIN')) {
            $isValid = filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
        } else {
            // (less accurate) fallback for PHP < 7.0
            $isValid = preg_match('/^[a-z0-9_-]+(\.[a-z0-9_-]+)*$/i', $hostname);
        }

        if ($isValid) {
            return true;
        } else {
            throw new \RuntimeException(
                sprintf(Resources::INVALID_CONFIG_HOSTNAME, $hostname)
            );
        }
    }

    /**
     * Creates a anonymous function that check if the given uri is valid or not.
     *
     * @return callable
     */
    public static function getIsValidUri()
    {
        return function ($uri) {
            return Validate::isValidUri($uri);
        };
    }

    /**
     * Throws exception if the string is not of a valid uri.
     *
     * @param string $uri String to check.
     *
     * @throws \InvalidArgumentException
     *
     * @return boolean
     */
    public static function isValidUri($uri)
    {
        $isValid = filter_var($uri, FILTER_VALIDATE_URL);

        if ($isValid) {
            return true;
        } else {
            throw new \RuntimeException(
                sprintf(Resources::INVALID_CONFIG_URI, $uri)
            );
        }
    }

    /**
     * Throws exception if the provided variable type is not object.
     *
     * @param mixed  $var  The variable to check.
     * @param string $name The parameter name.
     *
     * @throws InvalidArgumentTypeException.
     *
     * @return boolean
     */
    public static function isObject($var, $name)
    {
        if (!is_object($var)) {
            throw new InvalidArgumentTypeException('object', $name);
        }

        return true;
    }

    /**
     * Throws exception if the object is not of the specified class type.
     *
     * @param mixed  $objectInstance An object that requires class type validation.
     * @param string $class          The class the object instance should be.
     * @param string $name           The parameter name.
     *
     * @throws \InvalidArgumentException
     *
     * @return boolean
     */
    public static function isA($objectInstance, $class, $name)
    {
        Validate::canCastAsString($class, 'class');
        Validate::notNull($objectInstance, 'objectInstance');
        Validate::isObject($objectInstance, 'objectInstance');

        $objectType = get_class($objectInstance);

        if (is_a($objectInstance, $class)) {
            return true;
        } else {
            throw new \InvalidArgumentException(
                sprintf(
                    Resources::INSTANCE_TYPE_VALIDATION_MSG,
                    $name,
                    $objectType,
                    $class
                )
            );
        }
    }

    /**
     * Validate if method exists in object
     *
     * @param object $objectInstance An object that requires method existing
     *                               validation
     * @param string $method         Method name
     * @param string $name           The parameter name
     *
     * @return boolean
     */
    public static function methodExists($objectInstance, $method, $name)
    {
        Validate::canCastAsString($method, 'method');
        Validate::notNull($objectInstance, 'objectInstance');
        Validate::isObject($objectInstance, 'objectInstance');

        if (method_exists($objectInstance, $method)) {
            return true;
        } else {
            throw new \InvalidArgumentException(
                sprintf(
                    Resources::ERROR_METHOD_NOT_FOUND,
                    $method,
                    $name
                )
            );
        }
    }

    /**
     * Validate if string is date formatted
     *
     * @param string $value Value to validate
     * @param string $name  Name of parameter to insert in erro message
     *
     * @throws \InvalidArgumentException
     *
     * @return boolean
     */
    public static function isDateString($value, $name)
    {
        Validate::canCastAsString($value, 'value');

        try {
            new \DateTime($value);
            return true;
        } catch (\Exception $e) {
            throw new \InvalidArgumentException(
                sprintf(
                    Resources::ERROR_INVALID_DATE_STRING,
                    $name,
                    $value
                )
            );
        }
    }

    /**
     * Validate if the provided array has key, throw exception otherwise.
     *
     * @param  string  $key   The key to be searched.
     * @param  string  $name  The name of the array.
     * @param  array   $array The array to be validated.
     *
     * @throws \UnexpectedValueException
     * @throws \InvalidArgumentException
     *
     * @return  boolean
     */
    public static function hasKey($key, $name, array $array)
    {
        Validate::isArray($array, $name);

        if (!array_key_exists($key, $array)) {
            throw new \UnexpectedValueException(
                sprintf(
                    Resources::INVALID_VALUE_MSG,
                    $name,
                    sprintf(Resources::ERROR_KEY_NOT_EXIST, $key)
                )
            );
        }

        return true;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Models;

/**
 * Holds info about resource+ range used in HTTP requests
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class Range
{
    private $start;
    private $end;

    /**
     * Constructor
     *
     * @param integer $start the resource start value
     * @param integer $end   the resource end value
     *
     * @return Range
     */
    public function __construct($start, $end = null)
    {
        $this->start = $start;
        $this->end   = $end;
    }

    /**
     * Sets resource start range
     *
     * @param integer $start the resource range start
     *
     * @return void
     */
    public function setStart($start)
    {
        $this->start = $start;
    }

    /**
     * Gets resource start range
     *
     * @return integer
     */
    public function getStart()
    {
        return $this->start;
    }

    /**
     * Sets resource end range
     *
     * @param integer $end the resource range end
     *
     * @return void
     */
    public function setEnd($end)
    {
        $this->end = $end;
    }

    /**
     * Gets resource end range
     *
     * @return integer
     */
    public function getEnd()
    {
        return $this->end;
    }

    /**
     * Gets resource range length
     *
     * @return integer
     */
    public function getLength()
    {
        if ($this->end != null) {
            return $this->end - $this->start + 1;
        } else {
            return null;
        }
    }

    /**
     * Sets resource range length
     *
     * @param integer $value new resource range
     *
     * @return void
     */
    public function setLength($value)
    {
        $this->end = $this->start + $value - 1;
    }

    /**
     * Constructs the range string according to the set start and end
     *
     * @return string
     */
    public function getRangeString()
    {
        $rangeString = '';

        $rangeString .= ('bytes=' . $this->start . '-');
        if ($this->end != null) {
            $rangeString .= $this->end;
        }

        return $rangeString;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Queue;

use MicrosoftAzure\Storage\Common\Internal\Authentication\SharedAccessSignatureAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Authentication\SharedKeyAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Authentication\TokenAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Http\HttpFormatter;
use MicrosoftAzure\Storage\Common\Internal\Middlewares\CommonRequestMiddleware;
use MicrosoftAzure\Storage\Common\Internal\Serialization\XmlSerializer;
use MicrosoftAzure\Storage\Common\Internal\ServiceRestProxy;
use MicrosoftAzure\Storage\Common\Internal\ServiceRestTrait;
use MicrosoftAzure\Storage\Common\Internal\StorageServiceSettings;
use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Common\LocationMode;
use MicrosoftAzure\Storage\Queue\Internal\IQueue;
use MicrosoftAzure\Storage\Queue\Internal\QueueResources as Resources;
use MicrosoftAzure\Storage\Queue\Models\CreateMessageOptions;
use MicrosoftAzure\Storage\Queue\Models\CreateMessageResult;
use MicrosoftAzure\Storage\Queue\Models\CreateQueueOptions;
use MicrosoftAzure\Storage\Queue\Models\GetQueueMetadataResult;
use MicrosoftAzure\Storage\Queue\Models\ListMessagesOptions;
use MicrosoftAzure\Storage\Queue\Models\ListMessagesResult;
use MicrosoftAzure\Storage\Queue\Models\ListQueuesOptions;
use MicrosoftAzure\Storage\Queue\Models\ListQueuesResult;
use MicrosoftAzure\Storage\Queue\Models\PeekMessagesOptions;
use MicrosoftAzure\Storage\Queue\Models\PeekMessagesResult;
use MicrosoftAzure\Storage\Queue\Models\QueueACL;
use MicrosoftAzure\Storage\Queue\Models\QueueMessage;
use MicrosoftAzure\Storage\Queue\Models\QueueServiceOptions;
use MicrosoftAzure\Storage\Queue\Models\UpdateMessageResult;

/**
 * This class constructs HTTP requests and receive HTTP responses for queue
 * service layer.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Queue
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class QueueRestProxy extends ServiceRestProxy implements IQueue
{
    use ServiceRestTrait;

    /**
     * Builds a queue service object, it accepts the following
     * options:
     *
     * - http: (array) the underlying guzzle options. refer to
     *   http://docs.guzzlephp.org/en/latest/request-options.html for detailed available options
     * - middlewares: (mixed) the middleware should be either an instance of a sub-class that
     *   implements {@see MicrosoftAzure\Storage\Common\Middlewares\IMiddleware}, or a
     *   `callable` that follows the Guzzle middleware implementation convention
     *
     * Please refer to
     * https://azure.microsoft.com/en-us/documentation/articles/storage-configure-connection-string
     * for how to construct a connection string with storage account name/key, or with a shared
     * access signature (SAS Token).
     *
     * @param string $connectionString The configuration connection string.
     * @param array  $options          Array of options to pass to the service
     *
     * @return QueueRestProxy
     */
    public static function createQueueService(
        $connectionString,
        array $options = []
    ) {
        $settings = StorageServiceSettings::createFromConnectionString(
            $connectionString
        );

        $primaryUri = Utilities::tryAddUrlScheme(
            $settings->getQueueEndpointUri()
        );
        $secondaryUri = Utilities::tryAddUrlScheme(
            $settings->getQueueSecondaryEndpointUri()
        );

        $queueWrapper = new QueueRestProxy(
            $primaryUri,
            $secondaryUri,
            $settings->getName(),
            $options
        );

        // Getting authentication scheme
        if ($settings->hasSasToken()) {
            $authScheme = new SharedAccessSignatureAuthScheme(
                $settings->getSasToken()
            );
        } else {
            $authScheme = new SharedKeyAuthScheme(
                $settings->getName(),
                $settings->getKey()
            );
        }

        // Adding common request middleware
        $commonRequestMiddleware = new CommonRequestMiddleware(
            $authScheme,
            Resources::STORAGE_API_LATEST_VERSION,
            Resources::QUEUE_SDK_VERSION
        );
        $queueWrapper->pushMiddleware($commonRequestMiddleware);

        return $queueWrapper;
    }

    /**
     * Builds a queue service object, it accepts the following
     * options:
     *
     * - http: (array) the underlying guzzle options. refer to
     *   http://docs.guzzlephp.org/en/latest/request-options.html for detailed available options
     * - middlewares: (mixed) the middleware should be either an instance of a sub-class that
     *   implements {@see MicrosoftAzure\Storage\Common\Middlewares\IMiddleware}, or a
     *   `callable` that follows the Guzzle middleware implementation convention
     *
     * Please refer to
     * https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad
     * for authenticate access to Azure blobs and queues using Azure Active Directory.
     *
     * @param string $token            The bearer token passed as reference.
     * @param string $connectionString The configuration connection string.
     * @param array  $options          Array of options to pass to the service
     *
     * @return QueueRestProxy
     */
    public static function createQueueServiceWithTokenCredential(
        &$token,
        $connectionString,
        array $options = []
    ) {
        $settings = StorageServiceSettings::createFromConnectionStringForTokenCredential(
            $connectionString
        );

        $primaryUri = Utilities::tryAddUrlScheme(
            $settings->getQueueEndpointUri()
        );

        $secondaryUri = Utilities::tryAddUrlScheme(
            $settings->getQueueSecondaryEndpointUri()
        );

        $queueWrapper = new QueueRestProxy(
            $primaryUri,
            $secondaryUri,
            $settings->getName(),
            $options
        );

        // Getting authentication scheme
        $authScheme = new TokenAuthScheme(
            $token
        );

        // Adding common request middleware
        $commonRequestMiddleware = new CommonRequestMiddleware(
            $authScheme,
            Resources::STORAGE_API_LATEST_VERSION,
            Resources::QUEUE_SDK_VERSION
        );
        $queueWrapper->pushMiddleware($commonRequestMiddleware);

        return $queueWrapper;
    }

    /**
     * Lists all queues in the storage account.
     *
     * @param ListQueuesOptions $options The optional list queue options.
     *
     * @return ListQueuesResult
     */
    public function listQueues(ListQueuesOptions $options = null)
    {
        return $this->listQueuesAsync($options)->wait();
    }

    /**
     * Creates promise to list all queues in the storage account.
     *
     * @param ListQueuesOptions $options The optional list queue options.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function listQueuesAsync(ListQueuesOptions $options = null)
    {
        $method      = Resources::HTTP_GET;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new ListQueuesOptions();
        }

        $maxResults = $options->getMaxResults();
        $include    = $options->getIncludeMetadata();
        $include    = $include ? 'metadata' : null;
        $prefix     = $options->getPrefix();
        $marker     = $options->getNextMarker();

        $this->addOptionalQueryParam($queryParams, Resources::QP_COMP, 'list');
        $this->addOptionalQueryParam($queryParams, Resources::QP_PREFIX, $prefix);
        $this->addOptionalQueryParam($queryParams, Resources::QP_MARKER, $marker);
        $this->addOptionalQueryParam($queryParams, Resources::QP_INCLUDE, $include);
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_MAX_RESULTS,
            $maxResults
        );

        $dataSerializer = $this->dataSerializer;

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            Resources::EMPTY_STRING,
            $options
        )->then(function ($response) use ($dataSerializer) {
            $parsed = $dataSerializer->unserialize($response->getBody());
            return ListQueuesResult::create(
                $parsed,
                Utilities::getLocationFromHeaders($response->getHeaders())
            );
        }, null);
    }

    /**
     * Clears all messages from the queue.
     *
     * If a queue contains a large number of messages, Clear Messages may time out
     * before all messages have been deleted. In this case the Queue service will
     * return status code 500 (Internal Server Error), with the additional error
     * code OperationTimedOut. If the operation times out, the client should
     * continue to retry Clear Messages until it succeeds, to ensure that all
     * messages have been deleted.
     *
     * @param string              $queueName The name of the queue.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return void
     */
    public function clearMessages($queueName, QueueServiceOptions $options = null)
    {
        $this->clearMessagesAsync($queueName, $options)->wait();
    }

    /**
     * Creates promise to clear all messages from the queue.
     *
     * If a queue contains a large number of messages, Clear Messages may time out
     * before all messages have been deleted. In this case the Queue service will
     * return status code 500 (Internal Server Error), with the additional error
     * code OperationTimedOut. If the operation times out, the client should
     * continue to retry Clear Messages until it succeeds, to ensure that all
     * messages have been deleted.
     *
     * @param string              $queueName The name of the queue.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function clearMessagesAsync(
        $queueName,
        QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');

        $method      = Resources::HTTP_DELETE;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName . '/messages';
        $body        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_NO_CONTENT,
            $body,
            $options
        );
    }

    /**
     * Adds a message to the queue and optionally sets a visibility timeout
     * for the message.
     *
     * @param string               $queueName   The name of the queue.
     * @param string               $messageText The message contents.
     * @param CreateMessageOptions $options     The optional parameters.
     *
     * @return CreateMessageResult
     */
    public function createMessage(
        $queueName,
        $messageText,
        CreateMessageOptions $options = null
    ) {
        return $this->createMessageAsync($queueName, $messageText, $options)->wait();
    }

    /**
     * Creates promise to add a message to the queue and optionally sets a
     * visibility timeout for the message.
     *
     * @param string               $queueName   The name of the queue.
     * @param string               $messageText The message contents.
     * @param CreateMessageOptions $options     The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createMessageAsync(
        $queueName,
        $messageText,
        CreateMessageOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');
        Validate::canCastAsString($messageText, 'messageText');

        $method      = Resources::HTTP_POST;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName . '/messages';
        $body        = Resources::EMPTY_STRING;
        $message     = new QueueMessage();
        $message->setMessageText($messageText);
        $body = $message->toXml($this->dataSerializer);

        if (is_null($options)) {
            $options = new CreateMessageOptions();
        }

        $this->addOptionalHeader(
            $headers,
            Resources::CONTENT_TYPE,
            Resources::URL_ENCODED_CONTENT_TYPE
        );

        $visibility = $options->getVisibilityTimeoutInSeconds();
        $timeToLive = $options->getTimeToLiveInSeconds();

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_VISIBILITY_TIMEOUT,
            $visibility
        );
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_MESSAGE_TTL,
            $timeToLive
        );

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        $dataSerializer = $this->dataSerializer;

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_CREATED,
            $body,
            $options
        )->then(function ($response) use ($dataSerializer) {
            $parsed = $dataSerializer->unserialize($response->getBody());
            return CreateMessageResult::create($parsed);
        }, null);
    }

    /**
     * Creates a new queue under the storage account.
     *
     * @param string                    $queueName The queue name.
     * @param Models\CreateQueueOptions  $options   The Optional parameters.
     *
     * @return void
     */
    public function createQueue(
        $queueName,
        Models\CreateQueueOptions $options = null
    ) {
        $this->createQueueAsync($queueName, $options)->wait();
    }

    /**
     * Creates promise to create a new queue under the storage account.
     *
     * @param string                     $queueName The queue name.
     * @param Models\CreateQueueOptions  $options   The Optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createQueueAsync(
        $queueName,
        Models\CreateQueueOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');

        $method      = Resources::HTTP_PUT;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName;

        if (is_null($options)) {
            $options = new CreateQueueOptions();
        }

        $metadata = $options->getMetadata();
        $headers  = $this->generateMetadataHeaders($metadata);

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            array(Resources::STATUS_CREATED, Resources::STATUS_NO_CONTENT),
            Resources::EMPTY_STRING,
            $options
        );
    }

    /**
     * Deletes a specified message from the queue.
     *
     * @param string              $queueName  The name of the queue.
     * @param string              $messageId  The id of the message.
     * @param string              $popReceipt The valid pop receipt value returned
     * from an earlier call to the Get Messages or Update Message operation.
     * @param QueueServiceOptions $options    The optional parameters.
     *
     * @return void
     */
    public function deleteMessage(
        $queueName,
        $messageId,
        $popReceipt,
        QueueServiceOptions $options = null
    ) {
        $this->deleteMessageAsync(
            $queueName,
            $messageId,
            $popReceipt,
            $options
        )->wait();
    }

    /**
     * Creates promise to delete a specified message from the queue.
     *
     * @param string              $queueName  The name of the queue.
     * @param string              $messageId  The id of the message.
     * @param string              $popReceipt The valid pop receipt value returned
     * from an earlier call to the Get Messages or Update Message operation.
     * @param QueueServiceOptions $options    The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function deleteMessageAsync(
        $queueName,
        $messageId,
        $popReceipt,
        QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');
        Validate::canCastAsString($messageId, 'messageId');
        Validate::notNullOrEmpty($messageId, 'messageId');
        Validate::canCastAsString($popReceipt, 'popReceipt');
        Validate::notNullOrEmpty($popReceipt, 'popReceipt');

        $method      = Resources::HTTP_DELETE;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName . '/messages/' . $messageId;
        $body        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_POPRECEIPT,
            $popReceipt
        );

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_NO_CONTENT,
            $body,
            $options
        );
    }

    /**
     * Deletes a queue.
     *
     * @param string              $queueName The queue name.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return void
     */
    public function deleteQueue($queueName, QueueServiceOptions $options = null)
    {
        $this->deleteQueueAsync($queueName, $options)->wait();
    }

    /**
     * Creates promise to delete a queue.
     *
     * @param string              $queueName The queue name.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function deleteQueueAsync(
        $queueName,
        QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');

        $method      = Resources::HTTP_DELETE;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_NO_CONTENT,
            Resources::EMPTY_STRING,
            $options
        );
    }

    /**
     * Returns queue properties, including user-defined metadata.
     *
     * @param string              $queueName The queue name.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return Models\GetQueueMetadataResult
     */
    public function getQueueMetadata($queueName, QueueServiceOptions $options = null)
    {
        return $this->getQueueMetadataAsync($queueName, $options)->wait();
    }

    /**
     * Creates promise to return queue properties, including user-defined metadata.
     *
     * @param string              $queueName The queue name.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getQueueMetadataAsync(
        $queueName,
        QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');

        $method      = Resources::HTTP_GET;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName;
        $body        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $this->addOptionalQueryParam($queryParams, Resources::QP_COMP, 'metadata');

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            $body,
            $options
        )->then(function ($response) {
            $responseHeaders = HttpFormatter::formatHeaders($response->getHeaders());
            $metadata = Utilities::getMetadataArray($responseHeaders);
            $maxCount = intval(
                Utilities::tryGetValue(
                    $responseHeaders,
                    Resources::X_MS_APPROXIMATE_MESSAGES_COUNT
                )
            );

            return new GetQueueMetadataResult($maxCount, $metadata);
        }, null);
    }

    /**
     * Lists all messages in the queue.
     *
     * @param string              $queueName The queue name.
     * @param ListMessagesOptions $options   The optional parameters.
     *
     * @return Models\ListMessagesResult
     */
    public function listMessages($queueName, ListMessagesOptions $options = null)
    {
        return $this->listMessagesAsync($queueName, $options)->wait();
    }

    /**
     * Creates promise to list all messages in the queue.
     *
     * @param string              $queueName The queue name.
     * @param ListMessagesOptions $options   The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function listMessagesAsync(
        $queueName,
        ListMessagesOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');

        $method      = Resources::HTTP_GET;
        $headers     = array();
        $queryParams = array();
        $postParams  = array();
        $path        = $queueName . '/messages';

        if (is_null($options)) {
            $options = new ListMessagesOptions();
        }

        $messagesCount = $options->getNumberOfMessages();
        $visibility    = $options->getVisibilityTimeoutInSeconds();

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_NUM_OF_MESSAGES,
            $messagesCount
        );
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_VISIBILITY_TIMEOUT,
            $visibility
        );

        $dataSerializer = $this->dataSerializer;

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            Resources::EMPTY_STRING,
            $options
        )->then(function ($response) use ($dataSerializer) {
            $parsed = $dataSerializer->unserialize($response->getBody());
            return ListMessagesResult::create($parsed);
        }, null);
    }

    /**
     * Retrieves a message from the front of the queue, without changing
     * the message visibility.
     *
     * @param string              $queueName The queue name.
     * @param PeekMessagesOptions $options   The optional parameters.
     *
     * @return Models\PeekMessagesResult
     */
    public function peekMessages($queueName, PeekMessagesOptions $options = null)
    {
        return $this->peekMessagesAsync($queueName, $options)->wait();
    }

    /**
     * Creates promise to retrieve a message from the front of the queue,
     * without changing the message visibility.
     *
     * @param string              $queueName The queue name.
     * @param PeekMessagesOptions $options   The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function peekMessagesAsync(
        $queueName,
        PeekMessagesOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');

        $method      = Resources::HTTP_GET;
        $headers     = array();
        $queryParams = array();
        $postParams  = array();
        $path        = $queueName . '/messages';

        if (is_null($options)) {
            $options = new PeekMessagesOptions();
        }

        $messagesCount = $options->getNumberOfMessages();

        $this->addOptionalQueryParam($queryParams, Resources::QP_PEEK_ONLY, 'true');
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_NUM_OF_MESSAGES,
            $messagesCount
        );

        $dataSerializer = $this->dataSerializer;

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            Resources::EMPTY_STRING,
            $options
        )->then(function ($response) use ($dataSerializer) {
            $parsed = $dataSerializer->unserialize($response->getBody());
            return PeekMessagesResult::create($parsed);
        }, null);
    }

    /**
     * Sets user-defined metadata on the queue. To delete queue metadata, call
     * this API without specifying any metadata in $metadata.
     *
     * @param string              $queueName The queue name.
     * @param array               $metadata  The metadata array.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return void
     */
    public function setQueueMetadata(
        $queueName,
        array $metadata = null,
        QueueServiceOptions $options = null
    ) {
        $this->setQueueMetadataAsync($queueName, $metadata, $options)->wait();
    }

    /**
     * Creates promise to set user-defined metadata on the queue. To delete
     * queue metadata, call this API without specifying any metadata in $metadata.
     *
     * @param string              $queueName The queue name.
     * @param array               $metadata  The metadata array.
     * @param QueueServiceOptions $options   The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function setQueueMetadataAsync(
        $queueName,
        array $metadata = null,
        QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');
        Utilities::validateMetadata($metadata);

        $method      = Resources::HTTP_PUT;
        $headers     = array();
        $queryParams = array();
        $postParams  = array();
        $path        = $queueName;
        $body        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $this->addOptionalQueryParam($queryParams, Resources::QP_COMP, 'metadata');

        $metadataHeaders = $this->generateMetadataHeaders($metadata);
        $headers         = $metadataHeaders;

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_NO_CONTENT,
            $body,
            $options
        );
    }

    /**
     * Updates the visibility timeout of a message and/or the message contents.
     *
     * @param string              $queueName                  The queue name.
     * @param string              $messageId                  The id of the message.
     * @param string              $popReceipt                 The valid pop receipt
     * value returned from an earlier call to the Get Messages or Update Message
     * operation.
     * @param string              $messageText                The message contents.
     * @param int                 $visibilityTimeoutInSeconds Specifies the new
     * visibility timeout value, in seconds, relative to server time.
     * The new value must be larger than or equal to 0, and cannot be larger
     * than 7 days. The visibility timeout of a message cannot be set to a value
     * later than the expiry time. A message can be updated until it has been
     * deleted or has expired.
     * @param QueueServiceOptions $options                    The optional
     * parameters.
     *
     * @return Models\UpdateMessageResult
     */
    public function updateMessage(
        $queueName,
        $messageId,
        $popReceipt,
        $messageText,
        $visibilityTimeoutInSeconds,
        QueueServiceOptions $options = null
    ) {
        return $this->updateMessageAsync(
            $queueName,
            $messageId,
            $popReceipt,
            $messageText,
            $visibilityTimeoutInSeconds,
            $options
        )->wait();
    }

    /**
     * Creates promise to update the visibility timeout of a message and/or the
     * message contents.
     *
     * @param string              $queueName                  The queue name.
     * @param string              $messageId                  The id of the message.
     * @param string              $popReceipt                 The valid pop receipt
     * value returned from an earlier call to the Get Messages or Update Message
     * operation.
     * @param string              $messageText                The message contents.
     * @param int                 $visibilityTimeoutInSeconds Specifies the new
     * visibility timeout value, in seconds, relative to server time.
     * The new value must be larger than or equal to 0, and cannot be larger
     * than 7 days. The visibility timeout of a message cannot be set to a value
     * later than the expiry time. A message can be updated until it has been
     * deleted or has expired.
     * @param QueueServiceOptions $options                    The optional
     * parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateMessageAsync(
        $queueName,
        $messageId,
        $popReceipt,
        $messageText,
        $visibilityTimeoutInSeconds,
        QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queueName, 'queueName');
        Validate::notNullOrEmpty($queueName, 'queueName');
        Validate::canCastAsString($messageId, 'messageId');
        Validate::notNullOrEmpty($messageId, 'messageId');
        Validate::canCastAsString($popReceipt, 'popReceipt');
        Validate::notNullOrEmpty($popReceipt, 'popReceipt');
        Validate::canCastAsString($messageText, 'messageText');
        Validate::isInteger(
            $visibilityTimeoutInSeconds,
            'visibilityTimeoutInSeconds'
        );
        Validate::notNull(
            $visibilityTimeoutInSeconds,
            'visibilityTimeoutInSeconds'
        );

        $method      = Resources::HTTP_PUT;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $path        = $queueName . '/messages' . '/' . $messageId;
        $body        = Resources::EMPTY_STRING;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_VISIBILITY_TIMEOUT,
            $visibilityTimeoutInSeconds
        );
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_POPRECEIPT,
            $popReceipt
        );

        if (!empty($messageText)) {
            $this->addOptionalHeader(
                $headers,
                Resources::CONTENT_TYPE,
                Resources::URL_ENCODED_CONTENT_TYPE
            );

            $message = new QueueMessage();
            $message->setMessageText($messageText);
            $body = $message->toXml($this->dataSerializer);
        }

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_NO_CONTENT,
            $body,
            $options
        )->then(function ($response) {
            $responseHeaders = HttpFormatter::formatHeaders($response->getHeaders());
            return UpdateMessageResult::create($responseHeaders);
        }, null);
    }

    /**
     * Gets the access control list (ACL)
     *
     * @param string                     $queue   The queue name.
     * @param Models\QueueServiceOptions $options The optional parameters.
     *
     * @return Models\QueueACL
     *
     * @see https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-queue-acl
     */
    public function getQueueAcl(
        $queue,
        Models\QueueServiceOptions $options = null
    ) {
        return $this->getQueueAclAsync($queue, $options)->wait();
    }

    /**
     * Creates the promise to gets the access control list (ACL)
     *
     * @param string                     $queue   The queue name.
     * @param Models\QueueServiceOptions $options The optional parameters.
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * @see https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-queue-acl
     */
    public function getQueueAclAsync(
        $queue,
        Models\QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queue, 'queue');

        $method      = Resources::HTTP_GET;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $statusCode  = Resources::STATUS_OK;
        $path        = $queue;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_COMP,
            'acl'
        );

        $dataSerializer = $this->dataSerializer;

        $promise = $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_OK,
            Resources::EMPTY_STRING,
            $options
        );

        return $promise->then(function ($response) use ($dataSerializer) {
            $parsed       = $dataSerializer->unserialize($response->getBody());
            return QueueACL::create($parsed);
        }, null);
    }

    /**
     * Sets the ACL.
     *
     * @param string                     $queue   name
     * @param Models\QueueACL            $acl     access control list for Queue
     * @param Models\QueueServiceOptions $options optional parameters
     *
     * @return void
     *
     * @see https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-queue-acl
     */
    public function setQueueAcl(
        $queue,
        Models\QueueACL $acl,
        Models\QueueServiceOptions $options = null
    ) {
        $this->setQueueAclAsync($queue, $acl, $options)->wait();
    }

    /**
     * Creates promise to set the ACL
     *
     * @param string                     $queue   name
     * @param Models\QueueACL            $acl     access control list for Queue
     * @param Models\QueueServiceOptions $options optional parameters
     *
     * @return \GuzzleHttp\Promise\PromiseInterface
     *
     * @see https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-queue-acl
     */
    public function setQueueAclAsync(
        $queue,
        Models\QueueACL $acl,
        Models\QueueServiceOptions $options = null
    ) {
        Validate::canCastAsString($queue, 'queue');
        Validate::notNullOrEmpty($acl, 'acl');

        $method      = Resources::HTTP_PUT;
        $headers     = array();
        $postParams  = array();
        $queryParams = array();
        $body        = $acl->toXml($this->dataSerializer);
        $path        = $queue;

        if (is_null($options)) {
            $options = new QueueServiceOptions();
        }

        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_COMP,
            'acl'
        );

        $options->setLocationMode(LocationMode::PRIMARY_ONLY);

        return $this->sendAsync(
            $method,
            $headers,
            $queryParams,
            $postParams,
            $path,
            Resources::STATUS_NO_CONTENT,
            $body,
            $options
        );
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Internal\Authentication
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common;

use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\Common\Internal\Validate;

/**
 * Provides methods to generate Azure Storage Shared Access Signature
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class SharedAccessSignatureHelper
{
    protected $accountName;
    protected $accountKey;

    /**
     * Constructor.
     *
     * @param string $accountName the name of the storage account.
     * @param string $accountKey the shared key of the storage account
     *
     */
    public function __construct($accountName, $accountKey)
    {
        Validate::canCastAsString($accountName, 'accountName');
        Validate::notNullOrEmpty($accountName, 'accountName');

        Validate::canCastAsString($accountKey, 'accountKey');
        Validate::notNullOrEmpty($accountKey, 'accountKey');

        $this->accountName = urldecode($accountName);
        $this->accountKey = $accountKey;
    }

    /**
     * Generates a shared access signature at the account level.
     *
     * @param string $signedVersion           Specifies the signed version to use.
     * @param string $signedPermissions       Specifies the signed permissions for
     *                                        the account SAS.
     * @param string $signedService           Specifies the signed services
     *                                        accessible with the account SAS.
     * @param string $signedResourceType      Specifies the signed resource types
     *                                        that are accessible with the account
     *                                        SAS.
     * @param \Datetime|string $signedExpiry  The time at which the shared access
     *                                        signature becomes invalid, in an ISO
     *                                        8601 format.
     * @param \Datetime|string $signedStart   The time at which the SAS becomes
     *                                        valid, in an ISO 8601 format.
     * @param string $signedIP                Specifies an IP address or a range
     *                                        of IP addresses from which to accept
     *                                        requests.
     * @param string $signedProtocol          Specifies the protocol permitted for
     *                                        a request made with the account SAS.
     *
     * @see Constructing an account SAS at
     *      https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/constructing-an-account-sas
     *
     * @return string
     */
    public function generateAccountSharedAccessSignatureToken(
        $signedVersion,
        $signedPermissions,
        $signedService,
        $signedResourceType,
        $signedExpiry,
        $signedStart = "",
        $signedIP = "",
        $signedProtocol = ""
    ) {
        // check that version is valid
        Validate::canCastAsString($signedVersion, 'signedVersion');
        Validate::notNullOrEmpty($signedVersion, 'signedVersion');
        Validate::isDateString($signedVersion, 'signedVersion');

        // validate and sanitize signed service
        $signedService = $this->validateAndSanitizeSignedService($signedService);

        // validate and sanitize signed resource type
        $signedResourceType = $this->validateAndSanitizeSignedResourceType($signedResourceType);

        // validate and sanitize signed permissions
        $signedPermissions = $this->validateAndSanitizeSignedPermissions($signedPermissions);

        // check that expiracy is valid
        if ($signedExpiry instanceof \Datetime) {
            $signedExpiry = Utilities::isoDate($signedExpiry);
        }
        Validate::canCastAsString($signedExpiry, 'signedExpiry');
        Validate::notNullOrEmpty($signedExpiry, 'signedExpiry');
        Validate::isDateString($signedExpiry, 'signedExpiry');

        // check that signed start is valid
        if ($signedStart instanceof \Datetime) {
            $signedStart = Utilities::isoDate($signedStart);
        }
        Validate::canCastAsString($signedStart, 'signedStart');
        if (strlen($signedStart) > 0) {
            Validate::isDateString($signedStart, 'signedStart');
        }

        // check that signed IP is valid
        Validate::canCastAsString($signedIP, 'signedIP');

        // validate and sanitize signed protocol
        $signedProtocol = $this->validateAndSanitizeSignedProtocol($signedProtocol);

        // construct an array with the parameters to generate the shared access signature at the account level
        $parameters = array();
        $parameters[] = $this->accountName;
        $parameters[] = $signedPermissions;
        $parameters[] = $signedService;
        $parameters[] = $signedResourceType;
        $parameters[] = $signedStart;
        $parameters[] = $signedExpiry;
        $parameters[] = $signedIP;
        $parameters[] = $signedProtocol;
        $parameters[] = $signedVersion;

        // implode the parameters into a string
        $stringToSign = utf8_encode(implode("\n", $parameters) . "\n");

        // decode the account key from base64
        $decodedAccountKey = base64_decode($this->accountKey);

        // create the signature with hmac sha256
        $signature = hash_hmac("sha256", $stringToSign, $decodedAccountKey, true);

        // encode the signature as base64 and url encode.
        $sig = urlencode(base64_encode($signature));

        //adding all the components for account SAS together.
        $sas  = 'sv=' . $signedVersion;
        $sas .= '&ss=' . $signedService;
        $sas .= '&srt=' . $signedResourceType;
        $sas .= '&sp=' . $signedPermissions;
        $sas .= '&se=' . $signedExpiry;
        $sas .= $signedStart === ''? '' : '&st=' . $signedStart;
        $sas .= $signedIP === ''? '' : '&sip=' . $signedIP;
        $sas .= '&spr=' . $signedProtocol;
        $sas .= '&sig=' . $sig;

        // return the signature
        return $sas;
    }

    /**
     * Validates and sanitizes the signed service parameter
     *
     * @param string $signedService Specifies the signed services accessible
     *                              with the account SAS.
     *
     * @return string
     */
    protected function validateAndSanitizeSignedService($signedService)
    {
        // validate signed service is not null or empty
        Validate::canCastAsString($signedService, 'signedService');
        Validate::notNullOrEmpty($signedService, 'signedService');

        // The signed service should only be a combination of the letters b(lob) q(ueue) t(able) or f(ile)
        $validServices = ['b', 'q', 't', 'f'];

        return $this->validateAndSanitizeStringWithArray(
            strtolower($signedService),
            $validServices
        );
    }

    /**
     * Validates and sanitizes the signed resource type parameter
     *
     * @param string $signedResourceType    Specifies the signed resource types
     *                                      that are accessible with the account
     *                                      SAS.
     *
     * @return string
     */
    protected function validateAndSanitizeSignedResourceType($signedResourceType)
    {
        // validate signed resource type is not null or empty
        Validate::canCastAsString($signedResourceType, 'signedResourceType');
        Validate::notNullOrEmpty($signedResourceType, 'signedResourceType');

        // The signed resource type should only be a combination of the letters s(ervice) c(container) or o(bject)
        $validResourceTypes = ['s', 'c', 'o'];

        return $this->validateAndSanitizeStringWithArray(
            strtolower($signedResourceType),
            $validResourceTypes
        );
    }

    /**
     * Validates and sanitizes the signed permissions parameter
     *
     * @param string $signedPermissions Specifies the signed permissions for the
     *                                  account SAS.
     *
     * @return string
     */
    protected function validateAndSanitizeSignedPermissions(
        $signedPermissions
    ) {
        // validate signed permissions are not null or empty
        Validate::canCastAsString($signedPermissions, 'signedPermissions');
        Validate::notNullOrEmpty($signedPermissions, 'signedPermissions');

        $validPermissions = ['r', 'w', 'd', 'l', 'a', 'c', 'u', 'p'];

        return $this->validateAndSanitizeStringWithArray(
            strtolower($signedPermissions),
            $validPermissions
        );
    }

    /**
     * Validates and sanitizes the signed protocol parameter
     *
     * @param string $signedProtocol Specifies the signed protocol for the
     *                               account SAS.

     * @return string
     */
    protected function validateAndSanitizeSignedProtocol($signedProtocol)
    {
        Validate::canCastAsString($signedProtocol, 'signedProtocol');
        // sanitize string
        $sanitizedSignedProtocol = strtolower($signedProtocol);
        if (strlen($sanitizedSignedProtocol) > 0) {
            if (strcmp($sanitizedSignedProtocol, "https") != 0 && strcmp($sanitizedSignedProtocol, "https,http") != 0) {
                throw new \InvalidArgumentException(Resources::SIGNED_PROTOCOL_INVALID_VALIDATION_MSG);
            }
        }

        return $sanitizedSignedProtocol;
    }

    /**
     * Removes duplicate characters from a string
     *
     * @param string $input        The input string.

     * @return string
     */
    protected function validateAndSanitizeStringWithArray($input, array $array)
    {
        $result = '';
        foreach ($array as $value) {
            if (strpos($input, $value) !== false) {
                //append the valid permission to result.
                $result .= $value;
                //remove all the character that represents the permission.
                $input = str_replace(
                    $value,
                    '',
                    $input
                );
            }
        }

        Validate::isTrue(
            strlen($input) == '',
            sprintf(
                Resources::STRING_NOT_WITH_GIVEN_COMBINATION,
                implode(', ', $array)
            )
        );
        return $result;
    }

    /**
     * Generate the canonical resource using the given account name, service
     * type and resource.
     *
     * @param  string $accountName The account name of the service.
     * @param  string $service     The service name of the service.
     * @param  string $resource    The name of the resource.
     *
     * @return string
     */
    protected static function generateCanonicalResource(
        $accountName,
        $service,
        $resource
    ) {
        static $serviceMap = array(
            Resources::RESOURCE_TYPE_BLOB  => 'blob',
            Resources::RESOURCE_TYPE_FILE  => 'file',
            Resources::RESOURCE_TYPE_QUEUE => 'queue',
            Resources::RESOURCE_TYPE_TABLE => 'table',
        );
        $serviceName = $serviceMap[$service];
        if (Utilities::startsWith($resource, '/')) {
            $resource = substr($resource, 1);
        }
        return sprintf('/%s/%s/%s', $serviceName, $accountName, $resource);
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Models;

use MicrosoftAzure\Storage\Common\Internal\Resources;

/**
 * Holds signed identifiers.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class SignedIdentifier
{
    private $id;
    private $accessPolicy;

    /**
     * Constructor
     *
     * @param string            $id           The id of this signed identifier.
     * @param AccessPolicy|null $accessPolicy The access policy.
     */
    public function __construct($id = '', AccessPolicy $accessPolicy = null)
    {
        $this->setId($id);
        $this->setAccessPolicy($accessPolicy);
    }

    /**
     * Gets id.
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Sets id.
     *
     * @param string $id value.
     *
     * @return void
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * Gets accessPolicy.
     *
     * @return AccessPolicy
     */
    public function getAccessPolicy()
    {
        return $this->accessPolicy;
    }

    /**
     * Sets accessPolicy.
     *
     * @param AccessPolicy|null $accessPolicy value.
     *
     * @return void
     */
    public function setAccessPolicy(AccessPolicy $accessPolicy = null)
    {
        $this->accessPolicy = $accessPolicy;
    }

    /**
     * Converts this current object to XML representation.
     *
     * @internal
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();
        $accessPolicyArray = array();
        $accessPolicyArray[Resources::XTAG_SIGNED_ID] = $this->getId();
        $accessPolicyArray[Resources::XTAG_ACCESS_POLICY] =
            $this->getAccessPolicy()->toArray();
        $array[Resources::XTAG_SIGNED_IDENTIFIER] = $accessPolicyArray;

        return $array;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Exceptions
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Exceptions;

use MicrosoftAzure\Storage\Common\Internal\Serialization\XmlSerializer;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use Psr\Http\Message\ResponseInterface;

/**
 * Fires when the response code is incorrect.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Exceptions
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2016 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ServiceException extends \LogicException
{
    private $response;
    private $errorText;
    private $errorMessage;

    /**
     * Constructor
     *
     * @param ResponseInterface $response The response received that causes the
     *                                    exception.
     *
     * @internal
     *
     * @return ServiceException
     */
    public function __construct(ResponseInterface $response)
    {
        parent::__construct(
            sprintf(
                Resources::AZURE_ERROR_MSG,
                $response->getStatusCode(),
                $response->getReasonPhrase(),
                $response->getBody()
            )
        );
        $this->code         = $response->getStatusCode();
        $this->response     = $response;
        $this->errorText    = $response->getReasonPhrase();
        $this->errorMessage = self::parseErrorMessage($response);
    }

    /**
     * Error message to be parsed.
     *
     * @param  ResponseInterface $response The response with a response body.
     *
     * @internal
     *
     * @return string
     */
    protected static function parseErrorMessage(ResponseInterface $response)
    {
        //try to parse using xml serializer, if failed, return the whole body
        //as the error message.
        $serializer = new XmlSerializer();
        $errorMessage = '';
        try {
            $internalErrors = libxml_use_internal_errors(true);
            $parsedArray = $serializer->unserialize($response->getBody());
            $messages = array();
            foreach (libxml_get_errors() as $error) {
                $messages[] = $error->message;
            }
            if (!empty($messages)) {
                throw new \Exception(
                    sprintf(Resources::ERROR_CANNOT_PARSE_XML, implode('; ', $messages))
                );
            }
            libxml_use_internal_errors($internalErrors);
            if (array_key_exists(Resources::XTAG_MESSAGE, $parsedArray)) {
                $errorMessage = $parsedArray[Resources::XTAG_MESSAGE];
            } else {
                $errorMessage = $response->getBody();
            }
        } catch (\Exception $e) {
            $errorMessage = $response->getBody();
        }
        return $errorMessage;
    }

    /**
     * Gets error text.
     *
     * @return string
     */
    public function getErrorText()
    {
        return $this->errorText;
    }

    /**
     * Gets detailed error message.
     *
     * @return string
     */
    public function getErrorMessage()
    {
        return $this->errorMessage;
    }

    /**
     * Gets the request ID of the failure.
     *
     * @return string
     */
    public function getRequestID()
    {
        $requestID = '';
        if (array_key_exists(
            Resources::X_MS_REQUEST_ID,
            $this->getResponse()->getHeaders()
        )) {
            $requestID = $this->getResponse()
                ->getHeaders()[Resources::X_MS_REQUEST_ID][0];
        }
        return $requestID;
    }

    /**
     * Gets the Date of the failure.
     *
     * @return string
     */
    public function getDate()
    {
        $date = '';
        if (array_key_exists(
            Resources::DATE,
            $this->getResponse()->getHeaders()
        )) {
            $date = $this->getResponse()
                ->getHeaders()[Resources::DATE][0];
        }
        return $date;
    }

    /**
     * Gets the response of the failue.
     *
     * @return string
     */
    public function getResponse()
    {
        return $this->response;
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\Common\Models;

use MicrosoftAzure\Storage\Common\LocationMode;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Validate;
use MicrosoftAzure\Storage\Common\Middlewares\MiddlewareStack;
use MicrosoftAzure\Storage\Common\Middlewares\IMiddleware;

/**
 * This class provides the base structure of service options, granting user to
 * send with different options for each individual API call.
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\Common\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ServiceOptions
{
    /**
     * The middlewares to be applied using the operation.
     * @internal
     */
    protected $middlewares;

    /**
     * The middleware stack used for the operation.
     * @internal
     */
    protected $middlewareStack;

    /**
     * The number of concurrency when performing concurrent requests.
     * @internal
     */
    protected $numberOfConcurrency;

    /**
     * If streamming is used for the operation.
     * @internal
     */
    protected $isStreaming;

    /**
     * The location mode of the operation.
     * @internal
     */
    protected $locationMode;

    /**
     * If to decode the content of the response body.
     * @internal
     */
    protected $decodeContent;

    /**
     * The timeout of the operation
     * @internal
     */
    protected $timeout;

    /**
     * Initialize the properties to default value.
     */
    public function __construct(ServiceOptions $options = null)
    {
        if ($options == null) {
            $this->setNumberOfConcurrency(Resources::NUMBER_OF_CONCURRENCY);
            $this->setLocationMode(LocationMode::PRIMARY_ONLY);
            $this->setIsStreaming(false);
            $this->setDecodeContent(false);
            $this->middlewares = array();
            $this->middlewareStack = null;
        } else {
            $this->setNumberOfConcurrency($options->getNumberOfConcurrency());
            $this->setLocationMode($options->getLocationMode());
            $this->setIsStreaming($options->getIsStreaming());
            $this->setDecodeContent($options->getDecodeContent());
            $this->middlewares = $options->getMiddlewares();
            $this->middlewareStack = $options->getMiddlewareStack();
        }
    }

    /**
     * Push a middleware into the middlewares.
     * @param  callable|IMiddleware $middleware middleware to be pushed.
     *
     * @return void
     */
    public function pushMiddleware($middleware)
    {
        self::validateIsMiddleware($middleware);
        $this->middlewares[] = $middleware;
    }

    /**
     * Gets the middlewares.
     *
     * @return array
     */
    public function getMiddlewares()
    {
        return $this->middlewares;
    }

    /**
     * Sets middlewares.
     *
     * @param array $middlewares value.
     *
     * @return void
     */
    public function setMiddlewares(array $middlewares)
    {
        foreach ($middlewares as $middleware) {
            self::validateIsMiddleware($middleware);
        }
        $this->middlewares = $middlewares;
    }

    /**
     * Gets the middleware stack
     *
     * @return MiddlewareStack
     */
    public function getMiddlewareStack()
    {
        return $this->middlewareStack;
    }

    /**
     * Sets the middleware stack.
     *
     * @param MiddlewareStack $middlewareStack value.
     *
     * @return void
     */
    public function setMiddlewareStack(MiddlewareStack $middlewareStack)
    {
        $this->middlewareStack = $middlewareStack;
    }

    /**
     * Gets the number of concurrency value
     *
     * @return int
     */
    public function getNumberOfConcurrency()
    {
        return $this->numberOfConcurrency;
    }

    /**
     * Sets number of concurrency.
     *
     * @param int $numberOfConcurrency value.
     *
     * @return void
     */
    public function setNumberOfConcurrency($numberOfConcurrency)
    {
        $this->numberOfConcurrency = $numberOfConcurrency;
    }

    /**
     * Gets the isStreaming value
     *
     * @return bool
     */
    public function getIsStreaming()
    {
        return $this->isStreaming;
    }

    /**
     * Sets isStreaming.
     *
     * @param bool $isStreaming value.
     *
     * @return void
     */
    public function setIsStreaming($isStreaming)
    {
        $this->isStreaming = $isStreaming;
    }

    /**
     * Gets the locationMode value
     *
     * @return string
     */
    public function getLocationMode()
    {
        return $this->locationMode;
    }

    /**
     * Sets locationMode.
     *
     * @param string $locationMode value.
     *
     * @return void
     */
    public function setLocationMode($locationMode)
    {
        $this->locationMode = $locationMode;
    }

    /**
     * Gets the decodeContent value
     *
     * @return bool
     */
    public function getDecodeContent()
    {
        return $this->decodeContent;
    }

    /**
     * Sets decodeContent.
     *
     * @param bool $decodeContent value.
     *
     * @return void
     */
    public function setDecodeContent($decodeContent)
    {
        $this->decodeContent = $decodeContent;
    }

    /**
     * Gets the timeout value
     *
     * @return string
     */
    public function getTimeout()
    {
        return $this->timeout;
    }

    /**
     * Sets timeout.
     *
     * @param string $timeout value.
     *
     * @return void
     */
    public function setTimeout($timeout)
    {
        $this->timeout = $timeout;
    }

    /**
     * Generate request options using the input options and saved properties.
     *
     * @param  array  $options The options to be merged for the request options.
     *
     * @return array
     */
    public function generateRequestOptions(array $options)
    {
        $result = array();

        return $result;
    }

    /**
     * Validate if the given middleware is of callable or IMiddleware.
     *
     * @param  void $middleware the middleware to be validated.
     *
     * @return void
     */
    private static function validateIsMiddleware($middleware)
    {
        if (!(is_callable($middleware) || $middleware instanceof IMiddleware)) {
            Validate::isTrue(
                false,
                Resources::INVALID_TYPE_MSG . 'callable or IMiddleware'
            );
        }
    }
}


<?php

/**
 * LICENSE: The MIT License (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://github.com/azure/azure-storage-php/LICENSE
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * PHP version 5
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */

namespace MicrosoftAzure\Storage\File\Models;

use MicrosoftAzure\Storage\Common\Internal\Utilities;
use MicrosoftAzure\Storage\File\Internal\FileResources as Resources;

/**
 * Holds share properties fields
 *
 * @category  Microsoft
 * @package   MicrosoftAzure\Storage\File\Models
 * @author    Azure Storage PHP SDK <dmsh@microsoft.com>
 * @copyright 2017 Microsoft Corporation
 * @license   https://github.com/azure/azure-storage-php/LICENSE
 * @link      https://github.com/azure/azure-storage-php
 */
class ShareProperties
{
    private $lastModified;
    private $etag;
    private $quota;

    /**
     * Creates an instance with given response array.
     *
     * @param  array  $parsedResponse The response array.
     *
     * @return ShareProperties
     */
    public static function create(array $parsedResponse)
    {
        $result = new ShareProperties();
        $date   = $parsedResponse[Resources::QP_LAST_MODIFIED];
        $date   = Utilities::rfc1123ToDateTime($date);
        $result->setLastModified($date);
        $result->setETag($parsedResponse[Resources::QP_ETAG]);
        $result->setQuota($parsedResponse[Resources::QP_QUOTA]);
        return $result;
    }

    /**
     * Gets share lastModified.
     *
     * @return \DateTime
     */
    public function getLastModified()
    {
        return $this->lastModified;
    }

    /**
     * Sets share lastModified.
     *
     * @param \DateTime $lastModified value.
     *
     * @return void
     */
    public function setLastModified(\DateTime $lastModified)
    {
        $this->lastModified = $lastModified;
    }

    /**
     * Gets share etag.
     *
     * @return string
     */
    public function getETag()
    {
        return $this->etag;
    }

    /**
     * Sets share etag.
     *
     * @param string $etag value.
     *
     * @return void
     */
    public function setETag($etag)
    {
        $this->etag = $etag;
    }

    /**
     * Gets share quota.
     *
     * @return string
     */
    public function getQuota()
    {
        return $this->quota;
    }

    /**
     * Sets share quota.
     *
     * @param string $quota value.
     *
     * @return void
     */
    public function setQuota($quota)
    {
        $this->quota = $quota;
    }
}