<commit_before><?php

namespace FlickrDownloadr\Command;

use FlickrDownloadr\Photo\Photo;
use FlickrDownloadr\Photo\SizeHelper;
use FlickrDownloadr\Photoset\Photoset;
use Nette\Utils\Strings;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class PhotosetDownload extends Command
{
    /** @var \FlickrDownloadr\Photoset\Repository */
    private $photosetRepository;

    /** @var \FlickrDownloadr\Photo\Repository */
    private $photoRepository;
	
	/** @var \FlickrDownloadr\Photoset\DirnameCreator */
	private $dirnameCreator;
	
	/** @var \FlickrDownloadr\Photo\SizeHelper */
	private $photoSizeHelper;

	/** @var \FlickrDownloadr\Photo\FilenameCreator */
	private $photoFilenameCreator;

	public function __construct(
		\FlickrDownloadr\Photoset\Repository $photosetRepository, 
		\FlickrDownloadr\Photo\Repository $photoRepository,
		\FlickrDownloadr\Photoset\DirnameCreator $dirnameCreator,
		\FlickrDownloadr\Photo\SizeHelper $photoSizeHelper,
		\FlickrDownloadr\Photo\FilenameCreator $photoFilenameCreator
	)
    {
        $this->photosetRepository = $photosetRepository;
        $this->photoRepository = $photoRepository;
		$this->dirnameCreator = $dirnameCreator;
		$this->photoSizeHelper = $photoSizeHelper;
		$this->photoFilenameCreator = $photoFilenameCreator;
        parent::__construct();
    }

    protected function configure()
    {
        $this
            ->setName('photoset:download')
            ->setDescription('Download photoset')
            ->addArgument('id', InputArgument::REQUIRED, 'ID of the photoset')
            ->addOption('no-slug', null, InputOption::VALUE_NONE, 'Do not convert filename to safe string')
            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Do not realy download')
            ->addOption('dir', null, InputOption::VALUE_OPTIONAL, 'Photoset directory. See the docs for supported placeholders', '%title%-%id%')
			->addOption('photo-size', 's', InputOption::VALUE_OPTIONAL, 'Name of photo size (original, large, medium, small...)', SizeHelper::NAME_ORIGINAL)
			->addOption('clean-dir', null, InputOption::VALUE_NONE, 'Erase directory if exists')
			->addOption('photo-name', null, InputOption::VALUE_OPTIONAL, 'Photo filename template. See the docs for supported placeholders', '%order%-%title%-%id%');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $id = $input->getArgument('id');
        $noSlug = $input->getOption('no-slug');
        $dryRun = $input->getOption('dry-run');
        $dir = $input->getOption('dir');
		$photoSize = $this->photoSizeHelper->validate($input->getOption('photo-size'));
		$cleanDir = $input->getOption('clean-dir');
		$photoFilename = $input->getOption('photo-name');

        $photoset = $this->photosetRepository->findOne($id);
        $dirName = $this->managePhotosetDir($photoset, $noSlug, $dryRun, $dir, $cleanDir);
        
        $photos = $this->photoRepository->findAllByPhotosetId($id, $photoSize);
        $output->writeln('<info>Number of photos in set: ' . count($photos) . '</info>');
        $i = 1;
        foreach ($photos as $photo) {
            $filename = $this->photoFilenameCreator->create($photo, $i, count($photos), $photoFilename, $photoSize, $noSlug);
            $output->write($filename . ' ');
            $size = $this->downloadPhoto($photo, $filename, $dirName, $dryRun);
            $result = $this->getDownloadResult($size);
            $output->writeln($result);
            $i++;
        }
    }
    
    /**
     * @param Photoset $photoset
     * @param boolean $noSlug
     * @param boolean $dryRun
     * @param string $dir
     * @param boolean $cleanDir
     * @return string
     */
    private function managePhotosetDir(Photoset $photoset, $noSlug, $dryRun, $dir, $cleanDir)
    {
		$dirName = $this->dirnameCreator->create($photoset, $dir, $noSlug);
		if ($cleanDir && is_dir($dirName) && !$dryRun) {
			\Nette\Utils\FileSystem::delete($dirName);
		}
		if (!is_dir($dirName) && !$dryRun) {
			\Nette\Utils\FileSystem::createDir($dirName);
        }
        return $dirName;
    }

    /**
     * @param Photo $photo
     * @param string $filename
     * @param string $dirName
     * @param boolean $dryRun
     * @return int Number of bytes that were written to the file, or FALSE on failure
     */
    private function downloadPhoto(Photo $photo, $filename, $dirName, $dryRun)
    {
        $url = $photo->getUrl();
		if ($dryRun) {
			return 0;
		}
        return file_put_contents($dirName . '/' . $filename, fopen($url, 'r'));
    }
    
    /**
     * Converts to human readable file size.
     * @param  int
     * @param  int
     * @return string
     */
    private function formatFilesize($bytes, $precision = 2)<commit_msg>photo filename can contains dir separators<commit_after><?php

namespace FlickrDownloadr\Command;

use FlickrDownloadr\Photo\Photo;
use FlickrDownloadr\Photo\SizeHelper;
use FlickrDownloadr\Photoset\Photoset;
use Nette\Utils\Strings;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class PhotosetDownload extends Command
{
    /** @var \FlickrDownloadr\Photoset\Repository */
    private $photosetRepository;

    /** @var \FlickrDownloadr\Photo\Repository */
    private $photoRepository;
	
	/** @var \FlickrDownloadr\Photoset\DirnameCreator */
	private $dirnameCreator;
	
	/** @var \FlickrDownloadr\Photo\SizeHelper */
	private $photoSizeHelper;

	/** @var \FlickrDownloadr\Photo\FilenameCreator */
	private $photoFilenameCreator;

	public function __construct(
		\FlickrDownloadr\Photoset\Repository $photosetRepository, 
		\FlickrDownloadr\Photo\Repository $photoRepository,
		\FlickrDownloadr\Photoset\DirnameCreator $dirnameCreator,
		\FlickrDownloadr\Photo\SizeHelper $photoSizeHelper,
		\FlickrDownloadr\Photo\FilenameCreator $photoFilenameCreator
	)
    {
        $this->photosetRepository = $photosetRepository;
        $this->photoRepository = $photoRepository;
		$this->dirnameCreator = $dirnameCreator;
		$this->photoSizeHelper = $photoSizeHelper;
		$this->photoFilenameCreator = $photoFilenameCreator;
        parent::__construct();
    }

    protected function configure()
    {
        $this
            ->setName('photoset:download')
            ->setDescription('Download photoset')
            ->addArgument('id', InputArgument::REQUIRED, 'ID of the photoset')
            ->addOption('no-slug', null, InputOption::VALUE_NONE, 'Do not convert filename to safe string')
            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Do not realy download')
            ->addOption('dir', null, InputOption::VALUE_OPTIONAL, 'Photoset directory. See the docs for supported placeholders', '%title%-%id%')
			->addOption('photo-size', 's', InputOption::VALUE_OPTIONAL, 'Name of photo size (original, large, medium, small...)', SizeHelper::NAME_ORIGINAL)
			->addOption('clean-dir', null, InputOption::VALUE_NONE, 'Erase directory if exists')
			->addOption('photo-name', null, InputOption::VALUE_OPTIONAL, 'Photo filename template. See the docs for supported placeholders', '%order%-%title%-%id%');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $id = $input->getArgument('id');
        $noSlug = $input->getOption('no-slug');
        $dryRun = $input->getOption('dry-run');
        $dir = $input->getOption('dir');
		$photoSize = $this->photoSizeHelper->validate($input->getOption('photo-size'));
		$cleanDir = $input->getOption('clean-dir');
		$photoFilename = $input->getOption('photo-name');

        $photoset = $this->photosetRepository->findOne($id);
        $dirName = $this->managePhotosetDir($photoset, $noSlug, $dryRun, $dir, $cleanDir);
        
        $photos = $this->photoRepository->findAllByPhotosetId($id, $photoSize);
        $output->writeln('<info>Number of photos in set: ' . count($photos) . '</info>');
        $i = 1;
        foreach ($photos as $photo) {
            $filename = $this->photoFilenameCreator->create($photo, $i, count($photos), $photoFilename, $photoSize, $noSlug);
            $output->write($filename . ' ');
            $size = $this->downloadPhoto($photo, $filename, $dirName, $dryRun);
            $result = $this->getDownloadResult($size);
            $output->writeln($result);
            $i++;
        }
    }
    
    /**
     * @param Photoset $photoset
     * @param boolean $noSlug
     * @param boolean $dryRun
     * @param string $dir
     * @param boolean $cleanDir
     * @return string
     */
    private function managePhotosetDir(Photoset $photoset, $noSlug, $dryRun, $dir, $cleanDir)
    {
		$dirName = $this->dirnameCreator->create($photoset, $dir, $noSlug);
		if ($cleanDir && is_dir($dirName) && !$dryRun) {
			\Nette\Utils\FileSystem::delete($dirName);
		}
		if (!is_dir($dirName) && !$dryRun) {
			\Nette\Utils\FileSystem::createDir($dirName);
        }
        return $dirName;
    }

    /**
     * @param Photo $photo
     * @param string $filename
     * @param string $dirName
     * @param boolean $dryRun
     * @return int Number of bytes that were written to the file, or FALSE on failure
     */
    private function downloadPhoto(Photo $photo, $filename, $dirName, $dryRun)
    {
        $url = $photo->getUrl();
		if ($dryRun) {
			return 0;
		}
		\Nette\Utils\FileSystem::createDir($dirName . '/' . dirname($filename));
        return file_put_contents($dirName . '/' . $filename, fopen($url, 'r'));
    }
    
    /**
     * Converts to human readable file size.
     * @param  int
     * @param  int
     * @return string
     */
    private function formatFilesize($bytes, $precision = 2)
{'fraction_non_alphanumeric': 0.1449, 'fraction_numerical': 0.0006, 'mean_word_length': 3.4867653656348137, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7535908', 'n_tokens_mistral': 3195, 'n_tokens_neox': 3000, 'n_words': 618}