Full Code of kleiram/transmission-php for AI

master 3a9da015251a cached
38 files
112.0 KB
27.9k tokens
362 symbols
1 requests
Download .txt
Repository: kleiram/transmission-php
Branch: master
Commit: 3a9da015251a
Files: 38
Total size: 112.0 KB

Directory structure:
gitextract_kh88jjkg/

├── .gitignore
├── .travis.yml
├── CHANGELOG
├── LICENSE
├── README.md
├── composer.json
├── examples/
│   └── queue.php
├── lib/
│   └── Transmission/
│       ├── Client.php
│       ├── Model/
│       │   ├── AbstractModel.php
│       │   ├── File.php
│       │   ├── FreeSpace.php
│       │   ├── ModelInterface.php
│       │   ├── Peer.php
│       │   ├── Session.php
│       │   ├── Stats/
│       │   │   ├── Session.php
│       │   │   └── Stats.php
│       │   ├── Status.php
│       │   ├── Torrent.php
│       │   ├── Tracker.php
│       │   └── TrackerStats.php
│       ├── Transmission.php
│       └── Util/
│           ├── PropertyMapper.php
│           └── ResponseValidator.php
├── phpunit.xml.dist
└── tests/
    ├── Transmission/
    │   ├── Mock/
    │   │   └── Model.php
    │   └── Tests/
    │       ├── ClientTest.php
    │       ├── Model/
    │       │   ├── AbstractModelTest.php
    │       │   ├── FileTest.php
    │       │   ├── PeerTest.php
    │       │   ├── SessionTest.php
    │       │   ├── StatusTest.php
    │       │   ├── TorrentTest.php
    │       │   ├── TrackerStatsTest.php
    │       │   └── TrackerTest.php
    │       ├── TransmissionTest.php
    │       └── Util/
    │           ├── PropertyMapperTest.php
    │           └── ResponseValidatorTest.php
    └── bootstrap.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
vendor/
composer.lock
composer.phar
phpunit.xml


================================================
FILE: .travis.yml
================================================
language: php

php: [5.3, 5.4, 5.5]

before_script:
    - composer install --dev --prefer-source

script:
    phpunit --coverage-text


================================================
FILE: CHANGELOG
================================================
Version     Changes

0.1.0       - Initial release

0.2.0       - Rewrote the entire public API

0.3.0       - Added support for authentication

0.4.0       - The library now requires at least PHP 5.3.2
            - Added support for getting files downloaded by torrent
            - Added support for getting trackers used by a torrent
            - Added support for getting peers connected to
            - The torrent now contains:
                * Whether it is finished
                * The up- and download rate (in bytes/s)
                * The size of the download (when completed)
                * The ETA of the download
                * The percentage of the download completed
            - Made the authentication more flexible
            - The client now sends an User-Agent header with each request
            - Added support for starting, stopping, veryfing and
              requesting a reannounce of torrents

0.5.0       - Fix a bug in the authentication/authorization mechanism
            - A whole lot of other stuff including management of the
              Transmission session (setting global download speed limit
              and toggling the speed limit among others).


================================================
FILE: LICENSE
================================================
Copyright (c) 2014, Ramon Kleiss <ramonkleiss@gmail.com
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.


================================================
FILE: README.md
================================================
# PHP Transmission API

[![Build Status](https://travis-ci.org/kleiram/transmission-php.png)](https://travis-ci.org/kleiram/transmission-php)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/kleiram/transmission-php/badges/quality-score.png?s=21ff8ce00b8b381734360405aeaf2b48875a8137)](https://scrutinizer-ci.com/g/kleiram/transmission-php/)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/4df441fd-864e-4491-a226-b35b79911af8/mini.png)](https://insight.sensiolabs.com/projects/4df441fd-864e-4491-a226-b35b79911af8)

This library provides an interface to the [Transmission](http://transmissionbt.com)
bit-torrent downloader. It provides means to get and remove torrents from
the downloader as well as adding new torrents to the download queue.

## Installation

Installation is easy using [Composer](https://getcomposer.org):

```json
{
    "require": {
        "kleiram/transmission-php": "dev-master"
    }
}
```

## Usage

Using the library is as easy as installing it:

```php
<?php
use Transmission\Transmission;

$transmission = new Transmission();

// Getting all the torrents currently in the download queue
$torrents = $transmission->all();

// Getting a specific torrent from the download queue
$torrent = $transmission->get(1);

// (you can also get a torrent by the hash of the torrent)
$torrent = $transmission->get(/* torrent hash */);

// Adding a torrent to the download queue
$torrent = $transmission->add(/* path to torrent */);

// Removing a torrent from the download queue
$torrent = $transmission->get(1);
$transmission->remove($torrent);

// Or if you want to delete all local data too
$transmission->remove($torrent, true);

// You can also get the Trackers that the torrent currently uses
// These are instances of the Transmission\Model\Tracker class
$trackers = $torrent->getTrackers();

// You can also get the Trackers statistics and info that the torrent currently has
// These are instances of the Transmission\Model\trackerStats class
$trackerStats = $torrent->getTrackerStats();

// To get the start date/time of the torrent in UNIX Timestamp format
$startTime = $torrent -> getStartDate();

// To get the number of peers connected
$connectedPeers = $torrent -> getPeersConnected();

// Getting the files downloaded by the torrent are available too
// These are instances of Transmission\Model\File
$files = $torrent->getFiles();

// You can start, stop, verify the torrent and ask the tracker for
// more peers to connect to
$transmission->stop($torrent);
$transmission->start($torrent);
$transmission->start($torrent, true); // Pass true if you want to start the torrent immediatly
$transmission->verify($torrent);
$transmission->reannounce($torrent);
```

To find out which information is contained by the torrent, check
[`Transmission\Model\Torrent`](https://github.com/kleiram/transmission-php/tree/master/lib/Transmission/Model/Torrent.php).

By default, the library will try to connect to `localhost:9091`. If you want to
connect to another host or post you can pass those to the constructor of the
`Transmission` class:

```php
<?php
use Transmission\Transmission;

$transmission = new Transmission('example.com', 33);

$torrents = $transmission->all();
$torrent  = $transmission->get(1);
$torrent  = $transmission->add(/* path to torrent */);

// When you already have a torrent, you don't have to pass the client again
$torrent->delete();
```

It is also possible to pass the torrent data directly instead of using a file
but the metadata must be base64-encoded:

```php
<?php
$torrent = $transmission->add(/* base64-encoded metainfo */, true);
```

If the Transmission server is secured with a username and password you can
authenticate using the `Client` class:

```php
<?php
use Transmission\Client;
use Transmission\Transmission;

$client = new Client();
$client->authenticate('username', 'password');
$transmission = new Transmission();
$transmission->setClient($client);
```

Additionally, you can control the actual Transmission setting. This means
you can modify the global download limit or change the download directory:

```php
<?php
use Transmission\Transmission;

$transmission = new Transmission();
$session = $transmission->getSession();

$session->setDownloadDir('/home/foo/downloads/complete');
$session->setIncompleteDir('/home/foo/downloads/incomplete');
$session->setIncompleteDirEnabled(true);
$session->save();
```

## Testing

Testing is done using [PHPUnit](https://github.com/sebastianbergmann/phpunit). To
test the application, you have to install the dependencies using Composer before
running the tests:

```bash
$ curl -s https://getcomposer.org/installer | php
$ php composer.phar install
$ phpunit --coverage-text
```

## Integration into frameworks

Currently, there's a [Symfony](https://github.com/chellem/TransmissionBundle)
bundle in development which allows you to easily use this library within Symfony.

## Changelog

    Version     Changes

    0.1.0       - Initial release

    0.2.0       - Rewrote the entire public API

    0.3.0       - Added support for authentication

    0.4.0       - The library now requires at least PHP 5.3.2
                - Added support for getting files downloaded by torrent
                - Added support for getting trackers used by a torrent
                - Added support for getting peers connected to
                - The torrent now contains:
                    * Whether it is finished
                    * The up- and download rate (in bytes/s)
                    * The size of the download (when completed)
                    * The ETA of the download
                    * The percentage of the download completed
                - Made the authentication more flexible
                - The client now sends an User-Agent header with each request
                - Added support for starting, stopping, veryfing and
                  requesting a reannounce of torrents

    0.5.0       - Fix a bug in the authentication/authorization mechanism
                - A whole lot of other stuff including management of the
                  Transmission session (setting global download speed limit
                  and toggling the speed limit among others).

## License

This library is licensed under the BSD 2-clause license.

    Copyright (c) 2014, Ramon Kleiss <ramonkleiss@gmail.com>
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are those
    of the authors and should not be interpreted as representing official policies,
    either expressed or implied, of the FreeBSD Project.


================================================
FILE: composer.json
================================================
{
    "name": "kleiram/transmission-php",
    "description": "PHP Transmission client",
    "keywords": ["transmission", "torrent", "download"],
    "type": "library",
    "license": "BSD-2-Clause",
    "authors": [
        {
            "name": "Ramon Kleiss",
            "email": "ramon@cubilon.nl"
        }
    ],
    "require": {
        "kriswallsmith/buzz": ">=0.9",
        "symfony/property-access": ">=2.2.1"
    },
    "autoload": {
        "psr-0": {
            "Transmission": "lib/"
        }
    }
}


================================================
FILE: examples/queue.php
================================================
<?php
require_once __DIR__.'/../vendor/autoload.php';

$transmission = new Transmission\Transmission();
$queue = $transmission->all();

echo "Downloading to: {$transmission->getSession()->getDownloadDir()}\n";

foreach ($queue as $torrent) {
    echo "{$torrent->getName()}";

    if ($torrent->isFinished()) {
        echo ": done\n";
    } else {
        if ($torrent->isDownloading()) {
            echo ": {$torrent->getPercentDone()}% ";
            echo "(eta: ". gmdate("H:i:s", $torrent->getEta()) .")\n";
        } else {
            echo ": paused\n";
        }
    }
}


================================================
FILE: lib/Transmission/Client.php
================================================
<?php
namespace Transmission;

use Buzz\Message\Request;
use Buzz\Message\Response;
use Buzz\Client\Curl;
use Buzz\Client\ClientInterface;

/**
 * The Client class is used to make API calls to the Transmission server
 *
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class Client
{
    /**
     * @var string
     */
    const DEFAULT_HOST = 'localhost';

    /**
     * @var integer
     */
    const DEFAULT_PORT = 9091;

    /**
     * @var string
     */
    const DEFAULT_PATH = '/transmission/rpc';

    /**
     * @var string
     */
    const TOKEN_HEADER = 'X-Transmission-Session-Id';

    /**
     * @var string
     */
    protected $host = self::DEFAULT_HOST;

    /**
     * @var integer
     */
    protected $port = self::DEFAULT_PORT;

    /**
     * @var string
     */
    protected $path = self::DEFAULT_PATH;

    /**
     * @var string
     */
    protected $token;

    /**
     * @var ClientInterface
     */
    protected $client;

    /**
     * @var string
     */
    protected $auth;

    /**
     * Constructor
     *
     * @param string  $host The hostname of the Transmission server
     * @param integer $port The port the Transmission server is listening on
     * @param string  $path The path to Transmission server rpc api
     */
    public function __construct($host = null, $port = null, $path = null)
    {
        $this->token    = null;
        $this->client   = new Curl();

        if ($host) $this->setHost($host);
        if ($port) $this->setPort($port);
        if ($path) $this->setPath($path);
    }

    /**
     * Authenticate against the Transmission server
     *
     * @param string $username
     * @param string $password
     */
    public function authenticate($username, $password)
    {
        $this->auth = base64_encode($username .':'. $password);
    }

    /**
     * Make an API call
     *
     * @param  string           $method
     * @param  array            $arguments
     * @return \stdClass
     * @throws \RuntimeException
     */
    public function call($method, array $arguments)
    {
        list($request, $response) = $this->compose($method, $arguments);

        try {
            $this->getClient()->send($request, $response);
        } catch (\Exception $e) {
            throw new \RuntimeException(
                'Could not connect to Transmission',
                0,
                $e
            );
        }

        return $this->validateResponse($response, $method, $arguments);
    }

    /**
     * Get the URL used to connect to Transmission
     *
     * @return string
     */
    public function getUrl()
    {
        return sprintf(
            'http://%s:%d',
            $this->getHost(),
            $this->getPort()
        );
    }

    /**
     * Set the hostname of the Transmission server
     *
     * @param string $host
     */
    public function setHost($host)
    {
        $this->host = (string) $host;
    }

    /**
     * Get the hostname of the Transmission server
     *
     * @return string
     */
    public function getHost()
    {
        return $this->host;
    }

    /**
     * Set the port the Transmission server is listening on
     *
     * @param integer $port
     */
    public function setPort($port)
    {
        $this->port = (integer) $port;
    }

    /**
     * Get the port the Transmission server is listening on
     *
     * @return integer
     */
    public function getPort()
    {
        return $this->port;
    }

    /**
     * Set the path to Transmission server rpc api
     *
     * @param string $path
     */
    public function setPath($path)
    {
        return $this->path = (string) $path;
    }

    /**
     * Get the path to Transmission server rpc api
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Set the CSRF-token of the Transmission client
     *
     * @param string $token
     */
    public function setToken($token)
    {
        $this->token = (string) $token;
    }

    /**
     * Get the CSRF-token for the Transmission client
     *
     * @return string
     */
    public function getToken()
    {
        return $this->token;
    }

    /**
     * Set the Buzz client used to connect to Transmission
     *
     * @param ClientInterface $client
     */
    public function setClient(ClientInterface $client)
    {
        $this->client = $client;
    }

    /**
     * Get the Buzz client used to connect to Transmission
     *
     * @return ClientInterface
     */
    public function getClient()
    {
        return $this->client;
    }

    /**
     * @param string $method
     * @param array $arguments
     * @return array|Request[]|Response[]
     */
    protected function compose($method, $arguments)
    {
        $request = new Request('POST', $this->getPath(), $this->getUrl());
        $request->addHeader(sprintf('%s: %s', self::TOKEN_HEADER, $this->getToken()));
        $request->setContent(json_encode(array(
            'method'    => $method,
            'arguments' => $arguments
        )));

        if (is_string($this->auth)) {
            $request->addHeader(sprintf('Authorization: Basic %s', $this->auth));
        }

        return array($request, new Response());
    }

    /**
     * @param  Response $response
     * @param  string                $method
     * @param  array                 $arguments
     * @return \stdClass
     * @throws \RuntimeException
     */
    protected function validateResponse($response, $method, $arguments)
    {
        if (!in_array($response->getStatusCode(), array(200, 401, 409))) {
            throw new \RuntimeException('Unexpected response received from Transmission');
        }

        if ($response->getStatusCode() == 401) {
            throw new \RuntimeException('Access to Transmission requires authentication');
        }

        if ($response->getStatusCode() == 409) {
            $this->setToken($response->getHeader(self::TOKEN_HEADER));

            return $this->call($method, $arguments);
        }

        return json_decode($response->getContent());
    }
}


================================================
FILE: lib/Transmission/Model/AbstractModel.php
================================================
<?php
namespace Transmission\Model;

use Transmission\Client;
use Transmission\Util\ResponseValidator;

/**
 * Base class for Transmission models
 *
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
abstract class AbstractModel implements ModelInterface
{
    /**
     * @var Client
     */
    protected $client;

    /**
     * Constructor
     *
     * @param Client $client
     */
    public function __construct(Client $client = null)
    {
        $this->client = $client;
    }

    /**
     * @param Client $client
     */
    public function setClient(Client $client)
    {
        $this->client = $client;
    }

    /**
     * @return Client
     */
    public function getClient()
    {
        return $this->client;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array();
    }

    /**
     * @param string $method
     * @param array  $arguments
     */
    protected function call($method, $arguments)
    {
        if ($this->client) {
            ResponseValidator::validate(
                $method,
                $this->client->call($method, $arguments)
            );
        }
    }
}


================================================
FILE: lib/Transmission/Model/File.php
================================================
<?php
namespace Transmission\Model;

/**
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class File extends AbstractModel
{
    /**
     * @var string
     */
    protected $name;

    /**
     * @var integer
     */
    protected $size;

    /**
     * @var integer
     */
    protected $completed;

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = (string) $name;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param integer $size
     */
    public function setSize($size)
    {
        $this->size = (integer) $size;
    }

    /**
     * @return integer
     */
    public function getSize()
    {
        return $this->size;
    }

    /**
     * @param integer $size
     */
    public function setCompleted($completed)
    {
        $this->completed = (integer) $completed;
    }

    /**
     * @return integer
     */
    public function getCompleted()
    {
        return $this->completed;
    }

    /**
     * @return boolean
     */
    public function isDone()
    {
        return $this->getSize() == $this->getCompleted();
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'name' => 'name',
            'length' => 'size',
            'bytesCompleted' => 'completed'
        );
    }

    public function __toString()
    {
        return $this->name;
    }
}


================================================
FILE: lib/Transmission/Model/FreeSpace.php
================================================
<?php
namespace Transmission\Model;

/**
 * @author Joysen Chellem
 */
class FreeSpace extends AbstractModel
{
    /**
     * @var string
     */
    private $path;

    /**
     * @var integer
     */
    private $size;

    /**
     * Gets the value of path.
     *
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Sets the value of path.
     *
     * @param string $path the path
     */
    public function setPath($path)
    {
        $this->path = $path;
    }

    /**
     * Gets the value of size.
     *
     * @return integer
     */
    public function getSize()
    {
        return $this->size;
    }

    /**
     * Sets the value of size.
     *
     * @param integer $size the size
     */
    public function setSize($size)
    {
        $this->size = $size;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'path' => 'path',
            'size-bytes' => 'size',
        );
    }
}


================================================
FILE: lib/Transmission/Model/ModelInterface.php
================================================
<?php
namespace Transmission\Model;

/**
 * The interface Transmission models must implement
 *
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
interface ModelInterface
{
    /**
     * Get the mapping of the model
     *
     * @return array
     */
    public static function getMapping();
}


