<commit_before><?php

namespace App\Sync\Task;

use App\Doctrine\ReloadableEntityManagerInterface;
use App\Entity;
use App\Flysystem\FilesystemManager;
use DoctrineBatchUtils\BatchProcessing\SimpleBatchIteratorAggregate;
use Psr\Log\LoggerInterface;

class CheckFolderPlaylistsTask extends AbstractTask
{
    protected Entity\Repository\StationPlaylistFolderRepository $folderRepo;

    protected Entity\Repository\StationPlaylistMediaRepository $spmRepo;

    protected FilesystemManager $filesystem;

    public function __construct(
        ReloadableEntityManagerInterface $em,
        LoggerInterface $logger,
        Entity\Repository\StationPlaylistMediaRepository $spmRepo,
        Entity\Repository\StationPlaylistFolderRepository $folderRepo,
        FilesystemManager $filesystem
    ) {
        parent::__construct($em, $logger);

        $this->spmRepo = $spmRepo;
        $this->folderRepo = $folderRepo;
        $this->filesystem = $filesystem;
    }

    public function run(bool $force = false): void
    {
        $stations = SimpleBatchIteratorAggregate::fromQuery(
            $this->em->createQuery(
                <<<'DQL'
                    SELECT s FROM App\Entity\Station s
                DQL
            ),
            1
        );

        foreach ($stations as $station) {
            /** @var Entity\Station $station */
            $this->syncPlaylistFolders($station);
            gc_collect_cycles();
        }
    }

    public function syncPlaylistFolders(Entity\Station $station): void
    {
        $this->logger->info(
            'Processing auto-assigning folders for station...',
            [
                'station' => $station->getName(),
            ]
        );

        $fs = $this->filesystem->getForStation($station);

        $mediaInPlaylistQuery = $this->em->createQuery(
            <<<'DQL'
                SELECT spm.media_id
                FROM App\Entity\StationPlaylistMedia spm
                WHERE spm.playlist_id = :playlist_id
            DQL
        );

        $mediaInFolderQuery = $this->em->createQuery(
            <<<'DQL'
                SELECT sm.id
                FROM App\Entity\StationMedia sm
                WHERE sm.storage_location = :storageLocation
                AND sm.path LIKE :path
            DQL
        )->setParameter('storageLocation', $station->getMediaStorageLocation());

        foreach ($station->getPlaylists() as $playlist) {
            if (Entity\StationPlaylist::SOURCE_SONGS !== $playlist->getSource()) {
                continue;
            }

            $folders = $playlist->getFolders();
            if (0 === $folders->count()) {
                continue;
            }

            // Get all media IDs that are already in the playlist.
            $mediaInPlaylistRaw = $mediaInPlaylistQuery->setParameter('playlist_id', $playlist->getId())
                ->getArrayResult();
            $mediaInPlaylist = array_column($mediaInPlaylistRaw, 'media_id', 'media_id');

            foreach ($folders as $folder) {
                $path = $folder->getPath();

                // Verify the folder still exists.
                if (!$fs->has(FilesystemManager::PREFIX_MEDIA . '://' . $path)) {
                    $this->em->remove($folder);
                }

                $mediaInFolderRaw = $mediaInFolderQuery->setParameter('path', $path . '/%')
                    ->getArrayResult();

                $addedRecords = 0;
                foreach ($mediaInFolderRaw as $row) {
                    $mediaId = $row['id'];

                    if (!isset($mediaInPlaylist[$mediaId])) {
                        $media = $this->em->find(Entity\StationMedia::class, $mediaId);
                        $this->spmRepo->addMediaToPlaylist($media, $playlist);

                        $mediaInPlaylist[$mediaId] = $mediaId;
                        $addedRecords++;
                    }
                }

                $logMessage = (0 === $addedRecords)
                    ? 'No changes detected in folder.'
                    : sprintf('%d media records added from folder.', $addedRecords);

                $this->logger->debug(
                    $logMessage,
                    [
                        'playlist' => $playlist->getName(),
                        'folder' => $folder->getPath(),
                    ]
                );
            }

            $this->em->flush();
            $this->em->clear();
        }
    }
}
<commit_msg>Avoid prematurely clearing the entitymanager.<commit_after><?php

namespace App\Sync\Task;

