#!/usr/bin/php
<?php
/**
 * Copyright © OXID eSales AG. All rights reserved.
 * See LICENSE file for license details.
 */

/**
 * Configure the database connection to your OXID eShop 6 database
 */
$dbHost = "localhost";
$dbUser = "";
$dbPassword = "";
$dbName = "";


// == LOGIC SECTION ===================================================================

class MediaGalleryIndexer
{

    protected $_sMediaPath = '/out/pictures/ddmedia/';
    protected $_iDefaultThumbnailSize = 185;

    /**
     * @var PDO
     */
    private $pdo = null;

    /**
     * @param string       $sFile
     * @param null|integer $iThumbSize
     *
     * @return bool|string
     */
    public function getThumbnailUrl($sFile = '', $iThumbSize = null)
    {
        if ($sFile) {
            if (!$iThumbSize) {
                $iThumbSize = $this->_iDefaultThumbnailSize;
            }

            $sThumbName = $this->getThumbName($sFile, $iThumbSize);

            if ($sThumbName) {
                return $this->getMediaUrl('thumbs/' . $sThumbName);
            }
        } else {
            return $this->getMediaUrl('thumbs/');
        }

        return false;
    }


    /**
     * @param string       $sFile
     * @param null|integer $iThumbSize
     *
     * @return string
     */
    public function getThumbName($sFile, $iThumbSize = null)
    {
        if (!$iThumbSize) {
            $iThumbSize = $this->_iDefaultThumbnailSize;
        }

        return str_replace('.', '_', md5(basename($sFile))) . '_thumb_' . $iThumbSize . '.jpg';
    }

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


    /**
     * Create directories
     */
    public function createDirs()
    {
        if (!is_dir($this->getMediaPath())) {
            mkdir($this->getMediaPath());
        }

        if (!is_dir($this->getThumbnailPath())) {
            mkdir($this->getThumbnailPath());
        }
    }

    /**
     * @param string $sFile
     *
     * @return string
     */
    public function getThumbnailPath($sFile = '')
    {
        $sPath = $this->getMediaPath() . 'thumbs/';

        if ($sFile) {
            return $sPath . $sFile;
        }

        return $sPath;
    }

    /**
     * @param string       $sFileName
     * @param null|integer $iThumbSize
     * @param bool         $blCrop
     *
     * @return bool|string
     * @throws Exception
     */
    public function createThumbnail($sFileName, $iThumbSize = null, $blCrop = true)
    {
        $sFilePath = $this->getMediaPath($sFileName);

        if (is_readable($sFilePath)) {
            if (!$iThumbSize) {
                $iThumbSize = $this->_iDefaultThumbnailSize;
            }

            list($iImageWidth, $iImageHeight, $iImageType) = getimagesize($sFilePath);

            switch ($iImageType) {
                case 1:
                    $rImg = imagecreatefromgif($sFilePath);
                    break;

                case 2:
                    $rImg = imagecreatefromjpeg($sFilePath);
                    break;

                case 3:
                    $rImg = imagecreatefrompng($sFilePath);
                    break;

                default:
                    throw new Exception('Invalid filetype');
                    break;
            }

            $iThumbWidth = $iImageWidth;
            $iThumbHeight = $iImageHeight;

            $iThumbX = 0;
            $iThumbY = 0;

            if ($blCrop) {
                if ($iImageWidth < $iImageHeight) {
                    $iThumbWidth = $iThumbSize;
                    $iThumbHeight = $iImageHeight / ($iImageWidth / $iThumbWidth);

                    $iThumbY = (($iThumbSize - $iThumbHeight) / 2);
                } elseif ($iImageHeight < $iImageWidth) {
                    $iThumbHeight = $iThumbSize;
                    $iThumbWidth = $iImageWidth / ($iImageHeight / $iThumbHeight);

                    $iThumbX = (($iThumbSize - $iThumbWidth) / 2);
                }
            } else {
                if ($iImageWidth < $iImageHeight) {
                    if ($iImageHeight > $iThumbSize) {
                        $iThumbWidth *= ($iThumbSize / $iImageHeight);
                        $iThumbHeight *= ($iThumbSize / $iImageHeight);
                    }
                } elseif ($iImageHeight < $iImageWidth) {
                    if ($iImageHeight > $iThumbSize) {
                        $iThumbWidth *= ($iThumbSize / $iImageWidth);
                        $iThumbHeight *= ($iThumbSize / $iImageWidth);
                    }
                }
            }

            $rTmpImg = imagecreatetruecolor($iThumbWidth, $iThumbHeight);
            imagecopyresampled($rTmpImg, $rImg, $iThumbX, $iThumbY, 0, 0, $iThumbWidth, $iThumbHeight, $iImageWidth, $iImageHeight);

            if ($blCrop) {
                $rThumbImg = imagecreatetruecolor($iThumbSize, $iThumbSize);
                imagefill($rThumbImg, 0, 0, imagecolorallocate($rThumbImg, 0, 0, 0));

                imagecopymerge($rThumbImg, $rTmpImg, 0, 0, 0, 0, $iThumbSize, $iThumbSize, 100);
            } else {
                $rThumbImg = $rTmpImg;
            }

            $sThumbName = $this->getThumbName($sFileName, $iThumbSize);

            imagejpeg($rThumbImg, $this->getThumbnailPath($sThumbName));

            return $sThumbName;
        }

        return false;
    }

