2019-10-13 00:32:09 +02:00
< ? php
2020-02-22 18:14:36 +01:00
/**
* This file is part of Part - DB ( https :// github . com / Part - DB / Part - DB - symfony ) .
*
2022-11-29 22:28:53 +01:00
* Copyright ( C ) 2019 - 2022 Jan Böhmer ( https :// github . com / jbtronics )
2020-02-22 18:14:36 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
2020-01-05 15:46:58 +01:00
declare ( strict_types = 1 );
2022-08-04 21:49:16 +02:00
namespace App\Command\Migrations ;
2019-10-13 00:32:09 +02:00
use App\Entity\Attachments\AttachmentType ;
2020-02-01 19:48:07 +01:00
use App\Entity\Base\AbstractNamedDBElement ;
2022-12-18 20:34:25 +01:00
use App\Entity\ProjectSystem\Project ;
2019-10-13 00:32:09 +02:00
use App\Entity\Parts\Category ;
use App\Entity\Parts\Manufacturer ;
use App\Entity\Parts\MeasurementUnit ;
use App\Entity\Parts\Part ;
use App\Entity\Parts\Storelocation ;
use App\Entity\Parts\Supplier ;
use App\Entity\PriceInformations\Currency ;
use App\Entity\UserSystem\Group ;
use App\Helpers\BBCodeToMarkdownConverter ;
use Doctrine\ORM\EntityManagerInterface ;
use Doctrine\ORM\EntityRepository ;
use Symfony\Component\Console\Command\Command ;
use Symfony\Component\Console\Input\InputInterface ;
use Symfony\Component\Console\Output\OutputInterface ;
use Symfony\Component\Console\Style\SymfonyStyle ;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface ;
2022-08-04 21:49:16 +02:00
use function count ;
2019-10-13 00:32:09 +02:00
/**
2023-04-15 23:14:53 +02:00
* This command converts the BBCode used by old Part - DB versions ( < 1.0 ), to the current used Markdown format .
2019-10-13 00:32:09 +02:00
*/
2023-05-28 01:21:05 +02:00
#[\Symfony\Component\Console\Attribute\AsCommand('partdb:migrations:convert-bbcode|app:convert-bbcode', 'Converts BBCode used in old Part-DB versions to newly used Markdown')]
2019-10-13 00:32:09 +02:00
class ConvertBBCodeCommand extends Command
{
2020-01-05 22:49:00 +01:00
/**
2023-04-15 23:14:53 +02:00
* @ var string The LIKE criteria used to detect on SQL server if an entry contains BBCode
2020-01-05 22:49:00 +01:00
*/
2019-11-09 00:47:20 +01:00
protected const BBCODE_CRITERIA = '%[%]%[/%]%' ;
2020-01-05 22:49:00 +01:00
/**
* @ var string The regex ( performed in PHP ) used to check if a property really contains BBCODE
*/
2019-10-13 00:32:09 +02:00
protected const BBCODE_REGEX = '/\\[.+\\].*\\[\\/.+\\]/' ;
2022-09-18 22:59:31 +02:00
protected EntityManagerInterface $em ;
protected PropertyAccessorInterface $propertyAccessor ;
protected BBCodeToMarkdownConverter $converter ;
2019-10-13 00:32:09 +02:00
public function __construct ( EntityManagerInterface $entityManager , PropertyAccessorInterface $propertyAccessor )
{
$this -> em = $entityManager ;
$this -> propertyAccessor = $propertyAccessor ;
$this -> converter = new BBCodeToMarkdownConverter ();
parent :: __construct ();
}
2020-01-05 15:46:58 +01:00
protected function configure () : void
2019-10-13 00:32:09 +02:00
{
2023-05-28 01:21:05 +02:00
$this -> setHelp ( ' Older versions of Part - DB ( < 1.0 ) used BBCode for rich text formatting .
2019-10-13 00:32:09 +02:00
Part - DB now uses Markdown which offers more features but is incompatible with BBCode .
When you upgrade from an pre 1.0 version you have to run this command to convert your comment fields ' );
$this -> addOption ( 'dry-run' , null , null , 'Do not save changes to DB. In combination with -v or -vv you can check what will be changed!' );
}
/**
* Returns a list which entities and which properties need to be checked .
*/
2019-11-09 00:47:20 +01:00
protected function getTargetsLists () : array
2019-10-13 00:32:09 +02:00
{
return [
Part :: class => [ 'description' , 'comment' ],
AttachmentType :: class => [ 'comment' ],
Storelocation :: class => [ 'comment' ],
2022-12-18 20:34:25 +01:00
Project :: class => [ 'comment' ],
2019-10-13 00:32:09 +02:00
Category :: class => [ 'comment' ],
Manufacturer :: class => [ 'comment' ],
MeasurementUnit :: class => [ 'comment' ],
Supplier :: class => [ 'comment' ],
Currency :: class => [ 'comment' ],
Group :: class => [ 'comment' ],
];
}
2020-02-01 17:00:03 +01:00
protected function execute ( InputInterface $input , OutputInterface $output ) : int
2019-10-13 00:32:09 +02:00
{
$io = new SymfonyStyle ( $input , $output );
$targets = $this -> getTargetsLists ();
//Convert for every class target
foreach ( $targets as $class => $properties ) {
$io -> section ( sprintf ( 'Convert entities of class %s' , $class ));
$io -> note ( sprintf (
'Search for entities of type %s that need conversion' ,
$class
));
//Determine which entities of this type we need to modify
/** @var EntityRepository $repo */
$repo = $this -> em -> getRepository ( $class );
$qb = $repo -> createQueryBuilder ( 'e' )
-> select ( 'e' );
//Add fields criteria
foreach ( $properties as $key => $property ) {
2019-11-09 00:47:20 +01:00
$qb -> orWhere ( 'e.' . $property . ' LIKE ?' . $key );
2019-10-13 00:32:09 +02:00
$qb -> setParameter ( $key , static :: BBCODE_CRITERIA );
}
//Fetch resulting classes
$results = $qb -> getQuery () -> getResult ();
2020-01-05 22:49:00 +01:00
$io -> note ( sprintf ( 'Found %d entities, that need to be converted!' , count ( $results )));
2019-10-13 00:32:09 +02:00
//In verbose mode print the names of the entities
foreach ( $results as $result ) {
2020-02-01 19:48:07 +01:00
/** @var AbstractNamedDBElement $result */
2019-10-13 00:32:09 +02:00
$io -> writeln (
2020-08-21 21:36:22 +02:00
'Convert entity: ' . $result -> getName () . ' (' . get_class ( $result ) . ': ' . $result -> getID () . ')' ,
2019-10-13 00:32:09 +02:00
OutputInterface :: VERBOSITY_VERBOSE
);
foreach ( $properties as $property ) {
//Retrieve bbcode from entity
$bbcode = $this -> propertyAccessor -> getValue ( $result , $property );
//Check if the current property really contains BBCode
2020-08-21 21:36:22 +02:00
if ( ! preg_match ( static :: BBCODE_REGEX , $bbcode )) {
2019-10-13 00:32:09 +02:00
continue ;
}
$io -> writeln (
'BBCode (old): '
2019-11-09 00:47:20 +01:00
. str_replace ( '\n' , ' ' , substr ( $bbcode , 0 , 255 )),
2019-10-13 00:32:09 +02:00
OutputInterface :: VERBOSITY_VERY_VERBOSE
);
$markdown = $this -> converter -> convert ( $bbcode );
$io -> writeln (
'Markdown (new): '
2019-11-09 00:47:20 +01:00
. str_replace ( '\n' , ' ' , substr ( $markdown , 0 , 255 )),
2019-10-13 00:32:09 +02:00
OutputInterface :: VERBOSITY_VERY_VERBOSE
);
$io -> writeln ( '' , OutputInterface :: VERBOSITY_VERY_VERBOSE );
$this -> propertyAccessor -> setValue ( $result , $property , $markdown );
}
}
}
//If we are not in dry run, save changes to DB
2020-08-21 21:36:22 +02:00
if ( ! $input -> getOption ( 'dry-run' )) {
2019-10-13 00:32:09 +02:00
$this -> em -> flush ();
$io -> success ( 'Changes saved to DB successfully!' );
}
2020-02-01 17:00:03 +01:00
2023-05-28 01:21:05 +02:00
return \Symfony\Component\Console\Command\Command :: SUCCESS ;
2019-10-13 00:32:09 +02:00
}
2019-11-09 00:47:20 +01:00
}