================================================
FILE: lib/Transmission/Model/Peer.php
================================================
<?php
namespace Transmission\Model;

/**
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class Peer extends AbstractModel
{
    /**
     * @var string
     */
    protected $address;

    /**
     * @var integer
     */
    protected $port;

    /**
     * @var string
     */
    protected $clientName;

    /**
     * @var boolean
     */
    protected $clientChoked;

    /**
     * @var boolean
     */
    protected $clientInterested;

    /**
     * @var boolean
     */
    protected $downloading;

    /**
     * @var boolean
     */
    protected $encrypted;

    /**
     * @var boolean
     */
    protected $incoming;

    /**
     * @var boolean
     */
    protected $uploading;

    /**
     * @var boolean
     */
    protected $utp;

    /**
     * @var boolean
     */
    protected $peerChoked;

    /**
     * @var boolean
     */
    protected $peerInterested;

    /**
     * @var double
     */
    protected $progress;

    /**
     * @var integer
     */
    protected $uploadRate;

    /**
     * @var integer
     */
    protected $downloadRate;

    /**
     * @param string $address
     */
    public function setAddress($address)
    {
        $this->address = (string) $address;
    }

    /**
     * @return string
     */
    public function getAddress()
    {
        return $this->address;
    }

    /**
     * @param integer $port
     */
    public function setPort($port)
    {
        $this->port = (integer) $port;
    }

    /**
     * @return integer
     */
    public function getPort()
    {
        return $this->port;
    }

    /**
     * @param string $clientName
     */
    public function setClientName($clientName)
    {
        $this->clientName = (string) $clientName;
    }

    /**
     * @return string
     */
    public function getClientName()
    {
        return $this->clientName;
    }

    /**
     * @param boolean $choked
     */
    public function setClientChoked($choked)
    {
        $this->clientChoked = (boolean) $choked;
    }

    /**
     * @return boolean
     */
    public function isClientChoked()
    {
        return $this->clientChoked;
    }

    /**
     * @param boolean $interested
     */
    public function setClientInterested($interested)
    {
        $this->clientInterested = (boolean) $interested;
    }

    /**
     * @return boolean
     */
    public function isClientInterested()
    {
        return $this->clientInterested;
    }

    /**
     * @param boolean $downloading
     */
    public function setDownloading($downloading)
    {
        $this->downloading = (boolean) $downloading;
    }

    /**
     * @return boolean
     */
    public function isDownloading()
    {
        return $this->downloading;
    }

    /**
     * @param boolean $encrypted
     */
    public function setEncrypted($encrypted)
    {
        $this->encrypted = (boolean) $encrypted;
    }

    /**
     * @return boolean
     */
    public function isEncrypted()
    {
        return $this->encrypted;
    }

    /**
     * @param boolean $incoming
     */
    public function setIncoming($incoming)
    {
        $this->incoming = (boolean) $incoming;
    }

    /**
     * @return boolean
     */
    public function isIncoming()
    {
        return $this->incoming;
    }

    /**
     * @param boolean $uploading
     */
    public function setUploading($uploading)
    {
        $this->uploading = (boolean) $uploading;
    }

    /**
     * @return boolean
     */
    public function isUploading()
    {
        return $this->uploading;
    }

    /**
     * @param boolean $utp
     */
    public function setUtp($utp)
    {
        $this->utp = (boolean) $utp;
    }

    /**
     * @return boolean
     */
    public function isUtp()
    {
        return $this->utp;
    }

    /**
     * @param boolean $choked
     */
    public function setPeerChoked($choked)
    {
        $this->peerChoked = (boolean) $choked;
    }

    /**
     * @return boolean
     */
    public function isPeerChoked()
    {
        return $this->peerChoked;
    }

    /**
     * @param boolean $interested
     */
    public function setPeerInterested($interested)
    {
        $this->peerInterested = (boolean) $interested;
    }

    /**
     * @return boolean
     */
    public function isPeerInterested()
    {
        return $this->peerInterested;
    }

    /**
     * @param double $progress
     */
    public function setProgress($progress)
    {
        $this->progress = (double) $progress;
    }

    /**
     * @return double
     */
    public function getProgress()
    {
        return $this->progress;
    }

    /**
     * @param integer $rate
     */
    public function setUploadRate($rate)
    {
        $this->uploadRate = (integer) $rate;
    }

    /**
     * @return integer
     */
    public function getUploadRate()
    {
        return $this->uploadRate;
    }

    /**
     * @param integer $rate
     */
    public function setDownloadRate($rate)
    {
        $this->downloadRate = (integer) $rate;
    }

    /**
     * @return integer
     */
    public function getDownloadRate()
    {
        return $this->downloadRate;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'address' => 'address',
            'port' => 'port',
            'clientName' => 'clientName',
            'clientIsChoked' => 'clientChoked',
            'clientIsInterested' => 'clientInterested',
            'isDownloadingFrom' => 'downloading',
            'isEncrypted' => 'encrypted',
            'isIncoming' => 'incoming',
            'isUploadingTo' => 'uploading',
            'isUTP' => 'utp',
            'peerIsChoked' => 'peerChoked',
            'peerIsInterested' => 'peerInterested',
            'progress' => 'progress',
            'rateToClient' => 'uploadRate',
            'rateFromClient' => 'downloadRate'
        );
    }
}


================================================
FILE: lib/Transmission/Model/Session.php
================================================
<?php
namespace Transmission\Model;

use Transmission\Util\ResponseValidator;

