<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_File
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

/**
 * @category   Core
 * @package    Core_File
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 * @group      Core_File
 */
class Core_FileTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Core_File
     */
    protected $_object;
    protected $_files;
    protected $_libmagicVersion;

    protected function setUp()
    {
        $this->_object = new Core_File('/path');

        // where are the file fixtures?
        $this->_files  = TESTS_ROOT .'/resources/fixtures/Core/File';
    }

    /**
     * @covers Core_File::__construct
     */
    public function testCanSetNamePathSizeAndTypeViaConstructor()
    {
        $object = new Core_File('/tmp/name.doc', 'name.doc', 23, 'application/octet-stream');

        $this->assertEquals('/tmp/name.doc', $object->getPath());
        $this->assertEquals('name.doc', $object->getName());
        $this->assertEquals(23, $object->getSize());
        $this->assertEquals('application/octet-stream', $object->getType());
    }

    /**
     * @covers Core_File::setPath
     * @covers Core_File::getPath
     */
    public function testCanSetAndGetPath()
    {
        $this->_object->setPath('/some/path');
        $this->assertEquals('/some/path', $this->_object->getPath());
    }

    /**
     * @covers Core_File::setName
     * @covers Core_File::getName
     */
    public function testCanSetAndGetName()
    {
        $this->_object->setPath('somename.txt');
        $this->assertEquals('somename.txt', $this->_object->getName());
    }

    /**
     * @covers Core_File::getName
     */
    public function testIfNoNameSpecifiedItWillBePathBasename()
    {
        $this->_object->setPath('/some/path/somename.txt');
        $this->assertEquals('somename.txt', $this->_object->getName());
    }

    /**
     * @covers Core_File::setSize
     * @covers Core_File::getSize
     */
    public function testCanSetAndGetSize()
    {
        $this->_object->setSize(33);
        $this->assertEquals(33, $this->_object->getSize());
    }

    /**
     * @covers Core_File::getSize
     */
    public function testIfNoSizeSpecifiedItWillBeReadFromPath()
    {
        $path = __FILE__;
        $this->_object->setPath($path);

        $this->assertEquals(filesize($path), $this->_object->getSize());
    }

    /**
     * @covers Core_File::setType
     * @covers Core_File::getType
     */
    public function testCanSetAndGetType()
    {
        $this->_object->setType('text/plain');
        $this->assertEquals('text/plain', $this->_object->getType());
    }

    /**
     * @covers Core_File::getType
     * @covers Core_File::getMimeType
     */
    public function testWillStripParamsFromMime()
    {
        $this->assertEquals('text/plain', $this->_object->getType('text/plain; charset=UTF-8'));
    }

    /**
     * @covers Core_File::getType
     * @covers Core_File::getMimeType
     */
    public function testWillStripParamsFromInvalidMime()
    {
        $this->assertEquals('text/plain', $this->_object->getType('text/plain charset=UTF-8'));
    }

    /**
     * @covers Core_File::setExtension
     * @covers Core_File::getExtension
     */
    public function testCanSetAndGetExtension()
    {
        $this->_object->setExtension('tiff');
        $this->assertEquals('tiff', $this->_object->getExtension());
    }

    /**
     * @covers Core_File::getExtension
     */
    public function testIfNoExtensionSpecifiedItWillBeReadFromName()
    {
        $this->_object->setName('some.name.ext');

        $this->assertEquals('ext', $this->_object->getExtension());
    }

    /**
     * @covers Core_File::getExtension
     */
    public function testIfNoExtensionSpecifiedAndFilenameIsWithoutExtensionItWillBeAnEmptyString()
    {
        $this->_object->setName('some-name-ext');

        $this->assertEquals('', $this->_object->getExtension());
    }


    /**
     * @param string $path            File path (inside the $this->_files namespace)
     * @param string $type            Expected file MIME type
     * @param string $requiredVersion The minimum libmagic version that will recognize this.
     *
     * @covers Core_File::getType
     * @covers Core_File::getMimeType
     * @dataProvider pathsToTypes
     * @large
     * @group  mimetype
     */
    public function testIfNoTypeSpecifiedItWillBeReadFromPath($path, $type, $requiredVersion = null)
    {
        if (null !== $requiredVersion) {
            $version = $this->_getLibmagicVersion();
            if (!$version) {
                $this->markTestSkipped('Core_File::getType() requires libmagic');
            } else if (floatval($requiredVersion) > floatval($version)) {
                $this->markTestSkipped(
                    sprintf(
                        'Core_File::getType(%s) requires libmagic >= %s, libmagic %s found',
                        $path,
                        $requiredVersion,
                        $version
                    )
                );
            }
        }


        $this->_object->setPath($this->_files . $path);

        $this->assertEquals($type, $this->_object->getType());
    }

    public function pathsToTypes()
    {
        // file, expected MIME type
        // paths are relative to $this->_files
        return array(
            // PLEASE NOTE:
            // there are *not recognized* by the underlying system, it's not safe to use this MIME type!
            //
            // application/octet-stream
            array(
                '/application/octet-stream/application-octet-stream-charset-binary.f4v',
                'application/octet-stream',
                '4.0'
            ),

            // application/*
            array(
                '/application/application-zip-charset-binary.zip',
                'application/zip', '4.0'
            ),
            array(
                '/application/application-7z-charset-binary.7z',
                'application/7z',
                '5.1'
            ),
            array(
                '/application/application-zip-charset-binary.docx',
                'application/vnd.microsoft.office.word',
                '5.1'
            ),
            array(
                '/application/application-zip-charset-binary.pptx',
                'application/vnd.microsoft.office.powerpoint',
                '5.1'
            ),
            array(
                '/application/application-zip-charset-binary.xlsx',
                'application/vnd.microsoft.office.excel',
                '5.1'
            ),
            array(
                '/application/application-msword-charset-binary.doc',
                'application/vnd.microsoft.office.word',
                '4.0'
            ),
            array(
                '/application/application-vnd.ms-office-charset-binary.ppt',
                'application/vnd.microsoft.office.powerpoint',
                '5.1'
            ),
            array(
                '/application/application-vnd.ms-office-charset-binary.xls',
                'application/vnd.microsoft.office.excel',
                '5.0'
            ),
            array(
                '/application/application-pdf-charset-binary.pdf',
                'application/pdf',
                '4.0'
            ),

            // audio/*
            array('/audio/audio-mpeg-charset-binary-original.mp3',             'audio/mpeg', '4.0'),
            array('/audio/audio-mpeg-charset-binary-96K.mp3',                  'audio/mpeg', '4.0'),
            array('/application/application-ogg-charset-binary-96K.ogg',       'audio/ogg',  '4.0'),

            // image/*
            array('/image/image-bmp-charset-binary.bmp',                       'image/bmp',  '4.0'),
            array('/image/image-gif-charset-binary.gif',                       'image/gif',  '4.0'),
            array('/image/image-png-charset-binary.png',                       'image/png',  '4.0'),
            array('/image/image-jpeg-charset-binary.jpeg',                     'image/jpeg', '4.0'),

            // text/*
            array('/text/text-plain-charset-ascii.txt',                        'text/plain', '4.0'),
            array('/text/text-plain-charset-utf8.txt',                         'text/plain', '4.0'),
            array('/text/text-plain-charset-utf8-bom.txt',                     'text/plain', '4.0'),

            // video/*
            array('/video/video-flv-charset-binary-original.flv',              'video/flv',       '4.0'),
            array('/video/video-flv-charset-binary-1Mbps-F6.flv',              'video/flv',       '4.0'),
            array('/video/video-flv-charset-binary-1Mbps-F8.flv',              'video/flv',       '4.0'),
            array('/video/video-mp4-charset-binary-original.mp4',              'video/mp4',       '4.0'),
            array('/video/video-mp4-charset-binary-1Mbps.mp4',                 'video/mp4',       '4.0'),
            array('/video/video-mp4-charset-binary-1Mbps-F9.mp4',              'video/mp4',       '4.0'),
            array('/video/video-quicktime-charset-binary-1Mbps.mov',           'video/quicktime', '4.0'),
            array('/video/video-webm-charset-binary-720p.webm',                'video/webm',      '5.1'),
            array('/video/video-asf-charset-binary.wmv',                       'video/amf',       '5.1'),
        );
    }

    protected function _getLibmagicVersion()
    {
        if (null === $this->_libmagicVersion) {
            $ret    = 0;
            $output = array();
            exec('env file -v 2>&1', $output);
            if (preg_match('/^file-([\d\.]*)/', current($output), $matches)) {
                $this->_libmagicVersion = $matches[1];
            } else {
                $this->_libmagicVersion = false;
            }
        }
        return $this->_libmagicVersion;
    }
}
