-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EZP-28718: Embedded images should be handled as images instead of plain embed object after migrating from XmlText to RichText #39
Conversation
protected function loginAsAdmin() | ||
{ | ||
$userService = $this->getContainer()->get('ezpublish.api.service.user'); | ||
$permissionResolver = $this->getContainer()->get('date_based_publisher.permission_resolver'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
date_based_publisher?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. cut&paste error.. Fixed
'image-content-types', | ||
null, | ||
InputOption::VALUE_OPTIONAL, | ||
'Comma separated list of content types which are considered as images when converting embedded tags. Default value is 27' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be better if we use identifiers, type id's have a tendency to have different values depending on install more often then identifiers.
However the command can translate it to id using dbal, so service can stay on using type id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. fixed
'identifier', | ||
$literalIdentifiers | ||
) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can simplify all this, welcome to DBAL's magic PARAM_(INT|STR)_ARRAY
bind type ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aha.. thanx.. Cause my solution was indeed insanely cumbersome
|
||
$statement = $query->execute(); | ||
$result = array(); | ||
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
afaik you can use return $statement->fetchAll(PDO::FETCH_COLUMN);
to get what you want directly here.
} | ||
|
||
$query->select('id') | ||
->from($this->dbal->quoteIdentifier('ezcontentclass')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding this, I was about to say you don't need to quote constants with DBAL, but seeing it is done in https://github.com/ezsystems/ezpublish-kernel/blob/d1143080d2325cadc6ccc1e3aee55b29aecebae4/eZ/Publish/Core/FieldType/BinaryBase/BinaryBaseStorage/Gateway/DoctrineStorage.php#L269 I'm a bit unsure.
@alongosz Did you check that when writing it? Or was it just left over from style of zeta based older db code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right Andre, those constants does not need to be quoted it seems
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, if identifier is the same as some SQL keyword then it still needs to be quoted, I think. But AFAIR in our system it was more of the case with column names, not tables.
On the other hand... quoting only chosen ones is bad for my Aspergers, so I tried to Quote Them All ;)
But it's up to you, for sure it would be more readable w/o quoting :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it's up to you, for sure it would be more readable w/o quoting :)
It's not just up to me, but I prefer readability as long as we are following:
- https://www.doctrine-project.org/projects/doctrine-dbal/en/2.7/reference/portability.html#portability
- https://www.doctrine-project.org/projects/doctrine-dbal/en/2.7/reference/security.html#security
- https://www.doctrine-project.org/projects/doctrine-dbal/en/2.7/reference/known-vendor-issues.html#known-vendor-issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So proposal on tables and columns: We can write like this so we never need to be in doubt, and basically never need to quote:
$query->select('c.id')
->from('ezcontentclass', 'c')
Avoids the need to do $this->dbal->quoteIdentifier('id')
which is done further down here, also makes it explicit which table we act on all over. Again, optimizing for reading, cause that is what we do most of the time ;)
66ab403
to
1c22fbd
Compare
Fixed all review comments I believe... |
Added more bugfixes:
|
*/ | ||
private $currentContentFieldId; | ||
|
||
public function __construct(LoggerInterface $logger = null, $apiRepository = null, $imageContentTypes = array()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apiRepository should be first as it's not really optional.
imageContentTypes should be either optional setter injection, or required constructor argument. Rather then both at the same time.
nitpick for new/changed code: array()
=> []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
try { | ||
$location = $locationService->loadLocation($id); | ||
} catch (NotFoundException $e) { | ||
$this->logger->warning("Unable to find node_id=$id, referred to in embedded tag in contentobject_attribute.id=$this->currentContentFieldId."); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
$nodes = $xpath->query('//doc:ezembed'); | ||
foreach ($nodes as $node) { | ||
//href is in format : ezcontent://123 or ezlocation://123 | ||
$href=$node->attributes->getNamedItem('href')->nodeValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space between ' = '
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
//href is in format : ezcontent://123 or ezlocation://123 | ||
$href=$node->attributes->getNamedItem('href')->nodeValue; | ||
$isContentId = strpos($href, 'ezcontent') === 0; | ||
$id = (int) substr($href, strrpos($href, '/')+1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should setup cs checking on travis here, but it won't run on this PR right now as it's against dbal branch :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.. CS and running unit tests would be good. Who can setup that? I guess it should be adressed in a separate PR though ....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unit tests will be running as soon as you now change target branch to master and rebase for master and push. Its not running here since dbal
target branch is not setup as branch to run tests for, maybe we should not restrict branch to run on somehow for pr's on pr's.
See other repos where @alongosz has added cs testing on travis for inspiration on that, like: ezsystems/ezplatform-http-cache@aa1f551
} else { | ||
if (($classAttribute !== null) && ($node->attributes->getNamedItem('class')->nodeValue === 'ez-embed-type-image')) { | ||
$node->removeAttribute('ezxhtml:class'); | ||
//$node->setAttribute('ezxhtml:class', 'ez-embed-type-image'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to be removed?
As for line above, also the class logic here forget it can be several classes like in html. Or? (OE probably did not allow it, but I1'm thinking maybe the underlying xmltext allowed it if edited raw).
At least assume it can be several when comparing richtext nodes, as it adds ez-embed-type-image
to whatever was there from before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm.. I added this because I thought this would be a nice feature.. but I should probably check if class is indeed ez-embed-type-image
, and only remove that one (not everything) if it exists... ok then ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the comment line should be removed, indeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes and yes :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
Fixed according to all review comments, and rebased |
$xpath = new DOMXPath($richtextDocument); | ||
$ns = $richtextDocument->documentElement->namespaceURI; | ||
$xpath->registerNamespace('doc', $ns); | ||
$nodes = $xpath->query('//doc:ezembed'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to deal with ezembed-inline too....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
':version' | ||
) | ||
) | ||
->setParameters(array( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
if ($logger === null) { | ||
$this->logger = new NullLogger(); | ||
} else { | ||
$this->logger = $logger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could also be:
$this->logger = $logger instanceof LoggerInterface ? $logger : new NullLogger();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
*/ | ||
private $converter; | ||
|
||
public function __construct(Connection $dbal, RichTextConverter $converter, LoggerInterface $logger = null) | ||
{ | ||
parent::__construct(); | ||
|
||
$this->dbal = $dbal; | ||
$this->logger = $logger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems we need NullLogger here to form the looks of the new code bellow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll instead remove default value from constructor, forcing a logger to be set in DI config
ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is ok, but maybe double check with @adamwojs if there are still cases logger might not be set, as we tend to some places still allow it to be null for some reason. But that might just be baggage from earlier symfony versions, or attempt to have it as optional dependency.
{ | ||
$this->currentContentFieldId = $contentFieldId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could remove this as class property and rather inject it, to avoid global state set by method which is not a setter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, passing on $contentFieldId down the call stack
*/ | ||
public function providerForTestTagEmbeddedImages() | ||
{ | ||
$map = array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
|
||
$inputDocument = $this->createDocument($inputFilePath); | ||
$richText = new RichText($apiRepositoryStub); | ||
$richText->setImageContentTypes(array(27)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not it seems :)
review ping. PR should now be in compliance with all review comments |
Hmm, a month ago when I commented on building queries I didn't look at what happens here at all (slammed with work, sorry). But maybe I missed something? TL;DR |
@alongosz Not sure what you are talking about here, this is migration scenario, it's something people run before booting the system normally, during upgrade. And if they don't, they need to clear all cache anyway. So while it would be great if we had generic migrations features supported somehow cleanly via SPI (Storage Engine and FieldTypes at least), it's far far beyond the scope here and more for you and engineering team to think about for future versions (this is for existing, real world versions ;)). |
In general, there could be benefits with using persistence handler in upgrade scripts. But there are pitfalls too. Often, upgrade scripts fix an invalid DB state ( schema change for instance ). So, having API calls that are able to deal with such things would be nice to have, but not sure it is worth the effort. my 2 cents... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, if this is intended as a migration script and user knows about clearing Symfony cache after all the operations, I have no further objections.
My point however was also for building queries outside of API or SPI. Then we need to provide BC for database schema (which we do), which leads to showstoppers when it comes to evolving application.
If we had:
- database migration on upgrade (doctrine schema files WiP)
- everything encapsulated in at least SPI implementation
then we wouldn't need to worry about changing database at all.
Right now even if we achieve automatic database update on upgrades, then we still have some commands that operate on raw database.
But that's a little bit out of scope here. For now, with full context, which I didn't have before - +1
Some nitpicks:
<ezvalue key="limit">5</ezvalue> | ||
</ezconfig> | ||
</ezembed> | ||
</section> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
<ezvalue key="limit">5</ezvalue> | ||
</ezconfig> | ||
</ezembed> | ||
</section> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
<ezvalue key="limit">5</ezvalue> | ||
</ezconfig> | ||
</ezembed> | ||
</section> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
<ezvalue key="limit">5</ezvalue> | ||
</ezconfig> | ||
</ezembed> | ||
</section> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
<ezvalue key="limit">5</ezvalue> | ||
</ezconfig> | ||
</ezembed> | ||
</section> |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides small nitpic on array syntax +1
I'll merge as is
This one fixes
EZP-28718 : Embedded images should be handled as images instead of plain embed object after migrating from XmlText to RichText
EZP-28767 : Create a script to fix embedded images broken after migrating from XmlText to RichText
Running
bin/console ezxmltext:convert-to-richtext
will ensure embedded images are tagged correctly in the resulting ezrichtext.Running
bin/console ezxmltext:convert-to-richtext --fix-embedded-images-only
will only fix the embedded images on an already converted DB.Optionally, use
--image-content-types=image,thumbnail,foobar
to specify which classes should considered as image classes.Related doc pr :
ibexa/documentation-developer#268