/**
 * @author Joysen Chellem
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class Session extends AbstractModel
{
    /**
     * @var integer
     */
    protected $altSpeedDown;

    /**
     * @var boolean
     */
    protected $altSpeedEnabled;

    /**
     * @var string
     */
    protected $downloadDir;

    /**
     * @var boolean
     */
    protected $downloadQueueEnabled;

    /**
     * @var integer
     */
    protected $downloadQueueSize;

    /**
     * @var string
     */
    protected $incompleteDir;

    /**
     * @var boolean
     */
    protected $incompleteDirEnabled;

    /**
     * @var string
     */
    protected $torrentDoneScript;

    /**
     * @var boolean
     */
    protected $torrentDoneScriptEnabled;

    /**
     * @var double
     */
    protected $seedRatioLimit;

    /**
     * @var boolean
     */
    protected $seedRatioLimited;

    /**
     * @var integer
     */
    protected $seedQueueSize;

    /**
     * @var boolean
     */
    protected $seedQueueEnabled;

    /**
     * @var integer
     */
    protected $downloadSpeedLimit;

    /**
     * @var boolean
     */
    protected $downloadSpeedLimitEnabled;
    
    /**
     * @var integer
     */
    protected $uploadSpeedLimit;

    /**
     * @var boolean
     */
    protected $uploadSpeedLimitEnabled;

    /**
     * @param integer $speed
     */
    public function setAltSpeedDown($speed)
    {
        $this->altSpeedDown = (integer) $speed;
    }

    /**
     * @return integer
     */
    public function getAltSpeedDown()
    {
        return $this->altSpeedDown;
    }

    /**
     * @param boolean $enabled
     */
    public function setAltSpeedEnabled($enabled)
    {
        $this->altSpeedEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isAltSpeedEnabled()
    {
        return $this->altSpeedEnabled;
    }

    /**
     * @param string $downloadDir
     */
    public function setDownloadDir($downloadDir)
    {
        $this->downloadDir = (string) $downloadDir;
    }

    /**
     * @return string
     */
    public function getDownloadDir()
    {
        return $this->downloadDir;
    }

    /**
     * @param boolean $enabled
     */
    public function setDownloadQueueEnabled($enabled)
    {
        $this->downloadQueueEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isDownloadQueueEnabled()
    {
        return $this->downloadQueueEnabled;
    }

    /**
     * @param integer $size
     */
    public function setDownloadQueueSize($size)
    {
        $this->downloadQueueSize = (integer) $size;
    }

    /**
     * @return integer
     */
    public function getDownloadQueueSize()
    {
        return $this->downloadQueueSize;
    }

    /**
     * @param string $directory
     */
    public function setIncompleteDir($directory)
    {
        $this->incompleteDir = (string) $directory;
    }

    /**
     * @return string
     */
    public function getIncompleteDir()
    {
        return $this->incompleteDir;
    }

    /**
     * @param boolean $enabled
     */
    public function setIncompleteDirEnabled($enabled)
    {
        $this->incompleteDirEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isIncompleteDirEnabled()
    {
        return $this->incompleteDirEnabled;
    }

    /**
     * @param string $filename
     */
    public function setTorrentDoneScript($filename)
    {
        $this->torrentDoneScript = (string) $filename;
    }

    /**
     * @return string
     */
    public function getTorrentDoneScript()
    {
        return $this->torrentDoneScript;
    }

    /**
     * @param boolean $enabled
     */
    public function setTorrentDoneScriptEnabled($enabled)
    {
        $this->torrentDoneScriptEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isTorrentDoneScriptEnabled()
    {
        return $this->torrentDoneScriptEnabled;
    }

    /**
     * @param double $limit
     */
    public function setSeedRatioLimit($limit)
    {
        $this->seedRatioLimit = (double) $limit;
    }

    /**
     * @return double
     */
    public function getSeedRatioLimit()
    {
        return $this->seedRatioLimit;
    }

    /**
     * @param boolean $limited
     */
    public function setSeedRatioLimited($limited)
    {
        $this->seedRatioLimited = (boolean) $limited;
    }

    /**
     * @return boolean
     */
    public function isSeedRatioLimited()
    {
        return $this->seedRatioLimited;
    }

    /**
     * @param integer $size
     */
    public function setSeedQueueSize($size)
    {
        $this->seedQueueSize = (integer) $size;
    }

    /**
     * @return integer
     */
    public function getSeedQueueSize()
    {
        return $this->seedQueueSize;
    }

    /**
     * @param boolean $enabled
     */
    public function setSeedQueueEnabled($enabled)
    {
        $this->seedQueueEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isSeedQueueEnabled()
    {
        return $this->seedQueueEnabled;
    }

    /**
     * @param integer $limit
     */
    public function setDownloadSpeedLimit($limit)
    {
        $this->downloadSpeedLimit = (integer) $limit;
    }

    /**
     * @return integer
     */
    public function getDownloadSpeedLimit()
    {
        return $this->downloadSpeedLimit;
    }

    /**
     * @param boolean $enabled
     */
    public function setDownloadSpeedLimitEnabled($enabled)
    {
        $this->downloadSpeedLimitEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isDownloadSpeedLimitEnabled()
    {
        return $this->downloadSpeedLimitEnabled;
    }

    /**
     * @param integer $limit
     */
    public function setUploadSpeedLimit($limit)
    {
        $this->uploadSpeedLimit = (integer) $limit;
    }

    /**
     * @return integer
     */
    public function getUploadSpeedLimit()
    {
        return $this->uploadSpeedLimit;
    }

    /**
     * @param boolean $enabled
     */
    public function setUploadSpeedLimitEnabled($enabled)
    {
        $this->uploadSpeedLimitEnabled = (boolean) $enabled;
    }

    /**
     * @return boolean
     */
    public function isUploadSpeedLimitEnabled()
    {
        return $this->uploadSpeedLimitEnabled;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'alt-speed-down' => 'altSpeedDown',
            'alt-speed-enabled' => 'altSpeedEnabled',
            'download-dir' => 'downloadDir',
            'download-queue-enabled' => 'downloadQueueEnabled',
            'download-queue-size' => 'downloadQueueSize',
            'incomplete-dir' => 'incompleteDir',
            'incomplete-dir-enabled' => 'incompleteDirEnabled',
            'script-torrent-done-filename' => 'torrentDoneScript',
            'script-torrent-done-enabled' => 'torrentDoneScriptEnabled',
            'seedRatioLimit' => 'seedRatioLimit',
            'seedRatioLimited' => 'seedRatioLimited',
            'seed-queue-size' => 'seedQueueSize',
            'seed-queue-enabled' => 'seedQueueEnabled',
            'speed-limit-down' => 'downloadSpeedLimit',
            'speed-limit-down-enabled' => 'downloadSpeedLimitEnabled',
            'speed-limit-up' => 'uploadSpeedLimit',
            'speed-limit-up-enabled' => 'uploadSpeedLimitEnabled',
        );
    }

    public function save()
    {
        $arguments = array();

        foreach ($this->getMapping() as $key => $value) {
            $arguments[$key] = $this->{$value};
        }

        if (!empty($arguments) && $this->getClient()) {
            ResponseValidator::validate(
                'session-set',
                $this->getClient()->call('session-set', $arguments)
            );
        }
    }
}


================================================
FILE: lib/Transmission/Model/Stats/Session.php
================================================
<?php
namespace Transmission\Model\Stats;

use Transmission\Model\AbstractModel;

/**
 * @author Joysen Chellem
 */
class Session extends AbstractModel
{
    /**
     * @var integer
     */
    private $activeTorrentCount;

    /**
     * @var integer
     */
    private $downloadSpeed;

    /**
     * @var integer
     */
    private $pausedTorrentCount;

    /**
     * @var integer
     */
    private $torrentCount;

    /**
     * @var integer
     */
    private $uploadSpeed;

    /**
     * @var Stats
     */
    private $cumulative;

    /**
     * @var Stats
     */
    private $current;

    /**
     * Gets the value of activeTorrentCount.
     *
     * @return integer
     */
    public function getActiveTorrentCount()
    {
        return $this->activeTorrentCount;
    }

    /**
     * Sets the value of activeTorrentCount.
     *
     * @param integer $activeTorrentCount the active torrent count
     */
    public function setActiveTorrentCount($activeTorrentCount)
    {
        $this->activeTorrentCount = $activeTorrentCount;
    }

    /**
     * Gets the value of downloadSpeed.
     *
     * @return integer
     */
    public function getDownloadSpeed()
    {
        return $this->downloadSpeed;
    }

    /**
     * Sets the value of downloadSpeed.
     *
     * @param integer $downloadSpeed the download speed
     */
    public function setDownloadSpeed($downloadSpeed)
    {
        $this->downloadSpeed = $downloadSpeed;
    }

    /**
     * Gets the value of pausedTorrentCount.
     *
     * @return integer
     */
    public function getPausedTorrentCount()
    {
        return $this->pausedTorrentCount;
    }

    /**
     * Sets the value of pausedTorrentCount.
     *
     * @param integer $pausedTorrentCount the paused torrent count
     */
    public function setPausedTorrentCount($pausedTorrentCount)
    {
        $this->pausedTorrentCount = $pausedTorrentCount;
    }

    /**
     * Gets the value of torrentCount.
     *
     * @return integer
     */
    public function getTorrentCount()
    {
        return $this->torrentCount;
    }

    /**
     * Sets the value of torrentCount.
     *
     * @param integer $torrentCount the torrent count
     */
    public function setTorrentCount($torrentCount)
    {
        $this->torrentCount = $torrentCount;
    }

    /**
     * Gets the value of uploadSpeed.
     *
     * @return integer
     */
    public function getUploadSpeed()
    {
        return $this->uploadSpeed;
    }

    /**
     * Sets the value of uploadSpeed.
     *
     * @param integer $uploadSpeed the upload speed
     */
    public function setUploadSpeed($uploadSpeed)
    {
        $this->uploadSpeed = $uploadSpeed;
    }

    /**
     * Gets the value of cumulative.
     *
     * @return Stats
     */
    public function getCumulative()
    {
        return $this->cumulative;
    }

    /**
     * Sets the value of cumulative.
     *
     * @param Stats $cumulative the cumulative
     */
    public function setCumulative(Stats $cumulative)
    {
        $this->cumulative = $cumulative;
    }

    /**
     * Gets the value of current.
     *
     * @return Stats
     */
    public function getCurrent()
    {
        return $this->current;
    }

    /**
     * Sets the value of current.
     *
     * @param Stats $current the current
     */
    public function setCurrent(Stats $current)
    {
        $this->current = $current;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'activeTorrentCount' => 'activeTorrentCount',
            'downloadSpeed' => 'downloadSpeed',
            'pausedTorrentCount' => 'pausedTorrentCount',
            'torrentCount' => 'torrentCount',
            'uploadSpeed' => 'uploadSpeed',
            'cumulative-stats'=>'cumulative',
            'current-stats' => 'current',
        );
    }
}


================================================
FILE: lib/Transmission/Model/Stats/Stats.php
================================================
<?php

namespace Transmission\Model\Stats;

use Transmission\Model\ModelInterface;

/**
 * @author Joysen Chellem
 */
class Stats implements ModelInterface
{
    /**
     * @var integer
     */
    protected $downloadedBytes;

    /**
     * @var integer
     */
    protected $filesAdded;

    /**
     * @var integer
     */
    protected $secondsActive;

    /**
     * @var integer
     */
    protected $sessionCount;

    /**
     * @var integer
     */
    protected $uploadedBytes;

    /**
     * Gets the value of downloadedBytes.
     *
     * @return integer
     */
    public function getDownloadedBytes()
    {
        return $this->downloadedBytes;
    }

    /**
     * Sets the value of downloadedBytes.
     *
     * @param integer $downloadedBytes the downloaded bytes
     */
    public function setDownloadedBytes($downloadedBytes)
    {
        $this->downloadedBytes = $downloadedBytes;
    }

    /**
     * Gets the value of filesAdded.
     *
     * @return integer
     */
    public function getFilesAdded()
    {
        return $this->filesAdded;
    }

    /**
     * Sets the value of filesAdded.
     *
     * @param integer $filesAdded the files added
     */
    public function setFilesAdded($filesAdded)
    {
        $this->filesAdded = $filesAdded;
    }

    /**
     * Gets the value of secondsActive.
     *
     * @return integer
     */
    public function getSecondsActive()
    {
        return $this->secondsActive;
    }

    /**
     * Sets the value of secondsActive.
     *
     * @param integer $secondsActive the seconds active
     */
    public function setSecondsActive($secondsActive)
    {
        $this->secondsActive = $secondsActive;
    }

    /**
     * Gets the value of sessionCount.
     *
     * @return integer
     */
    public function getSessionCount()
    {
        return $this->sessionCount;
    }

    /**
     * Sets the value of sessionCount.
     *
     * @param integer $sessionCount the session count
     */
    public function setSessionCount($sessionCount)
    {
        $this->sessionCount = $sessionCount;
    }

    /**
     * Gets the value of uploadedBytes.
     *
     * @return integer
     */
    public function getUploadedBytes()
    {
        return $this->uploadedBytes;
    }

    /**
     * Sets the value of uploadedBytes.
     *
     * @param integer $uploadedBytes the uploaded bytes
     */
    public function setUploadedBytes($uploadedBytes)
    {
        $this->uploadedBytes = $uploadedBytes;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'downloadedBytes' => 'downloadedBytes',
            'filesAdded' => 'filesAdded',
            'secondsActive' => 'secondsActive',
            'sessionCount' => 'sessionCount',
            'uploadedBytes' => 'uploadedBytes'
        );
    }
}


================================================
FILE: lib/Transmission/Model/Status.php
================================================
<?php
namespace Transmission\Model;

/**
 * @author Ramon Kleiss <ramonkleiss@gmail.com>
 */
class Status extends AbstractModel
{
    /**
     * @var integer
     */
    const STATUS_STOPPED = 0;

    /**
     * @var integer
     */
    const STATUS_CHECK_WAIT = 1;

    /**
     * @var integer
     */
    const STATUS_CHECK = 2;

    /**
     * @var integer
     */
    const STATUS_DOWNLOAD_WAIT = 3;

    /**
     * @var integer
     */
    const STATUS_DOWNLOAD = 4;

    /**
     * @var integer
     */
    const STATUS_SEED_WAIT = 5;

    /**
     * @var integer
     */
    const STATUS_SEED = 6;

    /**
     * @var integer
     */
    protected $status;

    /**
     * @param integer|Status $status
     */
    public function __construct($status)
    {
        if ($status instanceof self) {
            $this->status = $status->getValue();
        } else {
            $this->status = (integer) $status;
        }
    }

    /**
     * @return integer
     */
    public function getValue()
    {
        return $this->status;
    }

    /**
     * @return boolean
     */
    public function isStopped()
    {
        return $this->status == self::STATUS_STOPPED;
    }

    /**
     * @return boolean
     */
    public function isChecking()
    {
        return ($this->status == self::STATUS_CHECK ||
                $this->status == self::STATUS_CHECK_WAIT);
    }

    /**
     * @return boolean
     */
    public function isDownloading()
    {
        return ($this->status == self::STATUS_DOWNLOAD ||
                $this->status == self::STATUS_DOWNLOAD_WAIT);
    }

    /**
     * @return boolean
     */
    public function isSeeding()
    {
        return ($this->status == self::STATUS_SEED ||
                $this->status == self::STATUS_SEED_WAIT);
    }
}


================================================
FILE: lib/Transmission/Model/Torrent.php
================================================
<?php
namespace Transmission\Model;

use Transmission\Util\PropertyMapper;

/**
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class Torrent extends AbstractModel
{
    /**
     * @var integer
     */
    protected $id;

    /**
     * @var integer
     */
    protected $eta;

    /**
     * @var integer
     */
    protected $size;

    /**
     * @var string
     */
    protected $name;

    /**
     * @var string
     */
    protected $hash;

    /**
     * @var Status
     */
    protected $status;

    /**
     * @var boolean
     */
    protected $finished;

    /**
     * @var integer
     */
    protected $startDate;
    
    /**
     * @var integer
     */
    protected $uploadRate;

    /**
     * @var integer
     */
    protected $downloadRate;

    /**
     * @var integer
     */
    protected $peersConnected;

    /**
     * @var double
     */
    protected $percentDone;

    /**
     * @var array
     */
    protected $files = array();

    /**
     * @var array
     */
    protected $peers = array();

    /**
     * @var array
     */
    protected $trackers = array();

    /**
     * @var array
     */
    protected $trackerStats = array();

    /**
     * @var double
     */
    protected $uploadRatio;
    
    /**
     * @var string
     */
    protected $downloadDir;

    /**
     * @var integer
     */
    protected $downloadedEver;

    /**
     * @var integer
     */
    protected $uploadedEver;

    /**
     * @param integer $id
     */
    public function setId($id)
    {
        $this->id = (integer) $id;
    }

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

    /**
     * @param integer $eta
     */
    public function setEta($eta)
    {
        $this->eta = (integer) $eta;
    }

    /**
     * @return integer
     */
    public function getEta()
    {
        return $this->eta;
    }

    /**
     * @param integer $size
     */
    public function setSize($size)
    {
        $this->size = (integer) $size;
    }

    /**
     * @return integer
     */
    public function getSize()
    {
        return $this->size;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = (string) $name;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $hash
     */
    public function setHash($hash)
    {
        $this->hash = (string) $hash;
    }

    /**
     * @return string
     */
    public function getHash()
    {
        return $this->hash;
    }

    /**
     * @param integer|Status $status
     */
    public function setStatus($status)
    {
        $this->status = new Status($status);
    }

    /**
     * @return integer
     */
    public function getStatus()
    {
        return $this->status->getValue();
    }

    /**
     * @param boolean $finished
     */
    public function setFinished($finished)
    {
        $this->finished = (boolean) $finished;
    }

    /**
     * @return boolean
     */
    public function isFinished()
    {
        return ($this->finished || (int) $this->getPercentDone() == 100);
    }

    /**
     * @var integer $startDate
     */
    public function setStartDate($startDate)
    {
        $this->startDate = (integer) $startDate;
    }

    /**
     * @return integer
     */
    public function getStartDate()
    {
        return $this->startDate;
    }
    /**
     * @var integer $rate
     */
    public function setUploadRate($rate)
    {
        $this->uploadRate = (integer) $rate;
    }

    /**
     * @return integer
     */
    public function getUploadRate()
    {
        return $this->uploadRate;
    }

    /**
     * @param integer $rate
     */
    public function setDownloadRate($rate)
    {
        $this->downloadRate = (integer) $rate;
    }

    /**
     * @param integer $peersConnected
     */
    public function setPeersConnected($peersConnected)
    {
        $this->peersConnected = (integer) $peersConnected;
    }

    /**
     * @return integer
     */
    public function getPeersConnected()
    {
        return $this->peersConnected;
    }

    /**
     * @return integer
     */
    public function getDownloadRate()
    {
        return $this->downloadRate;
    }

    /**
     * @param double $done
     */
    public function setPercentDone($done)
    {
        $this->percentDone = (double) $done;
    }

    /**
     * @return double
     */
    public function getPercentDone()
    {
        return $this->percentDone * 100.0;
    }

    /**
     * @param array $files
     */
    public function setFiles(array $files)
    {
        $this->files = array_map(function ($file) {
            return PropertyMapper::map(new File(), $file);
        }, $files);
    }

    /**
     * @return array
     */
    public function getFiles()
    {
        return $this->files;
    }

    /**
     * @param array $peers
     */
    public function setPeers(array $peers)
    {
        $this->peers = array_map(function ($peer) {
            return PropertyMapper::map(new Peer(), $peer);
        }, $peers);
    }

    /**
     * @return array
     */
    public function getPeers()
    {
        return $this->peers;
    }
    /**
     * @param array $trackerStats
     */
    public function setTrackerStats(array $trackerStats)
    {
        $this->trackerStats = array_map(function ($trackerStats) {
            return PropertyMapper::map(new TrackerStats(), $trackerStats);
        }, $trackerStats);
    }

    /**
     * @return array
     */
    public function getTrackerStats()
    {
        return $this->trackerStats;
    }

    /**
     * @param array $trackers
     */
    public function setTrackers(array $trackers)
    {
        $this->trackers = array_map(function ($tracker) {
            return PropertyMapper::map(new Tracker(), $tracker);
        }, $trackers);
    }

    /**
     * @return array
     */
    public function getTrackers()
    {
        return $this->trackers;
    }

    /**
     * @param double $ratio
     */
    public function setUploadRatio($ratio)
    {
        $this->uploadRatio = (double) $ratio;
    }

    /**
     * @return double
     */
    public function getUploadRatio()
    {
        return $this->uploadRatio;
    }

    /**
     * @return boolean
     */
    public function isStopped()
    {
        return $this->status->isStopped();
    }

    /**
     * @return boolean
     */
    public function isChecking()
    {
        return $this->status->isChecking();
    }

    /**
     * @return boolean
     */
    public function isDownloading()
    {
        return $this->status->isDownloading();
    }

    /**
     * @return boolean
     */
    public function isSeeding()
    {
        return $this->status->isSeeding();
    }
    
    /**
     * @return string
     */
    public function getDownloadDir()
    {
        return $this->downloadDir;
    }

    /**
     * @param string $downloadDir
     */
    public function setDownloadDir($downloadDir)
    {
        $this->downloadDir = $downloadDir;
    }

    /**
     * @return int
     */
    public function getDownloadedEver() {
        return $this->downloadedEver;
    }

    /**
     * @param int $downloadedEver
     */
    public function setDownloadedEver($downloadedEver) {
        $this->downloadedEver = $downloadedEver;
    }

    /**
     * @return int
     */
    public function getUploadedEver() {
        return $this->uploadedEver;
    }

    /**
     * @param int $uploadedEver
     */
    public function setUploadedEver($uploadedEver) {
        $this->uploadedEver = $uploadedEver;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'id' => 'id',
            'eta' => 'eta',
            'sizeWhenDone' => 'size',
            'name' => 'name',
            'status' => 'status',
            'isFinished' => 'finished',
            'rateUpload' => 'uploadRate',
            'rateDownload' => 'downloadRate',
            'percentDone' => 'percentDone',
            'files' => 'files',
            'peers' => 'peers',
            'peersConnected' => 'peersConnected',
            'trackers' => 'trackers',
            'trackerStats' => 'trackerStats',
            'startDate' => 'startDate',
            'uploadRatio' => 'uploadRatio',
            'hashString' => 'hash',
            'downloadDir' => 'downloadDir',
            'downloadedEver' => 'downloadedEver',
            'uploadedEver' => 'uploadedEver'
        );
    }
}


================================================
FILE: lib/Transmission/Model/Tracker.php
================================================
<?php
namespace Transmission\Model;

/**
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class Tracker extends AbstractModel
{
    /**
     * @var integer
     */
    protected $id;

    /**
     * @var integer
     */
    protected $tier;

    /**
     * @var string
     */
    protected $scrape;

    /**
     * @var string
     */
    protected $announce;

    /**
     * @param integer $id
     */
    public function setId($id)
    {
        $this->id = (integer) $id;
    }

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

    /**
     * @param integer $tier
     */
    public function setTier($tier)
    {
        $this->tier = (integer) $tier;
    }

    /**
     * @return integer
     */
    public function getTier()
    {
        return $this->tier;
    }

    /**
     * @param string $scrape
     */
    public function setScrape($scrape)
    {
        $this->scrape = (string) $scrape;
    }

    /**
     * @return string
     */
    public function getScrape()
    {
        return $this->scrape;
    }

    /**
     * @param string $announce
     */
    public function setAnnounce($announce)
    {
        $this->announce = (string) $announce;
    }

    /**
     * @return string
     */
    public function getAnnounce()
    {
        return $this->announce;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'id' => 'id',
            'tier' => 'tier',
            'scrape' => 'scrape',
            'announce' => 'announce'
        );
    }
}


================================================
FILE: lib/Transmission/Model/TrackerStats.php
================================================
<?php
namespace Transmission\Model;

/**
 * @author Bilal Ghouri <bilalghouri@live.com>
 */
class TrackerStats extends AbstractModel
{
    /**
     * @var string
     */
    protected $host;

    /**
     * @var integer
     */
    protected $leecherCount;
	
	/**
     * @var integer
     */
    protected $seederCount;

    /**
     * @var string
     */
    protected $lastAnnounceResult;

    /**
     * @var string
     */
    protected $lastScrapeResult;

    /**
     * @param string $host
     */
    public function setHost($host)
    {
        $this->host =  (string) $host;
    }

    /**
     * @return string
     */
    public function getHost()
    {
        return $this->host;
    }
	
    /**
     * @param string $lastAnnounceResult
     */
    public function setLastAnnounceResult($lastAnnounceResult)
    {
        $this->lastAnnounceResult =  (string) $lastAnnounceResult;
    }

    /**
     * @return string
     */
    public function getLastAnnounceResult()
    {
        return $this->lastAnnounceResult;
    }
	
	/**
     * @param string $lastScrapeResult
     */
    public function setLastScrapeResult($lastScrapeResult)
    {
        $this->lastScrapeResult =  (string) $lastScrapeResult;
    }

    /**
     * @return string
     */
    public function getLastScrapeResult()
    {
        return $this->lastScrapeResult;
    }

    /**
     * @param integer $seederCount
     */
    public function setSeederCount($seederCount)
    {
        $this->seederCount = (integer) $seederCount;
    }

    /**
     * @return integer
     */
    public function getSeederCount()
    {
        return $this->seederCount;
    }

    /**
     * @param integer $leecherCount
     */
    public function setLeecherCount($leecherCount)
    {
        $this->leecherCount = (integer) $leecherCount;
    }

    /**
     * @return integer
     */
    public function getLeecherCount()
    {
        return $this->leecherCount;
    }

    /**
     * {@inheritDoc}
     */
    public static function getMapping()
    {
        return array(
            'host' => 'host',
            'leecherCount' => 'leecherCount',
            'seederCount' => 'seederCount',
            'lastScrapeResult' => 'lastScrapeResult',
            'lastAnnounceResult' => 'lastAnnounceResult'
        );
    }
}


================================================
FILE: lib/Transmission/Transmission.php
================================================
<?php
namespace Transmission;