    /**
     * @param string $sFile
     *
     * @return string
     */
    public function getMediaPath($sFile = '')
    {
        $sPath = rtrim(dirname(__FILE__), '/') . '/';

        if ($sFile) {
            return rtrim($sFile, '/');
        }

        return $sPath;
    }

    /**
     * @param string $sFileName
     */
    public function createMoreThumbnails($sFileName)
    {
        // More Thumbnail Sizes
        $this->createThumbnail($sFileName, 300);
        $this->createThumbnail($sFileName, 800);
    }

    /*
     * @param string $dbHost,
     * @param string $dbUser
     * @param string $dbPassword
     * @param string $dbName
     *
     * @return PDO
     *
     * @throws PDOException
     */
    public function connectToDatabase($dbHost, $dbUser, $dbPassword, $dbName)
    {
        $this->pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8",
                                 $dbUser,
                                 $dbPassword,
                                 [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET @@SESSION.sql_mode=\'\'']
    );
    }

    /**
     * @return DirectoryIterator
     */
    private function getFileIterator()
    {
        $filter = [$this->getMediaPath() . 'thumbs',
                   __FILE__,
                   $this->getMediaPath() . 'dir.txt'
        ];

        $directoryIterator = new RecursiveIteratorIterator(
            new RecursiveCallbackFilterIterator(
                new RecursiveDirectoryIterator(
                    $this->getMediaPath(),
                    RecursiveDirectoryIterator::SKIP_DOTS
                ),
                function ($fileInfo, $key, $iterator) use ($filter) {
                    return !in_array($fileInfo->getPathName(), $filter);
                }
            )
        );

        return $directoryIterator;
    }

    /*
     * @param string $sFileName
     *
     * @return $sThumbName
     */
    private function generateThumbnails($sFileName)
    {
        try {
            $sThumbName = $this->createThumbnail($sFileName);
            $this->createMoreThumbnails($sFileName);
        } catch (Exception $e) {
            $sThumbName = '';
        }

        return $sThumbName;
    }

    /**
     * @param FileInfo $fileInfo
     *
     * @return string $result the number of rows affected
     *
     * @throws Exception
     */
    private function writeFileToIndexTable($fileInfo, $thumbName)
    {
        $mimeType = $this->getMimeType($fileInfo->getPathName());
        $sqlInsert = "REPLACE INTO `ddmedia` ( 
                                `OXID`, 
                                `OXSHOPID`, 
                                `DDFILENAME`, 
                                `DDFILESIZE`, 
                                `DDFILETYPE`, 
                                `DDTHUMB`, 
                                `DDIMAGESIZE` 
                      )
                        VALUES (
                        '" . md5($fileInfo->getPathName()) . "',
                        '" . 1 . "',
                        '" . $this->getFilenameRelativeToThisDirectory($fileInfo->getPathName()) . "',
                        " . $fileInfo->getSize() . ",
                        '" . $mimeType . "','" . $thumbName . "',
                        '" . $this->getImageSize(
                $fileInfo->getPathName(),
                $mimeType
            ) . "' 
                );";

        $numberOfAffectedRows = $this->pdo->exec($sqlInsert);
        if ($numberOfAffectedRows === false) {
            throw new Exception('Could not insert File ' . $fileInfo);
        }

        return $numberOfAffectedRows;
    }

    /**
     * @param string $pathName the path to a file inside this directory
     *
     * @return string the filename with subdirectories relative to the directory containing this file
     */
    private function getFilenameRelativeToThisDirectory($pathName)
    {
        $currentDirectory = $this->getMediaPath();
        $relativePathName = str_replace($currentDirectory, '', $pathName);

        return $relativePathName;
    }

    /**
     * @param string $fileName
     *
     * @return string The mimetype of the file
     */
    private function getMimeType($fileName)
    {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $fileName);
        finfo_close($finfo);

        return $mimeType;
    }

    /**
     * @param string $fileName
     * @param string $mimeType
     *
     * @return string The size of the image
     */
    private function getImageSize($fileName, $mimeType)
    {
        $sImageSize = '';
        if (is_readable($fileName) && preg_match("/image\//", $mimeType)) {
            $aImageSize = getimagesize($fileName);
            $sImageSize = ($aImageSize ? $aImageSize[0] . 'x' . $aImageSize[1] : '');
        }

        return $sImageSize;
    }


    /**
     * Write file names to the media gallery database table and create thumbnails of images
     */
    public function index()
    {
        $numberOfAffectedRows = 0;
        $fileIterator = $this->getFileIterator();
        foreach ($fileIterator as $fileInfo) {
            $thumbName = $this->generateThumbnails($fileInfo->getPathname());
            $result = $this->writeFileToIndexTable($fileInfo, $thumbName);
            if ($result !== false) {
                $numberOfAffectedRows += $result;
            }
        }
        echo 'Number of files found: ' . $numberOfAffectedRows . "\n";
    }

    /**
     * @throws Exception
     */
    public function checkLocationOfThisScript()
    {
        $directoryOfThisFile = $this->getMediaPath();
        if (!substr($directoryOfThisFile, -strlen('out/pictures/ddmedia')) === 'out/pictures/ddmedia') {
            throw new Exception("Please move this script to the directory out/pictures/ddmedia");
        }
    }

    /**
     * @throws Exception if the table ddmedia was not found
     */
    public function checkTableDdmediaExists()
    {
        $sqlToCheckTableDdmediaExists = 'SELECT 1 FROM `ddmedia`';
        $tableDdmediaExists = $this->pdo->query($sqlToCheckTableDdmediaExists);
        if ($tableDdmediaExists === false) {
            throw new Exception("The table ddmedia was not found. Please go to the OXID eShop admin and activate the WYSIWYG Editor.");
        }
    }

}

try {
    $mediaGalleryIndexer = new MediaGalleryIndexer();
    $mediaGalleryIndexer->createDirs();
    $mediaGalleryIndexer->checkLocationOfThisScript();
    $mediaGalleryIndexer->connectToDatabase($dbHost, $dbUser, $dbPassword, $dbName);
    $mediaGalleryIndexer->checkTableDdmediaExists();
    $mediaGalleryIndexer->index();
} catch (PDOException $pdoException) {
    echo "Please configure your database correctly" . PHP_EOL;
} catch (Exception $exception) {
    echo $exception->getMessage() . PHP_EOL;
}