src/CoreBundle/Migrations/Schema/V200/Version20230720143000.php
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Entity\PersonalFile;
use Chamilo\CoreBundle\Entity\ResourceNode;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\ORM\Query\Expr\Join;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use const GLOB_ONLYDIR;
final class Version20230720143000 extends AbstractMigrationChamilo
{
public function getDescription(): string
{
return 'Migrate my_files of users to personal_files ';
}
public function up(Schema $schema): void
{
$kernel = $this->container->get('kernel');
$rootPath = $kernel->getProjectDir();
$fallbackUser = $this->getFallbackUser();
$directory = $this->getUpdateRootPath().'/app/upload/users/';
$variable = 'split_users_upload_directory';
$query = $this->entityManager->createQuery('SELECT s.selectedValue FROM Chamilo\CoreBundle\Entity\SettingsCurrent s WHERE s.variable = :variable')
->setParameter('variable', $variable)
;
$result = $query->getOneOrNullResult();
$splitUsersUploadDirectory = $result['selectedValue'] ?? 'false';
if ('true' === $splitUsersUploadDirectory) {
$parentDirectories = glob($directory.'*', GLOB_ONLYDIR);
foreach ($parentDirectories as $parentDir) {
$firstDigit = basename($parentDir);
$subDirectories = glob($parentDir.'/*', GLOB_ONLYDIR);
foreach ($subDirectories as $userDir) {
$userId = basename($userDir);
$this->processUserDirectory($userId, $userDir, $fallbackUser, true);
}
}
} else {
$userDirectories = glob($directory.'*', GLOB_ONLYDIR);
foreach ($userDirectories as $userDir) {
$userId = basename($userDir);
$this->processUserDirectory($userId, $userDir, $fallbackUser, false);
}
}
}
private function processUserDirectory(string $userId, string $userDir, User $fallbackUser, bool $splitUsersUploadDirectory): void
{
$userEntity = $this->entityManager->getRepository(User::class)->find($userId);
$userToAssign = $userEntity ?? $fallbackUser;
if (null === $userEntity) {
error_log("User with ID {$userId} not found. Using fallback_user.");
} else {
error_log("Processing files for user with ID {$userId}.");
}
if ($splitUsersUploadDirectory) {
$baseDir = $userDir.'/';
} else {
$baseDir = $this->getUpdateRootPath().'/app/upload/users/'.$userId.'/';
}
error_log("Final path to check: {$baseDir}");
if (!is_dir($baseDir)) {
error_log("Directory not found for user with ID {$userId}. Skipping.");
return;
}
$myFilesDir = $baseDir.'my_files/';
$files = glob($myFilesDir.'*');
foreach ($files as $file) {
if (!is_file($file)) {
continue;
}
$title = basename($file);
error_log("Processing file: {$file} for user with ID {$userToAssign->getId()}.");
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder
->select('p')
->from(ResourceNode::class, 'n')
->innerJoin(PersonalFile::class, 'p', Join::WITH, 'p.resourceNode = n.id')
->where('n.title = :title')
->andWhere('n.creator = :creator')
->setParameter('title', $title)
->setParameter('creator', $userToAssign->getId())
;
$result = $queryBuilder->getQuery()->getOneOrNullResult();
if ($result) {
error_log('MIGRATIONS :: '.$file.' (Skipped: Already exists) ...');
continue;
}
error_log("MIGRATIONS :: Associating file {$file} to user with ID {$userToAssign->getId()}.");
$personalFile = new PersonalFile();
$personalFile->setTitle($title);
$personalFile->setCreator($userToAssign);
$personalFile->setParentResourceNode($userToAssign->getResourceNode()->getId());
$personalFile->setResourceName($title);
$mimeType = mime_content_type($file);
$uploadedFile = new UploadedFile($file, $title, $mimeType, null, true);
$personalFile->setUploadFile($uploadedFile);
$personalFile->addUserLink($userToAssign);
// Save the object to the database
$this->entityManager->persist($personalFile);
$this->entityManager->flush();
}
}
private function getFallbackUser(): ?User
{
return $this->entityManager->getRepository(User::class)->findOneBy(['status' => User::ROLE_FALLBACK], ['id' => 'ASC']);
}
}