use Transmission\Model\Torrent;
use Transmission\Model\Session;
use Transmission\Model\FreeSpace;
use Transmission\Model\Stats\Session as SessionStats;
use Transmission\Util\PropertyMapper;
use Transmission\Util\ResponseValidator;

/**
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class Transmission
{
    /**
     * @var Client
     */
    protected $client;

    /**
     * @var ResponseValidator
     */
    protected $validator;

    /**
     * @var PropertyMapper
     */
    protected $mapper;

    /**
     * Constructor
     *
     * @param string  $host
     * @param integer $port
     * @param string  $path
     */
    public function __construct($host = null, $port = null, $path = null)
    {
        $this->setClient(new Client($host, $port, $path));
        $this->setMapper(new PropertyMapper());
        $this->setValidator(new ResponseValidator());
    }

    /**
     * Get all the torrents in the download queue
     *
     * @return Torrent[]
     */
    public function all()
    {
        $client   = $this->getClient();
        $mapper   = $this->getMapper();
        $response = $this->getClient()->call(
            'torrent-get',
            array('fields' => array_keys(Torrent::getMapping()))
        );

        $torrents = array_map(function ($data) use ($mapper, $client) {
            return $mapper->map(
                new Torrent($client),
                $data
            );
        }, $this->getValidator()->validate('torrent-get', $response));

        return $torrents;
    }

    /**
     * Get a specific torrent from the download queue
     *
     * @param  integer                    $id
     * @return Torrent
     * @throws \RuntimeException
     */
    public function get($id)
    {
        $client   = $this->getClient();
        $mapper   = $this->getMapper();
        $response = $this->getClient()->call('torrent-get', array(
            'fields' => array_keys(Torrent::getMapping()),
            'ids'    => array($id)
        ));

        $torrent = array_reduce(
            $this->getValidator()->validate('torrent-get', $response),
            function ($torrent, $data) use ($mapper, $client) {
                return $torrent ? $torrent : $mapper->map(new Torrent($client), $data);
            });

        if (!$torrent instanceof Torrent) {
            throw new \RuntimeException(sprintf("Torrent with ID %s not found", $id));
        }

        return $torrent;
    }

    /**
     * Get the Transmission session
     *
     * @return Session
     */
    public function getSession()
    {
        $response = $this->getClient()->call(
            'session-get',
            array()
        );

        return $this->getMapper()->map(
            new Session($this->getClient()),
            $this->getValidator()->validate('session-get', $response)
        );
    }

    /**
     * @return SessionStats
     */
    public function getSessionStats()
    {
        $response = $this->getClient()->call(
            'session-stats',
            array()
        );

        return $this->getMapper()->map(
            new SessionStats(),
            $this->getValidator()->validate('session-stats', $response)
        );
    }

    /**
     * Get Free space
     * @param  string $path
     * @return FreeSpace
     */
    public function getFreeSpace($path=null)
    {
        if (!$path) {
            $path = $this->getSession()->getDownloadDir();
        }
        $response = $this->getClient()->call(
            'free-space',
            array('path'=>$path)
        );

        return $this->getMapper()->map(
            new FreeSpace(),
            $this->getValidator()->validate('free-space', $response)
        );
    }

    /**
     * Add a torrent to the download queue
     *
     * @param  string   $torrent
     * @param  boolean  $metainfo
     * @param  string   $savepath
     * @return Torrent
     */
    public function add($torrent, $metainfo = false, $savepath = null)
    {
        $parameters = array($metainfo ? 'metainfo' : 'filename' => $torrent);

        if ($savepath !== null) {
            $parameters['download-dir'] = (string) $savepath;
        }

        $response = $this->getClient()->call(
            'torrent-add',
            $parameters
        );

        return $this->getMapper()->map(
            new Torrent($this->getClient()),
            $this->getValidator()->validate('torrent-add', $response)
        );
    }

    /**
     * Start the download of a torrent
     *
     * @param Torrent $torrent
     * @param bool    $now
     */
    public function start(Torrent $torrent, $now = false)
    {
        $this->getClient()->call(
            $now ? 'torrent-start-now' : 'torrent-start',
            array('ids' => array($torrent->getId()))
        );
    }

    /**
     * Stop the download of a torrent
     *
     * @param Torrent $torrent
     */
    public function stop(Torrent $torrent)
    {
        $this->getClient()->call(
            'torrent-stop',
            array('ids' => array($torrent->getId()))
        );
    }

    /**
     * Verify the download of a torrent
     *
     * @param Torrent $torrent
     */
    public function verify(Torrent $torrent)
    {
        $this->getClient()->call(
            'torrent-verify',
            array('ids' => array($torrent->getId()))
        );
    }

    /**
     * Request a reannounce of a torrent
     *
     * @param Torrent $torrent
     */
    public function reannounce(Torrent $torrent)
    {
        $this->getClient()->call(
            'torrent-reannounce',
            array('ids' => array($torrent->getId()))
        );
    }

    /**
     * Remove a torrent from the download queue
     *
     * @param Torrent $torrent
     */
    public function remove(Torrent $torrent, $localData = false)
    {
        $arguments = array('ids' => array($torrent->getId()));

        if ($localData) {
            $arguments['delete-local-data'] = true;
        }

        $this->getClient()->call('torrent-remove', $arguments);
    }

    /**
     * Set the client used to connect to Transmission
     *
     * @param Client $client
     */
    public function setClient(Client $client)
    {
        $this->client = $client;
    }

    /**
     * Get the client used to connect to Transmission
     *
     * @return Client
     */
    public function getClient()
    {
        return $this->client;
    }

    /**
     * Set the hostname of the Transmission server
     *
     * @param string $host
     */
    public function setHost($host)
    {
        $this->getClient()->setHost($host);
    }

    /**
     * Get the hostname of the Transmission server
     *
     * @return string
     */
    public function getHost()
    {
        return $this->getClient()->getHost();
    }

    /**
     * Set the port the Transmission server is listening on
     *
     * @param integer $port
     */
    public function setPort($port)
    {
        $this->getClient()->setPort($port);
    }

    /**
     * Get the port the Transmission server is listening on
     *
     * @return integer
     */
    public function getPort()
    {
        return $this->getClient()->getPort();
    }

    /**
     * Set the mapper used to map responses from Transmission to models
     *
     * @param PropertyMapper $mapper
     */
    public function setMapper(PropertyMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    /**
     * Get the mapper used to map responses from Transmission to models
     *
     * @return PropertyMapper
     */
    public function getMapper()
    {
        return $this->mapper;
    }

    /**
     * Set the validator used to validate Transmission responses
     *
     * @param ResponseValidator $validator
     */
    public function setValidator(ResponseValidator $validator)
    {
        $this->validator = $validator;
    }

    /**
     * Get the validator used to validate Transmission responses
     *
     * @return ResponseValidator
     */
    public function getValidator()
    {
        return $this->validator;
    }
}


================================================
FILE: lib/Transmission/Util/PropertyMapper.php
================================================
<?php
namespace Transmission\Util;

use Transmission\Model\ModelInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;

/**
 * The PropertyMapper is used to map responses from Transmission to models
 *
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class PropertyMapper
{
    /**
     * @param  ModelInterface $model
     * @param  \stdClass                          $dto
     * @return ModelInterface
     */
    public static function map(ModelInterface $model, $dto)
    {
        $accessor = PropertyAccess::createPropertyAccessor();

        $mapping  = array_filter($model->getMapping(), function ($value) {
            return !is_null($value);
        });

        foreach ($mapping as $source => $dest) {
            try {
                $accessor->setValue(
                    $model,
                    $dest,
                    $accessor->getValue($dto, $source)
                );
            } catch (\Exception $e) {
                continue;
            }
        }

        return $model;
    }
}


================================================
FILE: lib/Transmission/Util/ResponseValidator.php
================================================
<?php
namespace Transmission\Util;

/**
 * @author Ramon Kleiss <ramon@cubilon.nl>
 */
class ResponseValidator
{
    /**
     * @param  string    $method
     * @param  \stdClass $response
     * @return \stdClass
     */
    public static function validate($method, \stdClass $response)
    {
        if (!isset($response->result)) {
            throw new \RuntimeException('Invalid response received from Transmission');
        }

        if (!in_array($response->result, array('success', 'duplicate torrent'))) {
            throw new \RuntimeException(sprintf(
                'An error occured: "%s"', $response->result
            ));
        }

        switch ($method) {
            case 'torrent-get':
                return self::validateGetResponse($response);
            case 'torrent-add':
                return self::validateAddResponse($response);
            case 'session-get':
                return self::validateSessionGetResponse($response);
            case 'session-stats':
                return self::validateSessionStatsGetResponse($response);
            case 'free-space':
                return self::validateFreeSpaceGetResponse($response);
        }
    }

    /**
     * @param  \stdClass         $response
     * @throws \RuntimeException
     */
    public static function validateGetResponse(\stdClass $response)
    {
        if (!isset($response->arguments) ||
            !isset($response->arguments->torrents)) {
            throw new \RuntimeException(
                'Invalid response received from Transmission'
            );
        }

        return $response->arguments->torrents;
    }

    /**
     * @param  \stdClass         $response
     * @throws \RuntimeException
     */
    public static function validateAddResponse(\stdClass $response)
    {
        $fields = array('torrent-added', 'torrent-duplicate');

        foreach ($fields as $field) {
            if (isset($response->arguments) &&
                isset($response->arguments->$field) &&
                count($response->arguments->$field)) {
                return $response->arguments->$field;
            }
        }

        throw new \RuntimeException('Invalid response received from Transmission');
    }

    public static function validateSessionGetResponse(\stdClass $response)
    {
        if (!isset($response->arguments)) {
            throw new \RuntimeException(
                'Invalid response received from Transmission'
            );
        }

        return $response->arguments;
    }

    /**
     * @param  \stdClass $response
     * @return \stdClass
     */
    public static function validateSessionStatsGetResponse(\stdClass $response)
    {
        if (!isset($response->arguments)) {
            throw new \RuntimeException(
                'Invalid response received from Transmission'
            );
        }
        $class='Transmission\\Model\\Stats\\Stats';
        foreach (array('cumulative-stats','current-stats') as $property) {
            if (property_exists($response->arguments,$property)) {
                $instance=self::map($response->arguments->$property,$class);
                $response->arguments->$property=$instance;
            }
        }

        return $response->arguments;
    }

    private static function map($object,$class)
    {
        return PropertyMapper::map(new $class(),$object);

    }

    public static function validateFreeSpaceGetResponse(\stdClass $response)
    {
        if (!isset($response->arguments)) {
            throw new \RuntimeException(
                'Invalid response received from Transmission'
            );
        }

        return $response->arguments;
    }
}


================================================
FILE: phpunit.xml.dist
================================================
<phpunit bootstrap="./tests/bootstrap.php" colors="true">
    <testsuites>
        <testsuite name="Transmission Test Suite">
            <directory suffix="Test.php">./tests/Transmission/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">./lib/Transmission/</directory>
        </whitelist>
    </filter>
</phpunit>


================================================
FILE: tests/Transmission/Mock/Model.php
================================================
<?php
namespace Transmission\Mock;

use Transmission\Model\ModelInterface;

class Model implements ModelInterface
{
    private $fo;
    private $bar;
    private $unused;

    public function setFo($fo)
    {
        $this->fo = $fo;
    }

    public function getFo()
    {
        return $this->fo;
    }

    public function setBar($bar)
    {
        $this->bar = $bar;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public function setUnused($unused)
    {
        $this->unused = $unused;
    }

    public function getUnused()
    {
        return $this->unused;
    }

    public static function getMapping()
    {
        return array(
            'foo' => 'fo',
            'bar' => 'bar',
            'unused' => null
        );
    }
}


================================================
FILE: tests/Transmission/Tests/ClientTest.php
================================================
<?php
namespace Transmission\Tests;

use Transmission\Client;

class ClientTest extends \PHPUnit_Framework_TestCase
{
    protected $client;

    /**
     * @test
     */
    public function shouldHaveDefaultHost()
    {
        $this->assertEquals('localhost', $this->getClient()->getHost());
    }

    /**
     * @test
     */
    public function shouldHaveDefaultPort()
    {
        $this->assertEquals(9091, $this->getClient()->getPort());
    }

    /**
     * @test
     */
    public function shouldHaveNoTokenOnInstantiation()
    {
        $this->assertEmpty($this->getClient()->getToken());
    }

    /**
     * @test
     */
    public function shouldHaveDefaultClient()
    {
        $this->assertInstanceOf('Buzz\Client\Curl', $this->getClient()->getClient());
    }

    /**
     * @test
     */
    public function shouldGenerateDefaultUrl()
    {
        $this->assertEquals('http://localhost:9091', $this->getClient()->getUrl());
    }

    /**
     * @test
     */
    public function shouldMakeApiCall()
    {
        $test   = $this;
        $client = $this->getMock('Buzz\Client\Curl');
        $client->expects($this->once())
            ->method('send')
            ->with(
                $this->isInstanceOf('Buzz\Message\Request'),
                $this->isInstanceOf('Buzz\Message\Response')
            )
            ->will($this->returnCallback(function ($request, $response) use ($test) {
                $test->assertEquals('POST', $request->getMethod());
                $test->assertEquals('/transmission/rpc', $request->getResource());
                $test->assertEquals('http://localhost:9091', $request->getHost());
                $test->assertEmpty($request->getHeader('X-Transmission-Session-Id'));
                $test->assertEquals('{"method":"foo","arguments":{"bar":"baz"}}', $request->getContent());

                $response->addHeader('HTTP/1.1 200 OK');
                $response->addHeader('Content-Type: application/json');
                $response->addHeader('X-Transmission-Session-Id: foo');
                $response->setContent('{"foo":"bar"}');
            }));

        $this->getClient()->setClient($client);
        $response = $this->getClient()->call('foo', array('bar' => 'baz'));

        $this->assertInstanceOf('stdClass', $response);
        $this->assertObjectHasAttribute('foo', $response);
        $this->assertEquals('bar', $response->foo);
    }

    /**
     * @test
     */
    public function shouldAuthenticate()
    {
        $test   = $this;
        $client = $this->getMock('Buzz\Client\Curl');
        $client->expects($this->once())
            ->method('send')
            ->with(
                $this->isInstanceOf('Buzz\Message\Request'),
                $this->isInstanceOf('Buzz\Message\Response')
            )
            ->will($this->returnCallback(function ($request, $response) use ($test) {
                $test->assertEquals('POST', $request->getMethod());
                $test->assertEquals('/transmission/rpc', $request->getResource());
                $test->assertEquals('http://localhost:9091', $request->getHost());
                $test->assertEmpty($request->getHeader('X-Transmission-Session-Id'));
                $test->assertEquals('Basic '. base64_encode('foo:bar'), $request->getHeader('Authorization'));
                $test->assertEquals('{"method":"foo","arguments":{"bar":"baz"}}', $request->getContent());

                $response->addHeader('HTTP/1.1 200 OK');
                $response->addHeader('Content-Type: application/json');
                $response->addHeader('X-Transmission-Session-Id: foo');
                $response->setContent('{"foo":"bar"}');
            }));

        $this->getClient()->authenticate('foo', 'bar');
        $this->getClient()->setClient($client);
        $response = $this->getClient()->call('foo', array('bar' => 'baz'));

        $this->assertInstanceOf('stdClass', $response);
        $this->assertObjectHasAttribute('foo', $response);
        $this->assertEquals('bar', $response->foo);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnExceptionDuringApiCall()
    {
        $client = $this->getMock('Buzz\Client\Curl');
        $client->expects($this->once())
            ->method('send')
            ->will($this->throwException(new \Exception()));

        $this->getClient()->setClient($client);
        $this->getClient()->call('foo', array());
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnUnexpectedStatusCode()
    {
        $client = $this->getMock('Buzz\Client\Curl');
        $client->expects($this->once())
            ->method('send')
            ->will($this->returnCallback(function ($request, $response) {
                $response->addHeader('HTTP/1.1 500 Internal Server Error');
            }));

        $this->getClient()->setClient($client);
        $this->getClient()->call('foo', array());
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnAccessDenied()
    {
        $client = $this->getMock('Buzz\Client\Curl');
        $client->expects($this->once())
            ->method('send')
            ->will($this->returnCallback(function ($request, $response) {
                $response->addHeader('HTTP/1.1 401 Access Denied');
            }));

        $this->getClient()->setClient($client);
        $this->getClient()->call('foo', array());
    }

    /**
     * @test
     */
    public function shouldHandle409ResponseWhenMakingAnApiCall()
    {
        $test   = $this;
        $client = $this->getMock('Buzz\Client\Curl');
        $client->expects($this->at(0))
            ->method('send')
            ->will($this->returnCallback(function ($request, $response) use ($test) {
                $test->assertEmpty($request->getHeader('X-Transmission-Session-Id'));

                $response->addHeader('HTTP/1.1 409 Conflict');
                $response->addHeader('X-Transmission-Session-Id: foo');
            }));

        $client->expects($this->at(1))
            ->method('send')
            ->will($this->returnCallback(function ($request, $response) {
                $response->addHeader('HTTP/1.1 200 OK');
                $response->addHeader('Content-Type: application/json');
                $response->addHeader('X-Transmission-Session-Id: foo');
                $response->setContent('{"foo":"bar"}');
            }));

        $this->getClient()->setClient($client);
        $response = $this->getClient()->call('foo', array());

        $this->assertEquals('foo', $this->getClient()->getToken());
        $this->assertInstanceOf('stdClass', $response);
        $this->assertObjectHasAttribute('foo', $response);
        $this->assertEquals('bar', $response->foo);
    }

    public function setup()
    {
        $this->client = new Client();
    }

    private function getClient()
    {
        return $this->client;
    }
}


================================================
FILE: tests/Transmission/Tests/Model/AbstractModelTest.php
================================================
<?php
namespace Transmission\Tests\Model;

class AbstractModelTest extends \PHPUnit_Framework_TestCase
{
    protected $model;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getModel());
    }

    /**
     * @test
     */
    public function shouldHaveEmptyMappingByDefault()
    {
        $this->assertEmpty($this->getModel()->getMapping());
    }

    /**
     * @test
     */
    public function shouldHaveNoClientByDefault()
    {
        $this->assertNull($this->getModel()->getClient());
    }

    /**
     * @test
     */
    public function shouldHaveClientIfSetByUser()
    {
        $client = $this->getMock('Transmission\Client');

        $this->getModel()->setClient($client);
        $this->assertEquals($client, $this->getModel()->getClient());
    }

    public function setup()
    {
        $this->model = $this->getMockForAbstractClass('Transmission\Model\AbstractModel');
    }

    private function getModel()
    {
        return $this->model;
    }
}


================================================
FILE: tests/Transmission/Tests/Model/FileTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\File;
use Transmission\Util\PropertyMapper;


class FileTest extends \PHPUnit_Framework_TestCase
{
    protected $file;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getFile());
    }

