PageRenderTime 310ms CodeModel.GetById 121ms app.highlight 73ms RepoModel.GetById 108ms app.codeStats 0ms

/library/Zend/File/Transfer/Adapter/Abstract.php

https://bitbucket.org/baruffaldi/cms-php-bfcms
PHP | 1069 lines | 602 code | 111 blank | 356 comment | 100 complexity | 6c56a648ef1620555db73ff84347ae81 MD5 | raw file
   1<?php
   2/**
   3 * Zend Framework
   4 *
   5 * LICENSE
   6 *
   7 * This source file is subject to the new BSD license that is bundled
   8 * with this package in the file LICENSE.txt.
   9 * It is also available through the world-wide-web at this URL:
  10 * http://framework.zend.com/license/new-bsd
  11 * If you did not receive a copy of the license and are unable to
  12 * obtain it through the world-wide-web, please send an email
  13 * to license@zend.com so we can send you a copy immediately.
  14 *
  15 * @category  Zend
  16 * @package   Zend_File_Transfer
  17 * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18 * @license   http://framework.zend.com/license/new-bsd     New BSD License
  19 * @version   $Id: $
  20 */
  21
  22/**
  23 * Abstract class for file transfers (Downloads and Uploads)
  24 *
  25 * @category  Zend
  26 * @package   Zend_File_Transfer
  27 * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  28 * @license   http://framework.zend.com/license/new-bsd     New BSD License
  29 */
  30abstract class Zend_File_Transfer_Adapter_Abstract
  31{
  32    /**@+
  33     * @const string Plugin loader Constants
  34     */
  35    const FILTER    = 'FILTER';
  36    const VALIDATE  = 'VALIDATE';
  37    /**@-*/
  38
  39    /**
  40     * Plugin loaders for filter and validation chains
  41     * @var array
  42     */
  43    protected $_loaders = array();
  44
  45    /**
  46     * Internal list of validators
  47     * @var array
  48     */
  49    protected $_validators = array();
  50
  51    /**
  52     * Internal list of messages
  53     * @var array
  54     */
  55    protected $_messages = array();
  56
  57    /**
  58     * Internal list of filters
  59     * @var array
  60     */
  61    protected $_filters = array();
  62
  63    /**
  64     * Internal validation flag
  65     *
  66     * @var boolean
  67     */
  68    protected $_validated = false;
  69
  70    /**
  71     * Internal list of files
  72     * This array looks like this:
  73     *     array(form => array( - Form is the name within the form or, if not set the filename
  74     *         name,            - Original name of this file
  75     *         type,            - Mime type of this file
  76     *         size,            - Filesize in bytes
  77     *         tmp_name,        - Internalally temporary filename for uploaded files
  78     *         error,           - Error which has occured
  79     *         destination,     - New destination for this file
  80     *         validators,      - Set validator names for this file
  81     *         files            - Set file names for this file
  82     *     ))
  83     *
  84     * @var array
  85     */
  86    protected $_files = array();
  87
  88    /**
  89     * TMP directory
  90     * @var string
  91     */
  92    protected $_tmpDir;
  93
  94    /**
  95     * Options for file transfers
  96     */
  97    protected $_options = array(
  98        'ignoreNoFile' => false
  99    );
 100
 101    /**
 102     * Send file
 103     * 
 104     * @param  mixed $options 
 105     * @return bool
 106     */
 107    abstract public function send($options = null);
 108
 109    /**
 110     * Receive file
 111     * 
 112     * @param  mixed $options 
 113     * @return bool
 114     */
 115    abstract public function receive($options = null);
 116
 117    /**
 118     * Is file sent?
 119     * 
 120     * @param  array|string|null $file 
 121     * @return bool
 122     */
 123    abstract public function isSent($file = null);
 124
 125    /**
 126     * Is file received?
 127     * 
 128     * @param  array|string|null $file 
 129     * @return bool
 130     */
 131    abstract public function isReceived($file = null);
 132
 133    /**
 134     * Retrieve progress of transfer
 135     * 
 136     * @return float
 137     */
 138    abstract public function getProgress();
 139
 140    /**
 141     * Set plugin loader to use for validator or filter chain
 142     * 
 143     * @param  Zend_Loader_PluginLoader_Interface $loader 
 144     * @param  string $type 'filter', or 'validate'
 145     * @return Zend_File_Transfer_Adapter_Abstract
 146     * @throws Zend_File_Transfer_Exception on invalid type
 147     */
 148    public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)
 149    {
 150        $type = strtoupper($type);
 151        switch ($type) {
 152            case self::FILTER:
 153            case self::VALIDATE:
 154                $this->_loaders[$type] = $loader;
 155                return $this;
 156            default:
 157                require_once 'Zend/File/Transfer/Exception.php';
 158                throw new Zend_File_Transfer_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type));
 159        }
 160    }
 161
 162    /**
 163     * Retrieve plugin loader for validator or filter chain
 164     *
 165     * Instantiates with default rules if none available for that type. Use 
 166     * 'filter' or 'validate' for $type.
 167     * 
 168     * @param  string $type 
 169     * @return Zend_Loader_PluginLoader
 170     * @throws Zend_File_Transfer_Exception on invalid type.
 171     */
 172    public function getPluginLoader($type)
 173    {
 174        $type = strtoupper($type);
 175        switch ($type) {
 176            case self::FILTER:
 177            case self::VALIDATE:
 178                $prefixSegment = ucfirst(strtolower($type));
 179                $pathSegment   = $prefixSegment;
 180                if (!isset($this->_loaders[$type])) {
 181                    $paths         = array(
 182                        'Zend_' . $prefixSegment . '_'     => 'Zend/' . $pathSegment . '/',
 183                        'Zend_' . $prefixSegment . '_File' => 'Zend/' . $pathSegment . '/File',
 184                    );
 185
 186                    require_once 'Zend/Loader/PluginLoader.php';
 187                    $this->_loaders[$type] = new Zend_Loader_PluginLoader($paths);
 188                }
 189                return $this->_loaders[$type];
 190            default:
 191                require_once 'Zend/File/Transfer/Exception.php';
 192                throw new Zend_File_Transfer_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
 193        }
 194    }
 195
 196    /**
 197     * Add prefix path for plugin loader
 198     *
 199     * If no $type specified, assumes it is a base path for both filters and 
 200     * validators, and sets each according to the following rules:
 201     * - filters:    $prefix = $prefix . '_Filter'
 202     * - validators: $prefix = $prefix . '_Validate'
 203     *
 204     * Otherwise, the path prefix is set on the appropriate plugin loader.
 205     * 
 206     * @param  string $path 
 207     * @return Zend_File_Transfer_Adapter_Abstract
 208     * @throws Zend_File_Transfer_Exception for invalid type
 209     */
 210    public function addPrefixPath($prefix, $path, $type = null)
 211    {
 212        $type = strtoupper($type);
 213        switch ($type) {
 214            case self::FILTER:
 215            case self::VALIDATE:
 216                $loader = $this->getPluginLoader($type);
 217                $loader->addPrefixPath($prefix, $path);
 218                return $this;
 219            case null:
 220                $prefix = rtrim($prefix, '_');
 221                $path   = rtrim($path, DIRECTORY_SEPARATOR);
 222                foreach (array(self::FILTER, self::VALIDATE) as $type) {
 223                    $cType        = ucfirst(strtolower($type));
 224                    $pluginPath   = $path . DIRECTORY_SEPARATOR . $cType . DIRECTORY_SEPARATOR;
 225                    $pluginPrefix = $prefix . '_' . $cType;
 226                    $loader       = $this->getPluginLoader($type);
 227                    $loader->addPrefixPath($pluginPrefix, $pluginPath);
 228                }
 229                return $this;
 230            default:
 231                require_once 'Zend/File/Transfer/Exception.php';
 232                throw new Zend_File_Transfer_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
 233        }
 234    }
 235
 236    /**
 237     * Add many prefix paths at once
 238     * 
 239     * @param  array $spec 
 240     * @return Zend_File_Transfer_Exception
 241     */
 242    public function addPrefixPaths(array $spec)
 243    {
 244        if (isset($spec['prefix']) && isset($spec['path'])) {
 245            return $this->addPrefixPath($spec['prefix'], $spec['path']);
 246        } 
 247        foreach ($spec as $type => $paths) {
 248            if (is_numeric($type) && is_array($paths)) {
 249                $type = null;
 250                if (isset($paths['prefix']) && isset($paths['path'])) {
 251                    if (isset($paths['type'])) {
 252                        $type = $paths['type'];
 253                    }
 254                    $this->addPrefixPath($paths['prefix'], $paths['path'], $type);
 255                }
 256            } elseif (!is_numeric($type)) {
 257                if (!isset($paths['prefix']) || !isset($paths['path'])) {
 258                    foreach ($paths as $prefix => $spec) {
 259                        if (is_array($spec)) {
 260                            foreach ($spec as $path) {
 261                                if (!is_string($path)) {
 262                                    continue;
 263                                }
 264                                $this->addPrefixPath($prefix, $path, $type);
 265                            }
 266                        } elseif (is_string($spec)) {
 267                            $this->addPrefixPath($prefix, $spec, $type);
 268                        }
 269                    }
 270                } else {
 271                    $this->addPrefixPath($paths['prefix'], $paths['path'], $type);
 272                }
 273            }
 274        }
 275        return $this;
 276    }
 277
 278    /**
 279     * Adds a new validator for this class
 280     *
 281     * @param  string|array $validator Type of validator to add
 282     * @param  string|array $options   Options to set for the validator
 283     * @param  string|array $files     Files to limit this validator to
 284     * @return Zend_File_Transfer_Adapter
 285     */
 286    public function addValidator($validator, $options = null, $files = null)
 287    {
 288        if ($validator instanceof Zend_Validate_Interface) {
 289            $class = get_class($validator);
 290        } elseif (is_string($validator)) {
 291            $class     = $this->getPluginLoader(self::VALIDATE)->load($validator);
 292            $validator = new $class($options);
 293        } else {
 294            require_once 'Zend/File/Transfer/Exception.php';
 295            throw new Zend_File_Transfer_Exception('Invalid validator specified');
 296        }
 297
 298        $this->_validators[$class] = $validator;
 299
 300        if ($files === null) {
 301            $files = array_keys($this->_files);
 302        } else {
 303            if (!is_array($files)) {
 304                $files = array($files);
 305            }
 306        }
 307
 308        foreach ($files as $key => $file) {
 309            if (!is_string($file)) {
 310                if (is_array($file) && !is_numeric($key)) {
 311                    $file = $key;
 312                } else {
 313                    continue;
 314                }
 315            }
 316            if (!array_key_exists($file, $this->_files)) {
 317                continue;
 318            }
 319            $this->_files[$file]['validators'][] = $class;
 320        }
 321        
 322        $this->_validated = false;
 323        return $this;
 324    }
 325
 326    /**
 327     * Add Multiple validators at once
 328     * 
 329     * @param  array $validators 
 330     * @param  string|array $files 
 331     * @return Zend_File_Transfer_Adapter_Abstract
 332     */
 333    public function addValidators(array $validators, $files = null)
 334    {
 335        foreach ($validators as $key => $spec) {
 336            if ($spec instanceof Zend_Validate_Interface) {
 337                $this->addValidator($spec, null, $files);
 338                continue;
 339            }
 340
 341            if (is_string($key)) {
 342                $this->addValidator($key, $spec, $files);
 343                continue;
 344            }
 345
 346            if (is_int($key)) {
 347                if (is_string($spec)) {
 348                    $this->addValidator($spec, null, $files);
 349                    continue;
 350                }
 351
 352                if (is_array($spec)) {
 353                    if (!array_key_exists('validator', $spec)) {
 354                        continue;
 355                    }
 356
 357                    $validator = $spec['validator'];
 358                    unset($spec['validator']);
 359                    $this->addValidator($validator, $spec, $files);
 360                    continue;
 361                }
 362
 363                continue;
 364            }
 365        }
 366
 367        return $this;
 368    }
 369
 370    /**
 371     * Sets a validator for the class, erasing all previous set
 372     *
 373     * @param  string|array $validator Validator to set
 374     * @param  string|array $files     Files to limit this validator to
 375     * @return Zend_File_Transfer_Adapter
 376     */
 377    public function setValidators(array $validators, $files = null)
 378    {
 379        $this->clearValidators();
 380        return $this->addValidators($validators, $files);
 381    }
 382
 383    /**
 384     * Determine if a given validator has already been registered
 385     * 
 386     * @param  string $name 
 387     * @return bool
 388     */
 389    public function hasValidator($name)
 390    {
 391        return (false !== $this->_getValidatorIdentifier($name));
 392    }
 393
 394    /**
 395     * Retrieve individual validator
 396     * 
 397     * @param  string $name 
 398     * @return Zend_Validate_Interface|null
 399     */
 400    public function getValidator($name)
 401    {
 402        if (false === ($identifier = $this->_getValidatorIdentifier($name))) {
 403            return null;
 404        }
 405        return $this->_validators[$identifier];
 406    }
 407
 408    /**
 409     * Returns all set validators
 410     *
 411     * @param  string|array $files (Optional) Returns the validator for this files
 412     * @return null|array List of set validators
 413     * @throws Zend_File_Transfer_Exception When file not found
 414     */
 415    public function getValidators($files = null)
 416    {
 417        if ($files === null) {
 418            return $this->_validators;
 419        }
 420
 421        if (!is_array($files)) {
 422            $files = array($files);
 423        }
 424
 425        $validators = array();
 426        foreach ($files as $file) {
 427            if (!isset($this->_files[$file])) {
 428                require_once 'Zend/File/Transfer/Exception.php';
 429                throw new Zend_File_Transfer_Exception('Unknown file');
 430            }
 431            $validators += $this->_files[$file]['validators'];
 432        }
 433        $validators = array_unique($validators);
 434
 435        foreach ($validators as $validator) {
 436            $result[] = $this->_validators[$validator];
 437        }
 438        return $result;
 439    }
 440
 441    /**
 442     * Remove an individual validator 
 443     * 
 444     * @param  string $name 
 445     * @return Zend_File_Transfer_Adapter_Abstract
 446     */
 447    public function removeValidator($name)
 448    {
 449        if (false === ($key = $this->_getValidatorIdentifier($name))) {
 450            return $this;
 451        }
 452
 453        unset($this->_validators[$key]);
 454        foreach (array_keys($this->_files) as $file) {
 455            if (!$index = array_search($key, $this->_files[$file]['validators'])) {
 456                continue;
 457            }
 458            unset($this->_files[$file]['validators'][$index]);
 459        }
 460
 461        $this->_validated = false;
 462        return $this;
 463    }
 464
 465    /**
 466     * Remove all validators
 467     * 
 468     * @return Zend_File_Transfer_Adapter_Abstract
 469     */
 470    public function clearValidators()
 471    {
 472        $this->_validators = array();
 473        foreach (array_keys($this->_files) as $file) {
 474            $this->_files[$file]['validators'] = array();
 475        }
 476
 477        $this->_validated = false;
 478        return $this;
 479    }
 480
 481    /**
 482     * Sets Options for adapters
 483     *
 484     * @param array $options
 485     */
 486    public function setOptions($options = array()) {
 487        if (is_array($options)) {
 488            foreach ($options as $name => $value) {
 489                if (array_key_exists($name, $this->_options)) {
 490                    $this->_options[$name] = (boolean) $value;
 491                } else {
 492                    require_once 'Zend/File/Transfer/Exception.php';
 493                    throw new Zend_File_Transfer_Exception("Unknown option: $name = $value");
 494                }
 495            }
 496        }
 497
 498        return $this;
 499    }
 500
 501    /**
 502     * Returns set options for adapters
 503     *
 504     * @param array $options
 505     */
 506    public function getOptions() {
 507        return $this->_options;
 508    }
 509
 510    /**
 511     * Checks if the files are valid
 512     *
 513     * @param  string|array $files (Optional) Files to check
 514     * @return boolean True if all checks are valid
 515     */
 516    public function isValid($files = null)
 517    {
 518        $check           = $this->_getFiles($files);
 519        $this->_messages = array();
 520        foreach ($check as $content) {
 521            $uploaderror = false;
 522            $fileerrors  = array();
 523            if (array_key_exists('validators', $content)) {
 524                foreach ($content['validators'] as $class) {
 525                    $validator = $this->_validators[$class];
 526                    if (!$uploaderror and !$validator->isValid($content['tmp_name'], $content)) {
 527                        $fileerrors += $validator->getMessages();
 528                    }
 529
 530                    if (($class === 'Zend_Validate_File_Upload') and (count($this->_messages) > 0)) {
 531                            $uploaderror = true;
 532                    }
 533                }
 534            }
 535
 536            if ($this->_options['ignoreNoFile'] and (isset($fileerrors['fileUploadErrorNoFile']))) {
 537                $fileerrors = array();
 538            }
 539
 540            $this->_messages += $fileerrors;
 541        }
 542
 543        if (count($this->_messages) > 0) {
 544            $this->_validated = false;
 545            return false;
 546        }
 547
 548        $this->_validated = true;
 549        return true;
 550    }
 551
 552    /**
 553     * Returns found validation messages
 554     *
 555     * @return array
 556     */
 557    public function getMessages()
 558    {
 559        return $this->_messages;
 560    }
 561
 562    /**
 563     * Retrieve error codes
 564     * 
 565     * @return array
 566     */
 567    public function getErrors()
 568    {
 569        return array_keys($this->_messages);
 570    }
 571
 572    /**
 573     * Adds a new filter for this class
 574     *
 575     * @param  string|array $filter Type of filter to add
 576     * @param  string|array $options   Options to set for the filter
 577     * @param  string|array $files     Files to limit this filter to
 578     * @return Zend_File_Transfer_Adapter
 579     */
 580    public function addFilter($filter, $options = null, $files = null)
 581    {
 582        if ($filter instanceof Zend_Filter_Interface) {
 583            $class = get_class($filter);
 584        } elseif (is_string($filter)) {
 585            $class  = $this->getPluginLoader(self::FILTER)->load($filter);
 586            $filter = new $class($options);
 587        } else {
 588            require_once 'Zend/File/Transfer/Exception.php';
 589            throw new Zend_File_Transfer_Exception('Invalid filter specified');
 590        }
 591
 592        $this->_filters[$class] = $filter;
 593
 594        if ($files === null) {
 595            $files = array_keys($this->_files);
 596        } else {
 597            if (!is_array($files)) {
 598                $files = array($files);
 599            }
 600        }
 601
 602        foreach ($files as $key => $file) {
 603            if (!is_string($file)) {
 604                if (is_array($file) && !is_numeric($key)) {
 605                    $file = $key;
 606                } else {
 607                    continue;
 608                }
 609            }
 610
 611            if (!array_key_exists($file, $this->_files)) {
 612                continue;
 613            }
 614
 615            $this->_files[$file]['filters'][] = $class;
 616        }
 617        
 618        return $this;
 619    }
 620
 621    /**
 622     * Add Multiple filters at once
 623     * 
 624     * @param  array $filters 
 625     * @param  string|array $files 
 626     * @return Zend_File_Transfer_Adapter_Abstract
 627     */
 628    public function addFilters(array $filters, $files = null)
 629    {
 630        foreach ($filters as $key => $spec) {
 631            if ($spec instanceof Zend_Filter_Interface) {
 632                $this->addFilter($spec, null, $files);
 633                continue;
 634            }
 635
 636            if (is_string($key)) {
 637                $this->addFilter($key, $spec, $files);
 638                continue;
 639            }
 640
 641            if (is_int($key)) {
 642                if (is_string($spec)) {
 643                    $this->addFilter($spec, null, $files);
 644                    continue;
 645                }
 646
 647                if (is_array($spec)) {
 648                    if (!array_key_exists('filter', $spec)) {
 649                        continue;
 650                    }
 651
 652                    $filter = $spec['filter'];
 653                    unset($spec['filter']);
 654                    $this->addFilter($filter, $spec, $files);
 655                    continue;
 656                }
 657
 658                continue;
 659            }
 660        }
 661
 662        return $this;
 663    }
 664
 665    /**
 666     * Sets a filter for the class, erasing all previous set
 667     *
 668     * @param  string|array $filter Filter to set
 669     * @param  string|array $files     Files to limit this filter to
 670     * @return Zend_File_Transfer_Adapter
 671     */
 672    public function setFilters(array $filters, $files = null)
 673    {
 674        $this->clearFilters();
 675        return $this->addFilters($filters, $files);
 676    }
 677
 678    /**
 679     * Determine if a given filter has already been registered
 680     * 
 681     * @param  string $name 
 682     * @return bool
 683     */
 684    public function hasFilter($name)
 685    {
 686        return (false !== $this->_getFilterIdentifier($name));
 687    }
 688
 689    /**
 690     * Retrieve individual filter
 691     * 
 692     * @param  string $name 
 693     * @return Zend_Filter_Interface|null
 694     */
 695    public function getFilter($name)
 696    {
 697        if (false === ($identifier = $this->_getFilterIdentifier($name))) {
 698            return null;
 699        }
 700        return $this->_filters[$identifier];
 701    }
 702
 703    /**
 704     * Returns all set filters
 705     *
 706     * @param  string|array $files (Optional) Returns the filter for this files
 707     * @return null|array List of set filters
 708     * @throws Zend_File_Transfer_Exception When file not found
 709     */
 710    public function getFilters($files = null)
 711    {
 712        if ($files === null) {
 713            return $this->_filters;
 714        }
 715
 716        if (!is_array($files)) {
 717            $files = array($files);
 718        }
 719
 720        $filters = array();
 721        foreach ($files as $file) {
 722            if (!isset($this->_files[$file])) {
 723                require_once 'Zend/File/Transfer/Exception.php';
 724                throw new Zend_File_Transfer_Exception('Unknown file');
 725            }
 726            $filters += $this->_files[$file]['filters'];
 727        }
 728        $filters = array_unique($filters);
 729
 730        foreach ($filters as $filter) {
 731            $result[] = $this->_filters[$filter];
 732        }
 733        return $result;
 734    }
 735
 736    /**
 737     * Remove an individual filter 
 738     * 
 739     * @param  string $name 
 740     * @return Zend_File_Transfer_Adapter_Abstract
 741     */
 742    public function removeFilter($name)
 743    {
 744        if (false === ($key = $this->_getFilterIdentifier($name))) {
 745            return $this;
 746        }
 747
 748        unset($this->_filters[$key]);
 749        foreach (array_keys($this->_files) as $file) {
 750            if (!$index = array_search($key, $this->_files[$file]['filters'])) {
 751                continue;
 752            }
 753            unset($this->_files[$file]['filters'][$index]);
 754        }
 755        return $this;
 756    }
 757
 758    /**
 759     * Remove all filters
 760     * 
 761     * @return Zend_File_Transfer_Adapter_Abstract
 762     */
 763    public function clearFilters()
 764    {
 765        $this->_filters = array();
 766        foreach (array_keys($this->_files) as $file) {
 767            $this->_files[$file]['filters'] = array();
 768        }
 769        return $this;
 770    }
 771
 772    /**
 773     * Returns all set files
 774     *
 775     * @return array List of set files
 776     * @throws Zend_File_Transfer_Exception Not implemented
 777     */
 778    public function getFile()
 779    {
 780        require_once 'Zend/File/Transfer/Exception.php';
 781        throw new Zend_File_Transfer_Exception('Method not implemented');
 782    }
 783
 784    /**
 785     * Retrieve filename of transferred file
 786     *
 787     * Returns final target destnation of transferred file.
 788     * 
 789     * @param  string $file 
 790     * @return string
 791     */
 792    public function getFileName($file)
 793    {
 794        $file = (string) $file;
 795        if (!array_key_exists($file, $this->_files)) {
 796             return null;
 797        }
 798
 799        $directory = $this->getDestination($file);
 800        return $directory . DIRECTORY_SEPARATOR . $this->_files[$file]['name'];
 801    }
 802
 803    /**
 804     * Adds one or more files
 805     *
 806     * @param  string|array $file      File to add
 807     * @param  string|array $validator Validators to use for this file, must be set before
 808     * @param  string|array $filter    Filters to use for this file, must be set before
 809     * @return Zend_File_Transfer_Adapter_Abstract
 810     * @throws Zend_File_Transfer_Exception Not implemented
 811     */
 812    public function addFile($file, $validator = null, $filter = null)
 813    {
 814        require_once 'Zend/File/Transfer/Exception.php';
 815        throw new Zend_File_Transfer_Exception('Method not implemented');
 816    }
 817
 818    /**
 819     * Returns all set types
 820     *
 821     * @return array List of set types
 822     * @throws Zend_File_Transfer_Exception Not implemented
 823     */
 824    public function getType()
 825    {
 826        require_once 'Zend/File/Transfer/Exception.php';
 827        throw new Zend_File_Transfer_Exception('Method not implemented');
 828    }
 829
 830    /**
 831     * Adds one or more type of files
 832     *
 833     * @param  string|array $type Type of files to add
 834     * @param  string|array $validator Validators to use for this file, must be set before
 835     * @param  string|array $filter    Filters to use for this file, must be set before
 836     * @return Zend_File_Transfer_Adapter_Abstract
 837     * @throws Zend_File_Transfer_Exception Not implemented
 838     */
 839    public function addType($type, $validator = null, $filter = null)
 840    {
 841        require_once 'Zend/File/Transfer/Exception.php';
 842        throw new Zend_File_Transfer_Exception('Method not implemented');
 843    }
 844
 845    /**
 846     * Sets a new destination for the given files
 847     *
 848     * @deprecated Will be changed to be a filter!!!
 849     * @param  string       $destination New destination directory
 850     * @param  string|array $files       Files to set the new destination for
 851     * @return Zend_File_Transfer_Abstract
 852     */
 853    public function setDestination($destination, $files = null)
 854    {
 855        if ($files === null) {
 856            foreach ($this->_files as $file => $content) {
 857                $this->_files[$file]['destination'] = $destination;
 858            }
 859        } else {
 860            if (!is_array($files)) {
 861                $files = array($files);
 862            }
 863
 864            foreach ($files as $file) {
 865                $this->_files[$file]['destination'] = $destination;
 866            }
 867        }
 868
 869        return $this;
 870    }
 871
 872    /**
 873     * Retrieve destination directory value
 874     * 
 875     * @param  null|string|array $files 
 876     * @return null|string|array
 877     */
 878    public function getDestination($files = null)
 879    {
 880        if ((null === $files) || is_array($files)) {
 881            $destinations = array();
 882            if (!is_array($files)) {
 883                $files = $this->_files;
 884            } else {
 885                $files = array_flip($files);
 886                $files = array_intersect_assoc($files, $this->_files);
 887            }
 888            foreach ($files as $file => $content) {
 889                if (array_key_exists('destination', $content)) {
 890                    $destinations[$file] = $content['destination'];
 891                } else {
 892                    $tmpdir = $this->_getTmpDir();
 893                    $this->setDestination($tmpdir, $file);
 894                    $destinations[$file] = $tmpdir;
 895                }
 896            }
 897            return $destinations;
 898        }
 899
 900        if (!is_string($files)) {
 901            require_once 'Zend/File/Transfer/Exception.php';
 902            throw new Zend_File_Transfer_Exception('Invalid file value passed to getDestination()');
 903        }
 904
 905        if (!array_key_exists($files, $this->_files)) {
 906            require_once 'Zend/File/Transfer/Exception.php';
 907            throw new Zend_File_Transfer_Exception(sprintf('Unknown file "%s" passed to getDestination()', $files));
 908        }
 909
 910        if (!array_key_exists('destination', $this->_files[$files])) {
 911            return $this->_getTmpDir();
 912        }
 913
 914        return $this->_files[$files]['destination'];
 915    }
 916
 917    /**
 918     * Internal function to filter all given files
 919     *
 920     * @param  string|array $files (Optional) Files to check
 921     * @return boolean False on error
 922     */
 923    protected function _filter($files = null)
 924    {
 925        $check           = $this->_getFiles($files);
 926        foreach ($check as $name => $content) {
 927            if (array_key_exists('filters', $content)) {
 928                foreach ($content['filters'] as $class) {
 929                    $filter = $this->_filters[$class];
 930                    try {
 931                        $result = $filter->filter($this->getFileName($name));
 932
 933                        $this->_files[$name]['destination'] = dirname($result);
 934                        $this->_files[$name]['name']        = basename($result);
 935                    } catch (Zend_Filter_Exception $e) {
 936                        $this->_messages += array($e->getMessage());
 937                    }
 938                }
 939            }
 940        }
 941
 942        if (count($this->_messages) > 0) {
 943            return false;
 944        }
 945
 946        return true;
 947    }
 948
 949    /**
 950     * Determine system TMP directory
 951     * 
 952     * @return string
 953     * @throws Zend_File_Transfer_Exception if unable to determine directory
 954     */
 955    protected function _getTmpDir()
 956    {
 957        if (null === $this->_tmpDir) {
 958            if (function_exists('sys_get_temp_dir')) {
 959                $tmpdir = sys_get_temp_dir();
 960            } elseif (!empty($_ENV['TMP'])) {
 961                $tmpdir = realpath($_ENV['TMP']);
 962            } elseif (!empty($_ENV['TMPDIR'])) {
 963                $tmpdir = realpath($_ENV['TMPDIR']);
 964            } else if (!empty($_ENV['TEMP'])) {
 965                $tmpdir = realpath($_ENV['TEMP']);
 966            } else {
 967                // Attemp to detect by creating a temporary file
 968                $tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
 969                if ($tempFile) {
 970                    $tmpdir = realpath(dirname($tempFile));
 971                    unlink($tempFile);
 972                } else {
 973                    require_once 'Zend/File/Transfer/Exception.php';
 974                    throw new Zend_File_Transfer_Exception('Could not determine temp directory');
 975                }
 976            }
 977            $this->_tmpDir = rtrim($tmpdir, "/\\");
 978        }
 979        return $this->_tmpDir;
 980    }
 981
 982    /**
 983     * Returns found files based on internal file array and given files
 984     *
 985     * @param  string|array $files (Optional) Files to return
 986     * @return array Found files
 987     * @throws Zend_File_Transfer_Exception On false filename
 988     */
 989    protected function _getFiles($files)
 990    {
 991        $check = null;
 992
 993        if (is_string($files)) {
 994            $files = array($files);
 995        }
 996
 997        if (is_array($files)) {
 998            foreach ($files as $find) {
 999                $found = null;
1000                foreach ($this->_files as $file => $content) {
1001                    if ($content['name'] === $find) {
1002                        $found = $file;
1003                        break;
1004                    }
1005
1006                    if ($file === $find) {
1007                        $found = $file;
1008                        break;
1009                    }
1010                }
1011
1012                if ($found === null) {
1013                    require_once 'Zend/File/Transfer/Exception.php';
1014                    throw new Zend_File_Transfer_Exception(sprintf('"%s" not found by file transfer adapter', $file));
1015                }
1016
1017                $check[$found] = $this->_files[$found];
1018            }
1019        }
1020
1021        if ($files === null) {
1022            $check = $this->_files;
1023        }
1024
1025        return $check;
1026    }
1027
1028    /**
1029     * Retrieve internal identifier for a named validator
1030     * 
1031     * @param  string $name 
1032     * @return string
1033     */
1034    protected function _getValidatorIdentifier($name)
1035    {
1036        if (array_key_exists($name, $this->_validators)) {
1037            return $name;
1038        }
1039
1040        foreach (array_keys($this->_validators) as $test) {
1041            if (preg_match('/' . preg_quote($name) . '$/i', $test)) {
1042                return $test;
1043            }
1044        }
1045
1046        return false;
1047    }
1048
1049    /**
1050     * Retrieve internal identifier for a named filter
1051     * 
1052     * @param  string $name 
1053     * @return string
1054     */
1055    protected function _getFilterIdentifier($name)
1056    {
1057        if (array_key_exists($name, $this->_filters)) {
1058            return $name;
1059        }
1060
1061        foreach (array_keys($this->_filters) as $test) {
1062            if (preg_match('/' . preg_quote($name) . '$/i', $test)) {
1063                return $test;
1064            }
1065        }
1066
1067        return false;
1068    }
1069}