use App\Doctrine\ReloadableEntityManagerInterface;
use App\Entity;
use App\Flysystem\FilesystemManager;
use DoctrineBatchUtils\BatchProcessing\SimpleBatchIteratorAggregate;
use Psr\Log\LoggerInterface;

class CheckFolderPlaylistsTask extends AbstractTask
{
    protected Entity\Repository\StationPlaylistFolderRepository $folderRepo;

    protected Entity\Repository\StationPlaylistMediaRepository $spmRepo;

    protected FilesystemManager $filesystem;

    public function __construct(
        ReloadableEntityManagerInterface $em,
        LoggerInterface $logger,
        Entity\Repository\StationPlaylistMediaRepository $spmRepo,
        Entity\Repository\StationPlaylistFolderRepository $folderRepo,
        FilesystemManager $filesystem
    ) {
        parent::__construct($em, $logger);

        $this->spmRepo = $spmRepo;
        $this->folderRepo = $folderRepo;
        $this->filesystem = $filesystem;
    }

    public function run(bool $force = false): void
    {
        $stations = SimpleBatchIteratorAggregate::fromQuery(
            $this->em->createQuery(
                <<<'DQL'
                    SELECT s FROM App\Entity\Station s
                DQL
            ),
            1
        );

        foreach ($stations as $station) {
            /** @var Entity\Station $station */
            $this->syncPlaylistFolders($station);
            gc_collect_cycles();
        }
    }

    public function syncPlaylistFolders(Entity\Station $station): void
    {
        $this->logger->info(
            'Processing auto-assigning folders for station...',
            [
                'station' => $station->getName(),
            ]
        );

        $fs = $this->filesystem->getForStation($station);

        $mediaInPlaylistQuery = $this->em->createQuery(
            <<<'DQL'
                SELECT spm.media_id
                FROM App\Entity\StationPlaylistMedia spm
                WHERE spm.playlist_id = :playlist_id
            DQL
        );

        $mediaInFolderQuery = $this->em->createQuery(
            <<<'DQL'
                SELECT sm.id
                FROM App\Entity\StationMedia sm
                WHERE sm.storage_location = :storageLocation
                AND sm.path LIKE :path
            DQL
        )->setParameter('storageLocation', $station->getMediaStorageLocation());

        foreach ($station->getPlaylists() as $playlist) {
            if (Entity\StationPlaylist::SOURCE_SONGS !== $playlist->getSource()) {
                continue;
            }

            $folders = $playlist->getFolders();
            if (0 === $folders->count()) {
                continue;
            }

            // Get all media IDs that are already in the playlist.
            $mediaInPlaylistRaw = $mediaInPlaylistQuery->setParameter('playlist_id', $playlist->getId())
                ->getArrayResult();
            $mediaInPlaylist = array_column($mediaInPlaylistRaw, 'media_id', 'media_id');

            foreach ($folders as $folder) {
                $path = $folder->getPath();

                // Verify the folder still exists.
                if (!$fs->has(FilesystemManager::PREFIX_MEDIA . '://' . $path)) {
                    $this->em->remove($folder);
                }

                $mediaInFolderRaw = $mediaInFolderQuery->setParameter('path', $path . '/%')
                    ->getArrayResult();

                $addedRecords = 0;
                foreach ($mediaInFolderRaw as $row) {
                    $mediaId = $row['id'];

                    if (!isset($mediaInPlaylist[$mediaId])) {
                        $media = $this->em->find(Entity\StationMedia::class, $mediaId);
                        $this->spmRepo->addMediaToPlaylist($media, $playlist);

                        $mediaInPlaylist[$mediaId] = $mediaId;
                        $addedRecords++;
                    }
                }

                $logMessage = (0 === $addedRecords)
                    ? 'No changes detected in folder.'
                    : sprintf('%d media records added from folder.', $addedRecords);

                $this->logger->debug(
                    $logMessage,
                    [
                        'playlist' => $playlist->getName(),
                        'folder' => $folder->getPath(),
                    ]
                );
            }

            $this->em->flush();
        }

        $this->em->clear();
    }
}

{'fraction_non_alphanumeric': 0.11502845029565993, 'fraction_numerical': 0.0008925582952136561, 'mean_word_length': 1.6750223813786929, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4728430', 'n_tokens_mistral': 2370, 'n_tokens_neox': 2259, 'n_words': 424}