    /**
     * @test
     */
    public function shouldHaveNonEmptyMapping()
    {
        $this->assertNotEmpty($this->getFile()->getMapping());
    }

    /**
     * @test
     */
    public function shouldBeCreatedFromMapping()
    {
        $source = (object) array(
            'name' => 'foo',
            'length' => 100,
            'bytesCompleted' => 10
        );

        PropertyMapper::map($this->getFile(), $source);

        $this->assertEquals('foo', $this->getFile()->getName());
        $this->assertEquals(100, $this->getFile()->getSize());
        $this->assertEquals(10, $this->getFile()->getCompleted());
        $this->assertFalse($this->getFile()->isDone());
    }

    /**
     * @test
     */
    public function shouldConvertToString()
    {
        $this->getFile()->setName('foo');

        $this->assertInternalType('string', (string) $this->getFile());
        $this->assertEquals('foo', (string) $this->getFile());
    }

    public function setup()
    {
        $this->file = new File();
    }

    private function getFile()
    {
        return $this->file;
    }
}



================================================
FILE: tests/Transmission/Tests/Model/PeerTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\Peer;
use Transmission\Util\PropertyMapper;

class PeerTest extends \PHPUnit_Framework_TestCase
{
    protected $peer;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getPeer());
    }

    /**
     * @test
     */
    public function shouldHaveNonEmptyMapping()
    {
        $this->assertNotEmpty($this->getPeer()->getMapping());
    }

    /**
     * @test
     */
    public function shouldBeCreatedFromMapping()
    {
        $source = (object) array(
            'address' => 'foo',
            'clientName' => 'foo',
            'clientIsChoked' => false,
            'clientIsInterested' => true,
            'flagStr' => 'foo',
            'isDownloadingFrom' => false,
            'isEncrypted' => true,
            'isIncoming' => false,
            'isUploadingTo' => true,
            'isUTP' => false,
            'peerIsChoked' => true,
            'peerIsInterested' => false,
            'port' => 3000,
            'progress' => 10.5,
            'rateToClient' => 1000,
            'rateFromClient' => 10000
        );

        PropertyMapper::map($this->getPeer(), $source);

        $this->assertEquals('foo', $this->getPeer()->getAddress());
        $this->assertEquals('foo', $this->getPeer()->getClientName());
        $this->assertFalse($this->getPeer()->isClientChoked());
        $this->assertTrue($this->getPeer()->isClientInterested());
        $this->assertFalse($this->getPeer()->isDownloading());
        $this->assertTrue($this->getPeer()->isEncrypted());
        $this->assertFalse($this->getPeer()->isIncoming());
        $this->assertTrue($this->getPeer()->isUploading());
        $this->assertFalse($this->getPeer()->isUtp());
        $this->assertTrue($this->getPeer()->isPeerChoked());
        $this->assertFalse($this->getPeer()->isPeerInterested());
        $this->assertEquals(3000, $this->getPeer()->getPort());
        $this->assertEquals(10.5, $this->getPeer()->getProgress());
        $this->assertEquals(1000, $this->getPeer()->getUploadRate());
        $this->assertEquals(10000, $this->getPeer()->getDownloadRate());
    }

    public function setup()
    {
        $this->peer = new Peer();
    }

    public function getPeer()
    {
        return $this->peer;
    }
}


================================================
FILE: tests/Transmission/Tests/Model/SessionTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\Session;
use Transmission\Util\PropertyMapper;
use Symfony\Component\PropertyAccess\PropertyAccess;

class SessionTest extends \PHPUnit_Framework_TestCase
{
    protected $session;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getSession());
    }

    /**
     * @test
     */
    public function shouldHaveNonEmptyMapping()
    {
        $this->assertNotEmpty($this->getSession()->getMapping());
    }

    /** 
     * @test
     */
    public function shouldBeCreatedFromMapping()
    {
        $source = (object) array(
            'alt-speed-down' => 1,
            'alt-speed-enabled' => true,
            'download-dir' => 'foo',
            'download-queue-enabled' => true,
            'download-queue-size' => 5,
            'incomplete-dir' => 'bar',
            'incomplete-dir-enabled' => true,
            'script-torrent-done-filename' => 'baz',
            'script-torrent-done-enabled' => true,
            'seedRatioLimit' => 3.14,
            'seedRatioLimited' => true,
            'seed-queue-size' => 5,
            'seed-queue-enabled' => true,
            'speed-limit-down' => 100,
            'speed-limit-down-enabled' => true,
            'speed-limit-up' => 100,
            'speed-limit-up-enabled' => true
        );

        PropertyMapper::map($this->getSession(), $source);

        $this->assertEquals(1, $this->getSession()->getAltSpeedDown());
        $this->assertTrue($this->getSession()->isAltSpeedEnabled());
        $this->assertEquals('foo', $this->getSession()->getDownloadDir());
        $this->assertEquals(5, $this->getSession()->getDownloadQueueSize());
        $this->assertTrue($this->getSession()->isDownloadQueueEnabled());
        $this->assertEquals('bar', $this->getSession()->getIncompleteDir());
        $this->assertTrue($this->getSession()->isIncompleteDirEnabled());
        $this->assertEquals('baz', $this->getSession()->getTorrentDoneScript());
        $this->assertTrue($this->getSession()->isTorrentDoneScriptEnabled());
        $this->assertEquals(3.14, $this->getSession()->getSeedRatioLimit());
        $this->assertTrue($this->getSession()->isSeedRatioLimited());
        $this->assertEquals(5, $this->getSession()->getSeedQueueSize());
        $this->assertTrue($this->getSession()->isSeedQueueEnabled());
        $this->assertEquals(100, $this->getSession()->getDownloadSpeedLimit());
        $this->assertTrue($this->getSession()->isDownloadSpeedLimitEnabled());
        $this->assertEquals(100, $this->getSession()->getUploadSpeedLimit());
        $this->assertTrue($this->getSession()->isUploadSpeedLimitEnabled());
    }

    /**
     * @test
     */
    public function shouldSave()
    {
        $expected = array(
            'alt-speed-down' => 1,
            'alt-speed-enabled' => true,
            'download-dir' => 'foo',
            'download-queue-enabled' => true,
            'download-queue-size' => 5,
            'incomplete-dir' => 'bar',
            'incomplete-dir-enabled' => true,
            'script-torrent-done-filename' => 'baz',
            'script-torrent-done-enabled' => true,
            'seedRatioLimit' => 3.14,
            'seedRatioLimited' => true,
            'seed-queue-size' => 5,
            'seed-queue-enabled' => true,
            'speed-limit-down' => 100,
            'speed-limit-down-enabled' => true,
            'speed-limit-up' => 100,
            'speed-limit-up-enabled' => true
        );

        PropertyMapper::map($this->getSession(), (object) $expected);

        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('session-set', $expected)
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success',
                );
            }));

        $this->getSession()->setClient($client);
        $this->getSession()->save();
    }

    /**
     * @test
     */
    public function shouldNotSaveWithNoClient()
    {
        $this->getSession()->save();
    }

    public function setup()
    {
        $this->session = new Session();
    }

    protected function getSession()
    {
        return $this->session;
    }
}


================================================
FILE: tests/Transmission/Tests/Model/StatusTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\Status;

class StatusTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function shouldConstructUsingStatusInstance()
    {
        $state  = new Status(Status::STATUS_STOPPED);
        $status = new Status($state);

        $this->assertTrue($status->isStopped());
    }
}


================================================
FILE: tests/Transmission/Tests/Model/TorrentTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\Torrent;
use Transmission\Util\PropertyMapper;
use Symfony\Component\PropertyAccess\PropertyAccess;

class TorrentTest extends \PHPUnit_Framework_TestCase
{
    protected $torrent;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getTorrent());
    }

    /**
     * @test
     */
    public function shouldHaveNonEmptyMapping()
    {
        $this->assertNotEmpty($this->getTorrent()->getMapping());
    }

    /**
     * @test
     */
    public function shouldBeCreatedFromMapping()
    {
        $source = (object) array(
            'id' => 1,
            'eta' => 10,
            'sizeWhenDone' => 10000,
            'name' => 'foo',
            'hashString' => 'bar',
            'status' => 0,
            'isFinished' => false,
            'rateUpload' => 10,
            'rateDownload' => 100,
            'downloadDir' => '/home/foo',
            'downloadedEver' => 1024000000,
            'uploadedEver' => 1024000000000, // 1 Tb
            'files' => array(
                (object) array()
            ),
            'peers' => array(
                (object) array(),
                (object) array()
            ),
            'peersConnected' => 10,
            'startDate' => 1427583510,
            'trackers' => array(
                (object) array(),
                (object) array(),
                (object) array()
            ),
            'trackerStats' => array(
                (object) array(),
                (object) array(),
                (object) array()
            )
        );

        PropertyMapper::map($this->getTorrent(), $source);

        $this->assertEquals(1, $this->getTorrent()->getId());
        $this->assertEquals(10, $this->getTorrent()->getEta());
        $this->assertEquals(10000, $this->getTorrent()->getSize());
        $this->assertEquals('foo', $this->getTorrent()->getName());
        $this->assertEquals('bar', $this->getTorrent()->getHash());
        $this->assertEquals(0, $this->getTorrent()->getStatus());
        $this->assertFalse($this->getTorrent()->isFinished());
        $this->assertEquals(10, $this->getTorrent()->getUploadRate());
        $this->assertEquals(100, $this->getTorrent()->getDownloadRate());
        $this->assertEquals('/home/foo', $this->getTorrent()->getDownloadDir());
        $this->assertEquals(1024000000, $this->getTorrent()->getDownloadedEver());
        $this->assertEquals(1024000000000, $this->getTorrent()->getUploadedEver());
        $this->assertCount(1, $this->getTorrent()->getFiles());
        $this->assertCount(2, $this->getTorrent()->getPeers());
        $this->assertCount(3, $this->getTorrent()->getTrackers());
    }

    /**
     * @test
     */
    public function shouldBeDoneWhenFinishedFlagIsSet()
    {
        $this->getTorrent()->setFinished(true);

        $this->assertTrue($this->getTorrent()->isFinished());
    }

    /**
     * @test
     */
    public function shouldBeDoneWhenPercentDoneIs100Percent()
    {
        $this->getTorrent()->setPercentDone(1);

        $this->assertTrue($this->getTorrent()->isFinished());
    }

    /**
     * @test
     * @dataProvider statusProvider
     */
    public function shouldHaveConvenienceMethods($status, $method)
    {
        $methods = array('stopped', 'checking', 'downloading', 'seeding');
        $accessor = PropertyAccess::createPropertyAccessor();
        $this->getTorrent()->setStatus($status);

        $methods = array_filter($methods, function ($value) use ($method) {
            return $method !== $value;
        });

        $this->assertTrue($accessor->getValue($this->getTorrent(), $method));
        foreach ($methods as $m) {
            $this->assertFalse($accessor->getValue($this->getTorrent(), $m), $m);
        }
    }

    public function statusProvider()
    {
        return array(
            array(0, 'stopped'),
            array(1, 'checking'),
            array(2, 'checking'),
            array(3, 'downloading'),
            array(4, 'downloading'),
            array(5, 'seeding'),
            array(6, 'seeding')
        );
    }

    public function setup()
    {
        $this->torrent = new Torrent();
    }

    public function getTorrent()
    {
        return $this->torrent;
    }
}


================================================
FILE: tests/Transmission/Tests/Model/TrackerStatsTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\TrackerStats;
use Transmission\Util\PropertyMapper;

class TrackerStatsTest extends \PHPUnit_Framework_TestCase
{
    protected $trackerStats;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getTrackerStats());
    }

    /**
     * @test
     */
    public function shouldHaveNonEmptyMapping()
    {
        $this->assertNotEmpty($this->getTrackerStats()->getMapping());
    }

    /**
     * @test
     */
    public function shouldBeCreatedFromMapping()
    {
        $source = (object) array(
            'host' => 'test',
            'leecherCount' => 1,
            'seederCount' => 2,
            'lastScrapeResult' => 'foo',
            'lastAnnounceResult' => 'bar'
        );

        PropertyMapper::map($this->getTrackerStats(), $source);

        $this->assertEquals('test', $this->getTrackerStats()->getHost());
        $this->assertEquals(1, $this->getTrackerStats()->getLeecherCount());
        $this->assertEquals(2, $this->getTrackerStats()->getSeederCount());
        $this->assertEquals('foo', $this->getTrackerStats()->getLastScrapeResult());
        $this->assertEquals('bar', $this->getTrackerStats()->getLastAnnounceResult());
    }

    public function setup()
    {
        $this->trackerStats = new TrackerStats();
    }

    private function getTrackerStats()
    {
        return $this->trackerStats;
    }
}


================================================
FILE: tests/Transmission/Tests/Model/TrackerTest.php
================================================
<?php
namespace Transmission\Tests\Model;

use Transmission\Model\Tracker;
use Transmission\Util\PropertyMapper;

class TrackerTest extends \PHPUnit_Framework_TestCase
{
    protected $tracker;

    /**
     * @test
     */
    public function shouldImplementModelInterface()
    {
        $this->assertInstanceOf('Transmission\Model\ModelInterface', $this->getTracker());
    }

    /**
     * @test
     */
    public function shouldHaveNonEmptyMapping()
    {
        $this->assertNotEmpty($this->getTracker()->getMapping());
    }

    /**
     * @test
     */
    public function shouldBeCreatedFromMapping()
    {
        $source = (object) array(
            'id' => 1,
            'tier' => 1,
            'scrape' => 'foo',
            'announce' => 'bar'
        );

        PropertyMapper::map($this->getTracker(), $source);

        $this->assertEquals(1, $this->getTracker()->getId());
        $this->assertEquals(1, $this->getTracker()->getTier());
        $this->assertEquals('foo', $this->getTracker()->getScrape());
        $this->assertEquals('bar', $this->getTracker()->getAnnounce());
    }

    public function setup()
    {
        $this->tracker = new Tracker();
    }

    private function getTracker()
    {
        return $this->tracker;
    }
}


================================================
FILE: tests/Transmission/Tests/TransmissionTest.php
================================================
<?php
namespace Transmission\Tests;

use Transmission\Transmission;
use Transmission\Model\Torrent;

class TransmissionTest extends \PHPUnit_Framework_TestCase
{
    protected $transmission;

    /**
     * @test
     */
    public function shouldHaveDefaultHost()
    {
        $this->assertEquals('localhost', $this->getTransmission()->getClient()->getHost());
    }

    /**
     * @test
     */
    public function shouldGetAllTorrentsInDownloadQueue()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-get')
            ->will($this->returnCallback(function ($method, $arguments) {
                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array(
                        'torrents' => array(
                            (object) array(),
                            (object) array(),
                            (object) array(),
                        )
                    )
                );
            }));

        $this->getTransmission()->setClient($client);

        $torrents = $this->getTransmission()->all();

        $this->assertCount(3, $torrents);
    }

    /**
     * @test
     */
    public function shouldGetTorrentById()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-get')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertEquals(1, $arguments['ids'][0]);

                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array(
                        'torrents' => array(
                            (object) array()
                        )
                    )
                );
            }));

        $this->getTransmission()->setClient($client);

        $torrent = $this->getTransmission()->get(1);

        $this->assertInstanceOf('Transmission\Model\Torrent', $torrent);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionWhenTorrentIsNotFound()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-get')
            ->will($this->returnCallback(function ($method, $arguments) {
                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array(
                        'torrents' => array()
                    )
                );
            }));

        $this->getTransmission()->setClient($client);
        $this->getTransmission()->get(1);
    }

    /**
     * @test
     */
    public function shouldAddTorrentByFilename()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-add')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertArrayHasKey('filename', $arguments);

                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array(
                        'torrent-added' => (object) array()
                    )
                );
            }));

        $this->getTransmission()->setClient($client);

        $torrent = $this->getTransmission()->add('foo');
        $this->assertInstanceOf('Transmission\Model\Torrent', $torrent);
    }

    /**
     * @test
     */
    public function shouldAddTorrentByMetainfo()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-add')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertArrayHasKey('metainfo', $arguments);

                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array(
                        'torrent-added' => (object) array()
                    )
                );
            }));

        $this->getTransmission()->setClient($client);

        $torrent = $this->getTransmission()->add('foo', true);
        $this->assertInstanceOf('Transmission\Model\Torrent', $torrent);
    }

    /**
     * @test
     */
    public function shouldHandleDuplicateTorrent()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-add')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertArrayHasKey('metainfo', $arguments);

                return (object) array(
                    'result' => 'duplicate torrent',
                    'arguments' => (object) array(
                        'torrent-duplicate' => (object) array()
                    )
                );
            }));

        $this->getTransmission()->setClient($client);

        $torrent = $this->getTransmission()->add('foo', true);
        $this->assertInstanceOf('Transmission\Model\Torrent', $torrent);
    }

    /**
     * @test
     */
    public function shouldGetSession()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('session-get')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertEmpty($arguments);

                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array()
                );
            }));

        $this->getTransmission()->setClient($client);
        $session = $this->getTransmission()->getSession();

        $this->assertInstanceOf('Transmission\Model\Session', $session);
    }

    /**
     * @test
     */
    public function shouldGetSessionStats()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('session-stats')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertEmpty($arguments);

                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array()
                );
            }));

        $this->getTransmission()->setClient($client);
        $stats = $this->getTransmission()->getSessionStats();

        $this->assertInstanceOf('Transmission\Model\Stats\Session', $stats);
    }

    /**
     * @test
     */
    public function shouldGetFreeSpace()
    {
        $that   = $this;
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('free-space')
            ->will($this->returnCallback(function ($method, $arguments) use ($that) {
                $that->assertArrayHasKey('path', $arguments);

                return (object) array(
                    'result' => 'success',
                    'arguments' => (object) array()
                );
            }));

        $this->getTransmission()->setClient($client);
        $freeSpace = $this->getTransmission()->getFreeSpace('/');
        $this->assertInstanceOf('Transmission\Model\FreeSpace', $freeSpace);
    }

    /**
     * @test
     */
    public function shouldStartDownload()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-start', array('ids' => array(1)))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->start($torrent);
    }

    /**
     * @test
     */
    public function shouldStartDownloadImmediately()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-start-now', array('ids' => array(1)))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->start($torrent, true);
    }

    /**
     * @test
     */
    public function shouldStopDownload()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-stop', array('ids' => array(1)))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->stop($torrent);
    }

    /**
     * @test
     */
    public function shouldVerifyDownload()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-verify', array('ids' => array(1)))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->verify($torrent);
    }

    /**
     * @test
     */
    public function shouldReannounceDownload()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-reannounce', array('ids' => array(1)))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->reannounce($torrent);
    }

    /**
     * @test
     */
    public function shouldRemoveDownloadWithoutRemovingLocalData()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-remove', array('ids' => array(1)))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->remove($torrent);
    }

    /**
     * @test
     */
    public function shouldRemoveDownloadWithRemovingLocalData()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('call')
            ->with('torrent-remove', array('ids' => array(1), 'delete-local-data' => true))
            ->will($this->returnCallback(function () {
                return (object) array(
                    'result' => 'success'
                );
            }));

        $torrent = new Torrent();
        $torrent->setId(1);

        $transmission = new Transmission();
        $transmission->setClient($client);
        $transmission->remove($torrent, true);
    }

    /**
     * @test
     */
    public function shouldHaveDefaultPort()
    {
        $this->assertEquals(9091, $this->getTransmission()->getClient()->getPort());
    }

    /**
     * @test
     */
    public function shouldProvideFacadeForClient()
    {
        $client = $this->getMock('Transmission\Client');
        $client->expects($this->once())
            ->method('setHost')
            ->with('example.org');

        $client->expects($this->once())
            ->method('getHost')
            ->will($this->returnValue('example.org'));

        $client->expects($this->once())
            ->method('setPort')
            ->with(80);

        $client->expects($this->once())
            ->method('getPort')
            ->will($this->returnValue(80));

        $this->getTransmission()->setClient($client);
        $this->getTransmission()->setHost('example.org');
        $this->getTransmission()->setPort(80);

        $this->assertEquals('example.org', $this->getTransmission()->getHost());
        $this->assertEquals(80, $this->getTransmission()->getPort());
    }

    public function setup()
    {
        $this->transmission = new Transmission();
    }

    private function getTransmission()
    {
        return $this->transmission;
    }
}


================================================
FILE: tests/Transmission/Tests/Util/PropertyMapperTest.php
================================================
<?php
namespace Transmission\Tests\Util;

use Transmission\Util\PropertyMapper;

class PropertyMapperTest extends \PHPUnit_Framework_TestCase
{
    protected $mapper;

    /**
     * @test
     */
    public function shouldMapSourcesToModelWithMethodCall()
    {
        $source = (object) array(
            'foo' => 'this',
            'bar' => 'that',
            'ba' => 'thus',
            'unused' => false
        );

        $model = new \Transmission\Mock\Model();

        $this->getMapper()->map($model, $source);

        $this->assertEquals('this', $model->getFo());
        $this->assertEquals('that', $model->getBar());
        $this->assertNull($model->getUnused());
    }

    public function setup()
    {
        $this->mapper = new PropertyMapper();
    }

    private function getMapper()
    {
        return $this->mapper;
    }
}


================================================
FILE: tests/Transmission/Tests/Util/ResponseValidatorTest.php
================================================
<?php
namespace Transmission\Tests\Util;

use Transmission\Util\ResponseValidator;

class ResponseValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $validator;

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingResultField()
    {
        $response = (object) array();

        $this->getValidator()->validate('', $response);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnErrorResultField()
    {
        $response = (object) array('result' => 'error');

        $this->getValidator()->validate('', $response);
    }

    /**
     * @test
     */
    public function shouldThrowNoExceptionOnValidTorrentGetResponse()
    {
        $response = (object) array(
            'result' => 'success',
            'arguments' => (object) array(
                'torrents' => array(
                    (object) array('foo' => 'bar')
                )
            )
        );

        $expected  = array((object) array('foo' => 'bar'));
        $container = $this->getValidator()->validate('torrent-get', $response);
        $this->assertEquals($expected, $container);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingArgumentsInTorrentGetResponse()
    {
        $response = (object) array('result' => 'success');

        $this->getValidator()->validate('torrent-get', $response);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingTorrentArgumentInTorrentGetResponse()
    {
        $response = (object) array('result' => 'success', 'arguments' => (object) array());

        $this->getValidator()->validate('torrent-get', $response);
    }

    /**
     * @test
     */
    public function shouldThrowNoExceptionOnValidTorrentAddResponse()
    {
        $response = (object) array(
            'result' => 'success',
            'arguments' => (object) array(
                'torrent-added' => (object) array(
                    'foo' => 'bar'
                )
            )
        );

        $expected  = (object) array('foo' => 'bar');
        $container = $this->getValidator()->validate('torrent-add', $response);
        $this->assertEquals($expected, $container);
    }

    /**
     * @test
     */
    public function shouldThrowNoExceptionOnValidSessionGetResponse()
    {
        $response = (object) array(
            'result' => 'success',
            'arguments' => (object) array(
                    'foo' => 'bar'
            )
        );

        $expected  = (object) array('foo' => 'bar');
        $container = $this->getValidator()->validate('session-get', $response);
        $this->assertEquals($expected, $container);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingArgumentsInSessionGetResponse()
    {
        $response = (object) array('result' => 'success');

        $this->getValidator()->validate('session-get', $response);
    }
    
    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingArgumentsSessionGetResponse()
    {
        $response = (object) array('result' => 'success');

        $this->getValidator()->validate('session-get', $response);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingArgumentsInTorrentAddResponse()
    {
        $response = (object) array('result' => 'success');

        $this->getValidator()->validate('torrent-add', $response);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnMissingTorrentFieldArgumentInTorrentAddResponse()
    {
        $response = (object) array('result' => 'success', 'arguments' => (object) array());

        $this->getValidator()->validate('torrent-add', $response);
    }

    /**
     * @test
     * @expectedException RuntimeException
     */
    public function shouldThrowExceptionOnEmptyTorrentFieldInTorrentAddResponse()
    {
        $response = (object) array('result' => 'success', 'arguments' => (object) array('torrent-added' => array()));

        $this->getValidator()->validate('torrent-add', $response);
    }

    /**
     * @test
     */
    public function shouldThrowNoExceptionOnValidOtherResponses()
    {
        $response = (object) array('result' => 'success');

        $container = $this->getValidator()->validate('torrent-remove', $response);
        $this->assertNull($container);
    }

    public function setup()
    {
        $this->validator = new ResponseValidator();
    }

    private function getValidator()
    {
        return $this->validator;
    }
}


================================================
FILE: tests/bootstrap.php
================================================
<?php
if (!$loader = @include __DIR__.'/../vendor/autoload.php') {
    echo <<<EOM
    Install dependencies using Composer:

        curl -s https://getcomposer.org/installer | php
        php composer.phar install

EOM;

    exit(1);
}

$loader->add('Transmission\Mock', __DIR__);
$loader->add('Transmission\Tests', __DIR__);
Download .txt
gitextract_kh88jjkg/

├── .gitignore
├── .travis.yml
├── CHANGELOG
├── LICENSE
├── README.md
├── composer.json
├── examples/
│   └── queue.php
├── lib/
│   └── Transmission/
│       ├── Client.php
│       ├── Model/
│       │   ├── AbstractModel.php
│       │   ├── File.php
│       │   ├── FreeSpace.php
│       │   ├── ModelInterface.php
│       │   ├── Peer.php
│       │   ├── Session.php
│       │   ├── Stats/
│       │   │   ├── Session.php
│       │   │   └── Stats.php
│       │   ├── Status.php
│       │   ├── Torrent.php
│       │   ├── Tracker.php
│       │   └── TrackerStats.php
│       ├── Transmission.php
│       └── Util/
│           ├── PropertyMapper.php
│           └── ResponseValidator.php
├── phpunit.xml.dist
└── tests/
    ├── Transmission/
    │   ├── Mock/
    │   │   └── Model.php
    │   └── Tests/
    │       ├── ClientTest.php
    │       ├── Model/
    │       │   ├── AbstractModelTest.php
    │       │   ├── FileTest.php
    │       │   ├── PeerTest.php
    │       │   ├── SessionTest.php
    │       │   ├── StatusTest.php
    │       │   ├── TorrentTest.php
    │       │   ├── TrackerStatsTest.php
    │       │   └── TrackerTest.php
    │       ├── TransmissionTest.php
    │       └── Util/
    │           ├── PropertyMapperTest.php
    │           └── ResponseValidatorTest.php
    └── bootstrap.php
Download .txt
SYMBOL INDEX (362 symbols across 29 files)

FILE: lib/Transmission/Client.php
  class Client (line 14) | class Client
    method __construct (line 73) | public function __construct($host = null, $port = null, $path = null)
    method authenticate (line 89) | public function authenticate($username, $password)
    method call (line 102) | public function call($method, array $arguments)
    method getUrl (line 124) | public function getUrl()
    method setHost (line 138) | public function setHost($host)
    method getHost (line 148) | public function getHost()
    method setPort (line 158) | public function setPort($port)
    method getPort (line 168) | public function getPort()
    method setPath (line 178) | public function setPath($path)
    method getPath (line 186) | public function getPath()
    method setToken (line 196) | public function setToken($token)
    method getToken (line 206) | public function getToken()
    method setClient (line 216) | public function setClient(ClientInterface $client)
    method getClient (line 226) | public function getClient()
    method compose (line 236) | protected function compose($method, $arguments)
    method validateResponse (line 259) | protected function validateResponse($response, $method, $arguments)

FILE: lib/Transmission/Model/AbstractModel.php
  class AbstractModel (line 12) | abstract class AbstractModel implements ModelInterface
    method __construct (line 24) | public function __construct(Client $client = null)
    method setClient (line 32) | public function setClient(Client $client)
    method getClient (line 40) | public function getClient()
    method getMapping (line 48) | public static function getMapping()
    method call (line 57) | protected function call($method, $arguments)

FILE: lib/Transmission/Model/File.php
  class File (line 7) | class File extends AbstractModel
    method setName (line 27) | public function setName($name)
    method getName (line 35) | public function getName()
    method setSize (line 43) | public function setSize($size)
    method getSize (line 51) | public function getSize()
    method setCompleted (line 59) | public function setCompleted($completed)
    method getCompleted (line 67) | public function getCompleted()
    method isDone (line 75) | public function isDone()
    method getMapping (line 83) | public static function getMapping()
    method __toString (line 92) | public function __toString()

FILE: lib/Transmission/Model/FreeSpace.php
  class FreeSpace (line 7) | class FreeSpace extends AbstractModel
    method getPath (line 24) | public function getPath()
    method setPath (line 34) | public function setPath($path)
    method getSize (line 44) | public function getSize()
    method setSize (line 54) | public function setSize($size)
    method getMapping (line 62) | public static function getMapping()

FILE: lib/Transmission/Model/ModelInterface.php
  type ModelInterface (line 9) | interface ModelInterface
    method getMapping (line 16) | public static function getMapping();

FILE: lib/Transmission/Model/Peer.php
  class Peer (line 7) | class Peer extends AbstractModel
    method setAddress (line 87) | public function setAddress($address)
    method getAddress (line 95) | public function getAddress()
    method setPort (line 103) | public function setPort($port)
    method getPort (line 111) | public function getPort()
    method setClientName (line 119) | public function setClientName($clientName)
    method getClientName (line 127) | public function getClientName()
    method setClientChoked (line 135) | public function setClientChoked($choked)
    method isClientChoked (line 143) | public function isClientChoked()
    method setClientInterested (line 151) | public function setClientInterested($interested)
    method isClientInterested (line 159) | public function isClientInterested()
    method setDownloading (line 167) | public function setDownloading($downloading)
    method isDownloading (line 175) | public function isDownloading()
    method setEncrypted (line 183) | public function setEncrypted($encrypted)
    method isEncrypted (line 191) | public function isEncrypted()
    method setIncoming (line 199) | public function setIncoming($incoming)
    method isIncoming (line 207) | public function isIncoming()
    method setUploading (line 215) | public function setUploading($uploading)
    method isUploading (line 223) | public function isUploading()
    method setUtp (line 231) | public function setUtp($utp)
    method isUtp (line 239) | public function isUtp()
    method setPeerChoked (line 247) | public function setPeerChoked($choked)
    method isPeerChoked (line 255) | public function isPeerChoked()
    method setPeerInterested (line 263) | public function setPeerInterested($interested)
    method isPeerInterested (line 271) | public function isPeerInterested()
    method setProgress (line 279) | public function setProgress($progress)
    method getProgress (line 287) | public function getProgress()
    method setUploadRate (line 295) | public function setUploadRate($rate)
    method getUploadRate (line 303) | public function getUploadRate()
    method setDownloadRate (line 311) | public function setDownloadRate($rate)
    method getDownloadRate (line 319) | public function getDownloadRate()
    method getMapping (line 327) | public static function getMapping()

FILE: lib/Transmission/Model/Session.php
  class Session (line 10) | class Session extends AbstractModel
    method setAltSpeedDown (line 100) | public function setAltSpeedDown($speed)
    method getAltSpeedDown (line 108) | public function getAltSpeedDown()
    method setAltSpeedEnabled (line 116) | public function setAltSpeedEnabled($enabled)
    method isAltSpeedEnabled (line 124) | public function isAltSpeedEnabled()
    method setDownloadDir (line 132) | public function setDownloadDir($downloadDir)
    method getDownloadDir (line 140) | public function getDownloadDir()
    method setDownloadQueueEnabled (line 148) | public function setDownloadQueueEnabled($enabled)
    method isDownloadQueueEnabled (line 156) | public function isDownloadQueueEnabled()
    method setDownloadQueueSize (line 164) | public function setDownloadQueueSize($size)
    method getDownloadQueueSize (line 172) | public function getDownloadQueueSize()
    method setIncompleteDir (line 180) | public function setIncompleteDir($directory)
    method getIncompleteDir (line 188) | public function getIncompleteDir()
    method setIncompleteDirEnabled (line 196) | public function setIncompleteDirEnabled($enabled)
    method isIncompleteDirEnabled (line 204) | public function isIncompleteDirEnabled()
    method setTorrentDoneScript (line 212) | public function setTorrentDoneScript($filename)
    method getTorrentDoneScript (line 220) | public function getTorrentDoneScript()
    method setTorrentDoneScriptEnabled (line 228) | public function setTorrentDoneScriptEnabled($enabled)
    method isTorrentDoneScriptEnabled (line 236) | public function isTorrentDoneScriptEnabled()
    method setSeedRatioLimit (line 244) | public function setSeedRatioLimit($limit)
    method getSeedRatioLimit (line 252) | public function getSeedRatioLimit()
    method setSeedRatioLimited (line 260) | public function setSeedRatioLimited($limited)
    method isSeedRatioLimited (line 268) | public function isSeedRatioLimited()
    method setSeedQueueSize (line 276) | public function setSeedQueueSize($size)
    method getSeedQueueSize (line 284) | public function getSeedQueueSize()
    method setSeedQueueEnabled (line 292) | public function setSeedQueueEnabled($enabled)
    method isSeedQueueEnabled (line 300) | public function isSeedQueueEnabled()
    method setDownloadSpeedLimit (line 308) | public function setDownloadSpeedLimit($limit)
    method getDownloadSpeedLimit (line 316) | public function getDownloadSpeedLimit()
    method setDownloadSpeedLimitEnabled (line 324) | public function setDownloadSpeedLimitEnabled($enabled)
    method isDownloadSpeedLimitEnabled (line 332) | public function isDownloadSpeedLimitEnabled()
    method setUploadSpeedLimit (line 340) | public function setUploadSpeedLimit($limit)
    method getUploadSpeedLimit (line 348) | public function getUploadSpeedLimit()
    method setUploadSpeedLimitEnabled (line 356) | public function setUploadSpeedLimitEnabled($enabled)
    method isUploadSpeedLimitEnabled (line 364) | public function isUploadSpeedLimitEnabled()
    method getMapping (line 372) | public static function getMapping()
    method save (line 395) | public function save()

FILE: lib/Transmission/Model/Stats/Session.php
  class Session (line 9) | class Session extends AbstractModel
    method getActiveTorrentCount (line 51) | public function getActiveTorrentCount()
    method setActiveTorrentCount (line 61) | public function setActiveTorrentCount($activeTorrentCount)
    method getDownloadSpeed (line 71) | public function getDownloadSpeed()
    method setDownloadSpeed (line 81) | public function setDownloadSpeed($downloadSpeed)
    method getPausedTorrentCount (line 91) | public function getPausedTorrentCount()
    method setPausedTorrentCount (line 101) | public function setPausedTorrentCount($pausedTorrentCount)
    method getTorrentCount (line 111) | public function getTorrentCount()
    method setTorrentCount (line 121) | public function setTorrentCount($torrentCount)
    method getUploadSpeed (line 131) | public function getUploadSpeed()
    method setUploadSpeed (line 141) | public function setUploadSpeed($uploadSpeed)
    method getCumulative (line 151) | public function getCumulative()
    method setCumulative (line 161) | public function setCumulative(Stats $cumulative)
    method getCurrent (line 171) | public function getCurrent()
    method setCurrent (line 181) | public function setCurrent(Stats $current)
    method getMapping (line 189) | public static function getMapping()

FILE: lib/Transmission/Model/Stats/Stats.php
  class Stats (line 10) | class Stats implements ModelInterface
    method getDownloadedBytes (line 42) | public function getDownloadedBytes()
    method setDownloadedBytes (line 52) | public function setDownloadedBytes($downloadedBytes)
    method getFilesAdded (line 62) | public function getFilesAdded()
    method setFilesAdded (line 72) | public function setFilesAdded($filesAdded)
    method getSecondsActive (line 82) | public function getSecondsActive()
    method setSecondsActive (line 92) | public function setSecondsActive($secondsActive)
    method getSessionCount (line 102) | public function getSessionCount()
    method setSessionCount (line 112) | public function setSessionCount($sessionCount)
    method getUploadedBytes (line 122) | public function getUploadedBytes()
    method setUploadedBytes (line 132) | public function setUploadedBytes($uploadedBytes)
    method getMapping (line 140) | public static function getMapping()

FILE: lib/Transmission/Model/Status.php
  class Status (line 7) | class Status extends AbstractModel
    method __construct (line 52) | public function __construct($status)
    method getValue (line 64) | public function getValue()
    method isStopped (line 72) | public function isStopped()
    method isChecking (line 80) | public function isChecking()
    method isDownloading (line 89) | public function isDownloading()
    method isSeeding (line 98) | public function isSeeding()

FILE: lib/Transmission/Model/Torrent.php
  class Torrent (line 9) | class Torrent extends AbstractModel
    method setId (line 114) | public function setId($id)
    method getId (line 122) | public function getId()
    method setEta (line 130) | public function setEta($eta)
    method getEta (line 138) | public function getEta()
    method setSize (line 146) | public function setSize($size)
    method getSize (line 154) | public function getSize()
    method setName (line 162) | public function setName($name)
    method getName (line 170) | public function getName()
    method setHash (line 178) | public function setHash($hash)
    method getHash (line 186) | public function getHash()
    method setStatus (line 194) | public function setStatus($status)
    method getStatus (line 202) | public function getStatus()
    method setFinished (line 210) | public function setFinished($finished)
    method isFinished (line 218) | public function isFinished()
    method setStartDate (line 226) | public function setStartDate($startDate)
    method getStartDate (line 234) | public function getStartDate()
    method setUploadRate (line 241) | public function setUploadRate($rate)
    method getUploadRate (line 249) | public function getUploadRate()
    method setDownloadRate (line 257) | public function setDownloadRate($rate)
    method setPeersConnected (line 265) | public function setPeersConnected($peersConnected)
    method getPeersConnected (line 273) | public function getPeersConnected()
    method getDownloadRate (line 281) | public function getDownloadRate()
    method setPercentDone (line 289) | public function setPercentDone($done)
    method getPercentDone (line 297) | public function getPercentDone()
    method setFiles (line 305) | public function setFiles(array $files)
    method getFiles (line 315) | public function getFiles()
    method setPeers (line 323) | public function setPeers(array $peers)
    method getPeers (line 333) | public function getPeers()
    method setTrackerStats (line 340) | public function setTrackerStats(array $trackerStats)
    method getTrackerStats (line 350) | public function getTrackerStats()
    method setTrackers (line 358) | public function setTrackers(array $trackers)
    method getTrackers (line 368) | public function getTrackers()
    method setUploadRatio (line 376) | public function setUploadRatio($ratio)
    method getUploadRatio (line 384) | public function getUploadRatio()
    method isStopped (line 392) | public function isStopped()
    method isChecking (line 400) | public function isChecking()
    method isDownloading (line 408) | public function isDownloading()
    method isSeeding (line 416) | public function isSeeding()
    method getDownloadDir (line 424) | public function getDownloadDir()
    method setDownloadDir (line 432) | public function setDownloadDir($downloadDir)
    method getDownloadedEver (line 440) | public function getDownloadedEver() {
    method setDownloadedEver (line 447) | public function setDownloadedEver($downloadedEver) {
    method getUploadedEver (line 454) | public function getUploadedEver() {
    method setUploadedEver (line 461) | public function setUploadedEver($uploadedEver) {
    method getMapping (line 468) | public static function getMapping()

FILE: lib/Transmission/Model/Tracker.php
  class Tracker (line 7) | class Tracker extends AbstractModel
    method setId (line 32) | public function setId($id)
    method getId (line 40) | public function getId()
    method setTier (line 48) | public function setTier($tier)
    method getTier (line 56) | public function getTier()
    method setScrape (line 64) | public function setScrape($scrape)
    method getScrape (line 72) | public function getScrape()
    method setAnnounce (line 80) | public function setAnnounce($announce)
    method getAnnounce (line 88) | public function getAnnounce()
    method getMapping (line 96) | public static function getMapping()

FILE: lib/Transmission/Model/TrackerStats.php
  class TrackerStats (line 7) | class TrackerStats extends AbstractModel
    method setHost (line 37) | public function setHost($host)
    method getHost (line 45) | public function getHost()
    method setLastAnnounceResult (line 53) | public function setLastAnnounceResult($lastAnnounceResult)
    method getLastAnnounceResult (line 61) | public function getLastAnnounceResult()
    method setLastScrapeResult (line 69) | public function setLastScrapeResult($lastScrapeResult)
    method getLastScrapeResult (line 77) | public function getLastScrapeResult()
    method setSeederCount (line 85) | public function setSeederCount($seederCount)
    method getSeederCount (line 93) | public function getSeederCount()
    method setLeecherCount (line 101) | public function setLeecherCount($leecherCount)
    method getLeecherCount (line 109) | public function getLeecherCount()
    method getMapping (line 117) | public static function getMapping()

FILE: lib/Transmission/Transmission.php
  class Transmission (line 14) | class Transmission
    method __construct (line 38) | public function __construct($host = null, $port = null, $path = null)
    method all (line 50) | public function all()
    method get (line 76) | public function get($id)
    method getSession (line 103) | public function getSession()
    method getSessionStats (line 119) | public function getSessionStats()
    method getFreeSpace (line 137) | public function getFreeSpace($path=null)
    method add (line 161) | public function add($torrent, $metainfo = false, $savepath = null)
    method start (line 186) | public function start(Torrent $torrent, $now = false)
    method stop (line 199) | public function stop(Torrent $torrent)
    method verify (line 212) | public function verify(Torrent $torrent)
    method reannounce (line 225) | public function reannounce(Torrent $torrent)
    method remove (line 238) | public function remove(Torrent $torrent, $localData = false)
    method setClient (line 254) | public function setClient(Client $client)
    method getClient (line 264) | public function getClient()
    method setHost (line 274) | public function setHost($host)
    method getHost (line 284) | public function getHost()
    method setPort (line 294) | public function setPort($port)
    method getPort (line 304) | public function getPort()
    method setMapper (line 314) | public function setMapper(PropertyMapper $mapper)
    method getMapper (line 324) | public function getMapper()
    method setValidator (line 334) | public function setValidator(ResponseValidator $validator)
    method getValidator (line 344) | public function getValidator()

FILE: lib/Transmission/Util/PropertyMapper.php
  class PropertyMapper (line 12) | class PropertyMapper
    method map (line 19) | public static function map(ModelInterface $model, $dto)

FILE: lib/Transmission/Util/ResponseValidator.php
  class ResponseValidator (line 7) | class ResponseValidator
    method validate (line 14) | public static function validate($method, \stdClass $response)
    method validateGetResponse (line 44) | public static function validateGetResponse(\stdClass $response)
    method validateAddResponse (line 60) | public static function validateAddResponse(\stdClass $response)
    method validateSessionGetResponse (line 75) | public static function validateSessionGetResponse(\stdClass $response)
    method validateSessionStatsGetResponse (line 90) | public static function validateSessionStatsGetResponse(\stdClass $resp...
    method map (line 108) | private static function map($object,$class)
    method validateFreeSpaceGetResponse (line 114) | public static function validateFreeSpaceGetResponse(\stdClass $response)

FILE: tests/Transmission/Mock/Model.php
  class Model (line 6) | class Model implements ModelInterface
    method setFo (line 12) | public function setFo($fo)
    method getFo (line 17) | public function getFo()
    method setBar (line 22) | public function setBar($bar)
    method getBar (line 27) | public function getBar()
    method setUnused (line 32) | public function setUnused($unused)
    method getUnused (line 37) | public function getUnused()
    method getMapping (line 42) | public static function getMapping()

FILE: tests/Transmission/Tests/ClientTest.php
  class ClientTest (line 6) | class ClientTest extends \PHPUnit_Framework_TestCase
    method shouldHaveDefaultHost (line 13) | public function shouldHaveDefaultHost()
    method shouldHaveDefaultPort (line 21) | public function shouldHaveDefaultPort()
    method shouldHaveNoTokenOnInstantiation (line 29) | public function shouldHaveNoTokenOnInstantiation()
    method shouldHaveDefaultClient (line 37) | public function shouldHaveDefaultClient()
    method shouldGenerateDefaultUrl (line 45) | public function shouldGenerateDefaultUrl()
    method shouldMakeApiCall (line 53) | public function shouldMakeApiCall()
    method shouldAuthenticate (line 87) | public function shouldAuthenticate()
    method shouldThrowExceptionOnExceptionDuringApiCall (line 124) | public function shouldThrowExceptionOnExceptionDuringApiCall()
    method shouldThrowExceptionOnUnexpectedStatusCode (line 139) | public function shouldThrowExceptionOnUnexpectedStatusCode()
    method shouldThrowExceptionOnAccessDenied (line 156) | public function shouldThrowExceptionOnAccessDenied()
    method shouldHandle409ResponseWhenMakingAnApiCall (line 172) | public function shouldHandle409ResponseWhenMakingAnApiCall()
    method setup (line 203) | public function setup()
    method getClient (line 208) | private function getClient()

FILE: tests/Transmission/Tests/Model/AbstractModelTest.php
  class AbstractModelTest (line 4) | class AbstractModelTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 11) | public function shouldImplementModelInterface()
    method shouldHaveEmptyMappingByDefault (line 19) | public function shouldHaveEmptyMappingByDefault()
    method shouldHaveNoClientByDefault (line 27) | public function shouldHaveNoClientByDefault()
    method shouldHaveClientIfSetByUser (line 35) | public function shouldHaveClientIfSetByUser()
    method setup (line 43) | public function setup()
    method getModel (line 48) | private function getModel()

FILE: tests/Transmission/Tests/Model/FileTest.php
  class FileTest (line 8) | class FileTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 15) | public function shouldImplementModelInterface()
    method shouldHaveNonEmptyMapping (line 23) | public function shouldHaveNonEmptyMapping()
    method shouldBeCreatedFromMapping (line 31) | public function shouldBeCreatedFromMapping()
    method shouldConvertToString (line 50) | public function shouldConvertToString()
    method setup (line 58) | public function setup()
    method getFile (line 63) | private function getFile()

FILE: tests/Transmission/Tests/Model/PeerTest.php
  class PeerTest (line 7) | class PeerTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 14) | public function shouldImplementModelInterface()
    method shouldHaveNonEmptyMapping (line 22) | public function shouldHaveNonEmptyMapping()
    method shouldBeCreatedFromMapping (line 30) | public function shouldBeCreatedFromMapping()
    method setup (line 70) | public function setup()
    method getPeer (line 75) | public function getPeer()

FILE: tests/Transmission/Tests/Model/SessionTest.php
  class SessionTest (line 8) | class SessionTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 15) | public function shouldImplementModelInterface()
    method shouldHaveNonEmptyMapping (line 23) | public function shouldHaveNonEmptyMapping()
    method shouldBeCreatedFromMapping (line 31) | public function shouldBeCreatedFromMapping()
    method shouldSave (line 77) | public function shouldSave()
    method shouldNotSaveWithNoClient (line 118) | public function shouldNotSaveWithNoClient()
    method setup (line 123) | public function setup()
    method getSession (line 128) | protected function getSession()

FILE: tests/Transmission/Tests/Model/StatusTest.php
  class StatusTest (line 6) | class StatusTest extends \PHPUnit_Framework_TestCase
    method shouldConstructUsingStatusInstance (line 11) | public function shouldConstructUsingStatusInstance()

FILE: tests/Transmission/Tests/Model/TorrentTest.php
  class TorrentTest (line 8) | class TorrentTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 15) | public function shouldImplementModelInterface()
    method shouldHaveNonEmptyMapping (line 23) | public function shouldHaveNonEmptyMapping()
    method shouldBeCreatedFromMapping (line 31) | public function shouldBeCreatedFromMapping()
    method shouldBeDoneWhenFinishedFlagIsSet (line 89) | public function shouldBeDoneWhenFinishedFlagIsSet()
    method shouldBeDoneWhenPercentDoneIs100Percent (line 99) | public function shouldBeDoneWhenPercentDoneIs100Percent()
    method shouldHaveConvenienceMethods (line 110) | public function shouldHaveConvenienceMethods($status, $method)
    method statusProvider (line 126) | public function statusProvider()
    method setup (line 139) | public function setup()
    method getTorrent (line 144) | public function getTorrent()

FILE: tests/Transmission/Tests/Model/TrackerStatsTest.php
  class TrackerStatsTest (line 7) | class TrackerStatsTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 14) | public function shouldImplementModelInterface()
    method shouldHaveNonEmptyMapping (line 22) | public function shouldHaveNonEmptyMapping()
    method shouldBeCreatedFromMapping (line 30) | public function shouldBeCreatedFromMapping()
    method setup (line 49) | public function setup()
    method getTrackerStats (line 54) | private function getTrackerStats()

FILE: tests/Transmission/Tests/Model/TrackerTest.php
  class TrackerTest (line 7) | class TrackerTest extends \PHPUnit_Framework_TestCase
    method shouldImplementModelInterface (line 14) | public function shouldImplementModelInterface()
    method shouldHaveNonEmptyMapping (line 22) | public function shouldHaveNonEmptyMapping()
    method shouldBeCreatedFromMapping (line 30) | public function shouldBeCreatedFromMapping()
    method setup (line 47) | public function setup()
    method getTracker (line 52) | private function getTracker()

FILE: tests/Transmission/Tests/TransmissionTest.php
  class TransmissionTest (line 7) | class TransmissionTest extends \PHPUnit_Framework_TestCase
    method shouldHaveDefaultHost (line 14) | public function shouldHaveDefaultHost()
    method shouldGetAllTorrentsInDownloadQueue (line 22) | public function shouldGetAllTorrentsInDownloadQueue()
    method shouldGetTorrentById (line 51) | public function shouldGetTorrentById()
    method shouldThrowExceptionWhenTorrentIsNotFound (line 82) | public function shouldThrowExceptionWhenTorrentIsNotFound()
    method shouldAddTorrentByFilename (line 104) | public function shouldAddTorrentByFilename()
    method shouldAddTorrentByMetainfo (line 131) | public function shouldAddTorrentByMetainfo()
    method shouldHandleDuplicateTorrent (line 158) | public function shouldHandleDuplicateTorrent()
    method shouldGetSession (line 185) | public function shouldGetSession()
    method shouldGetSessionStats (line 210) | public function shouldGetSessionStats()
    method shouldGetFreeSpace (line 235) | public function shouldGetFreeSpace()
    method shouldStartDownload (line 259) | public function shouldStartDownload()
    method shouldStartDownloadImmediately (line 282) | public function shouldStartDownloadImmediately()
    method shouldStopDownload (line 305) | public function shouldStopDownload()
    method shouldVerifyDownload (line 328) | public function shouldVerifyDownload()
    method shouldReannounceDownload (line 351) | public function shouldReannounceDownload()
    method shouldRemoveDownloadWithoutRemovingLocalData (line 374) | public function shouldRemoveDownloadWithoutRemovingLocalData()
    method shouldRemoveDownloadWithRemovingLocalData (line 397) | public function shouldRemoveDownloadWithRemovingLocalData()
    method shouldHaveDefaultPort (line 420) | public function shouldHaveDefaultPort()
    method shouldProvideFacadeForClient (line 428) | public function shouldProvideFacadeForClient()
    method setup (line 455) | public function setup()
    method getTransmission (line 460) | private function getTransmission()

FILE: tests/Transmission/Tests/Util/PropertyMapperTest.php
  class PropertyMapperTest (line 6) | class PropertyMapperTest extends \PHPUnit_Framework_TestCase
    method shouldMapSourcesToModelWithMethodCall (line 13) | public function shouldMapSourcesToModelWithMethodCall()
    method setup (line 31) | public function setup()
    method getMapper (line 36) | private function getMapper()

FILE: tests/Transmission/Tests/Util/ResponseValidatorTest.php
  class ResponseValidatorTest (line 6) | class ResponseValidatorTest extends \PHPUnit_Framework_TestCase
    method shouldThrowExceptionOnMissingResultField (line 14) | public function shouldThrowExceptionOnMissingResultField()
    method shouldThrowExceptionOnErrorResultField (line 25) | public function shouldThrowExceptionOnErrorResultField()
    method shouldThrowNoExceptionOnValidTorrentGetResponse (line 35) | public function shouldThrowNoExceptionOnValidTorrentGetResponse()
    method shouldThrowExceptionOnMissingArgumentsInTorrentGetResponse (line 55) | public function shouldThrowExceptionOnMissingArgumentsInTorrentGetResp...
    method shouldThrowExceptionOnMissingTorrentArgumentInTorrentGetResponse (line 66) | public function shouldThrowExceptionOnMissingTorrentArgumentInTorrentG...
    method shouldThrowNoExceptionOnValidTorrentAddResponse (line 76) | public function shouldThrowNoExceptionOnValidTorrentAddResponse()
    method shouldThrowNoExceptionOnValidSessionGetResponse (line 95) | public function shouldThrowNoExceptionOnValidSessionGetResponse()
    method shouldThrowExceptionOnMissingArgumentsInSessionGetResponse (line 113) | public function shouldThrowExceptionOnMissingArgumentsInSessionGetResp...
    method shouldThrowExceptionOnMissingArgumentsSessionGetResponse (line 124) | public function shouldThrowExceptionOnMissingArgumentsSessionGetRespon...
    method shouldThrowExceptionOnMissingArgumentsInTorrentAddResponse (line 135) | public function shouldThrowExceptionOnMissingArgumentsInTorrentAddResp...
    method shouldThrowExceptionOnMissingTorrentFieldArgumentInTorrentAddResponse (line 146) | public function shouldThrowExceptionOnMissingTorrentFieldArgumentInTor...
    method shouldThrowExceptionOnEmptyTorrentFieldInTorrentAddResponse (line 157) | public function shouldThrowExceptionOnEmptyTorrentFieldInTorrentAddRes...
    method shouldThrowNoExceptionOnValidOtherResponses (line 167) | public function shouldThrowNoExceptionOnValidOtherResponses()
    method setup (line 175) | public function setup()
    method getValidator (line 180) | private function getValidator()
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (122K chars).
[
  {
    "path": ".gitignore",
    "chars": 48,
    "preview": "vendor/\ncomposer.lock\ncomposer.phar\nphpunit.xml\n"
  },
  {
    "path": ".travis.yml",
    "chars": 134,
    "preview": "language: php\n\nphp: [5.3, 5.4, 5.5]\n\nbefore_script:\n    - composer install --dev --prefer-source\n\nscript:\n    phpunit --"
  },
  {
    "path": "CHANGELOG",
    "chars": 1207,
    "preview": "Version     Changes\n\n0.1.0       - Initial release\n\n0.2.0       - Rewrote the entire public API\n\n0.3.0       - Added sup"
  },
  {
    "path": "LICENSE",
    "chars": 1535,
    "preview": "Copyright (c) 2014, Ramon Kleiss <ramonkleiss@gmail.com\nAll rights reserved.\n\nRedistribution and use in source and binar"
  },
  {
    "path": "README.md",
    "chars": 7913,
    "preview": "# PHP Transmission API\n\n[![Build Status](https://travis-ci.org/kleiram/transmission-php.png)](https://travis-ci.org/klei"
  },
  {
    "path": "composer.json",
    "chars": 517,
    "preview": "{\n    \"name\": \"kleiram/transmission-php\",\n    \"description\": \"PHP Transmission client\",\n    \"keywords\": [\"transmission\","
  },
  {
    "path": "examples/queue.php",
    "chars": 580,
    "preview": "<?php\nrequire_once __DIR__.'/../vendor/autoload.php';\n\n$transmission = new Transmission\\Transmission();\n$queue = $transm"
  },
  {
    "path": "lib/Transmission/Client.php",
    "chars": 6095,
    "preview": "<?php\nnamespace Transmission;\n\nuse Buzz\\Message\\Request;\nuse Buzz\\Message\\Response;\nuse Buzz\\Client\\Curl;\nuse Buzz\\Clien"
  },
  {
    "path": "lib/Transmission/Model/AbstractModel.php",
    "chars": 1165,
    "preview": "<?php\nnamespace Transmission\\Model;\n\nuse Transmission\\Client;\nuse Transmission\\Util\\ResponseValidator;\n\n/**\n * Base clas"
  },
  {
    "path": "lib/Transmission/Model/File.php",
    "chars": 1494,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * @author Ramon Kleiss <ramon@cubilon.nl>\n */\nclass File extends AbstractModel"
  },
  {
    "path": "lib/Transmission/Model/FreeSpace.php",
    "chars": 1042,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * @author Joysen Chellem\n */\nclass FreeSpace extends AbstractModel\n{\n    /**\n "
  },
  {
    "path": "lib/Transmission/Model/ModelInterface.php",
    "chars": 293,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * The interface Transmission models must implement\n *\n * @author Ramon Kleiss "
  },
  {
    "path": "lib/Transmission/Model/Peer.php",
    "chars": 5916,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * @author Ramon Kleiss <ramon@cubilon.nl>\n */\nclass Peer extends AbstractModel"
  },
  {
    "path": "lib/Transmission/Model/Session.php",
    "chars": 8010,
    "preview": "<?php\nnamespace Transmission\\Model;\n\nuse Transmission\\Util\\ResponseValidator;\n\n/**\n * @author Joysen Chellem\n * @author "
  },
  {
    "path": "lib/Transmission/Model/Stats/Session.php",
    "chars": 3902,
    "preview": "<?php\nnamespace Transmission\\Model\\Stats;\n\nuse Transmission\\Model\\AbstractModel;\n\n/**\n * @author Joysen Chellem\n */\nclas"
  },
  {
    "path": "lib/Transmission/Model/Stats/Stats.php",
    "chars": 2865,
    "preview": "<?php\n\nnamespace Transmission\\Model\\Stats;\n\nuse Transmission\\Model\\ModelInterface;\n\n/**\n * @author Joysen Chellem\n */\ncl"
  },
  {
    "path": "lib/Transmission/Model/Status.php",
    "chars": 1790,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * @author Ramon Kleiss <ramonkleiss@gmail.com>\n */\nclass Status extends Abstra"
  },
  {
    "path": "lib/Transmission/Model/Torrent.php",
    "chars": 8598,
    "preview": "<?php\nnamespace Transmission\\Model;\n\nuse Transmission\\Util\\PropertyMapper;\n\n/**\n * @author Ramon Kleiss <ramon@cubilon.n"
  },
  {
    "path": "lib/Transmission/Model/Tracker.php",
    "chars": 1597,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * @author Ramon Kleiss <ramon@cubilon.nl>\n */\nclass Tracker extends AbstractMo"
  },
  {
    "path": "lib/Transmission/Model/TrackerStats.php",
    "chars": 2301,
    "preview": "<?php\nnamespace Transmission\\Model;\n\n/**\n * @author Bilal Ghouri <bilalghouri@live.com>\n */\nclass TrackerStats extends A"
  },
  {
    "path": "lib/Transmission/Transmission.php",
    "chars": 8081,
    "preview": "<?php\nnamespace Transmission;\n\nuse Transmission\\Model\\Torrent;\nuse Transmission\\Model\\Session;\nuse Transmission\\Model\\Fr"
  },
  {
    "path": "lib/Transmission/Util/PropertyMapper.php",
    "chars": 1026,
    "preview": "<?php\nnamespace Transmission\\Util;\n\nuse Transmission\\Model\\ModelInterface;\nuse Symfony\\Component\\PropertyAccess\\Property"
  },
  {
    "path": "lib/Transmission/Util/ResponseValidator.php",
    "chars": 3684,
    "preview": "<?php\nnamespace Transmission\\Util;\n\n/**\n * @author Ramon Kleiss <ramon@cubilon.nl>\n */\nclass ResponseValidator\n{\n    /**"
  },
  {
    "path": "phpunit.xml.dist",
    "chars": 389,
    "preview": "<phpunit bootstrap=\"./tests/bootstrap.php\" colors=\"true\">\n    <testsuites>\n        <testsuite name=\"Transmission Test Su"
  },
  {
    "path": "tests/Transmission/Mock/Model.php",
    "chars": 782,
    "preview": "<?php\nnamespace Transmission\\Mock;\n\nuse Transmission\\Model\\ModelInterface;\n\nclass Model implements ModelInterface\n{\n    "
  },
  {
    "path": "tests/Transmission/Tests/ClientTest.php",
    "chars": 7055,
    "preview": "<?php\nnamespace Transmission\\Tests;\n\nuse Transmission\\Client;\n\nclass ClientTest extends \\PHPUnit_Framework_TestCase\n{\n  "
  },
  {
    "path": "tests/Transmission/Tests/Model/AbstractModelTest.php",
    "chars": 1093,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nclass AbstractModelTest extends \\PHPUnit_Framework_TestCase\n{\n    protected $"
  },
  {
    "path": "tests/Transmission/Tests/Model/FileTest.php",
    "chars": 1473,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\File;\nuse Transmission\\Util\\PropertyMapper;\n\n\nclass Fi"
  },
  {
    "path": "tests/Transmission/Tests/Model/PeerTest.php",
    "chars": 2402,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\Peer;\nuse Transmission\\Util\\PropertyMapper;\n\nclass Pee"
  },
  {
    "path": "tests/Transmission/Tests/Model/SessionTest.php",
    "chars": 4399,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\Session;\nuse Transmission\\Util\\PropertyMapper;\nuse Sym"
  },
  {
    "path": "tests/Transmission/Tests/Model/StatusTest.php",
    "chars": 372,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\Status;\n\nclass StatusTest extends \\PHPUnit_Framework_T"
  },
  {
    "path": "tests/Transmission/Tests/Model/TorrentTest.php",
    "chars": 4387,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\Torrent;\nuse Transmission\\Util\\PropertyMapper;\nuse Sym"
  },
  {
    "path": "tests/Transmission/Tests/Model/TrackerStatsTest.php",
    "chars": 1520,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\TrackerStats;\nuse Transmission\\Util\\PropertyMapper;\n\nc"
  },
  {
    "path": "tests/Transmission/Tests/Model/TrackerTest.php",
    "chars": 1272,
    "preview": "<?php\nnamespace Transmission\\Tests\\Model;\n\nuse Transmission\\Model\\Tracker;\nuse Transmission\\Util\\PropertyMapper;\n\nclass "
  },
  {
    "path": "tests/Transmission/Tests/TransmissionTest.php",
    "chars": 13653,
    "preview": "<?php\nnamespace Transmission\\Tests;\n\nuse Transmission\\Transmission;\nuse Transmission\\Model\\Torrent;\n\nclass TransmissionT"
  },
  {
    "path": "tests/Transmission/Tests/Util/PropertyMapperTest.php",
    "chars": 854,
    "preview": "<?php\nnamespace Transmission\\Tests\\Util;\n\nuse Transmission\\Util\\PropertyMapper;\n\nclass PropertyMapperTest extends \\PHPUn"
  },
  {
    "path": "tests/Transmission/Tests/Util/ResponseValidatorTest.php",
    "chars": 4905,
    "preview": "<?php\nnamespace Transmission\\Tests\\Util;\n\nuse Transmission\\Util\\ResponseValidator;\n\nclass ResponseValidatorTest extends "
  },
  {
    "path": "tests/bootstrap.php",
    "chars": 327,
    "preview": "<?php\nif (!$loader = @include __DIR__.'/../vendor/autoload.php') {\n    echo <<<EOM\n    Install dependencies using Compos"
  }
]

About this extraction

This page contains the full source code of the kleiram/transmission-php GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (112.0 KB), approximately 27.9k tokens, and a symbol index with 362 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!