Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
locale.module
Priority:
Major
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
14 Sep 2012 at 19:02 UTC
Updated:
29 Jul 2014 at 21:10 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
gábor hojtsyComment #3
jose reyero commentedA much better version, extending LocaleTranslation query builder and saving way more code.
Comment #5
jose reyero commentedFixed stupid issue with checkVersion, which was causing all these errors.
Comment #7
gábor hojtsyTagging for interface translation.
Comment #8
jose reyero commentedSome minor improvements and bug fixes:
- Fixed issues with PoDatabaseReader/Writer.
- Added some methods in LocaleString class.
- More options that were needed in LocaleTranslation::buildQuery() for consistency with DatabaseReader queries.
Comment #9
jose reyero commentedRelated, annoying issues when testing the patch, though not blocking it, #1789090: Warnings when exporting templates: addcslashes() expects parameter 1 to be string
Comment #10
gábor hojtsyFirst, great abstraction, I like the string => translation | source abstraction. I also like the lots of custom code removed :) This has been an old issue and lots of work went into #361597: CRUD API for locale source and locale target strings, so it would be great to have a solid solution for this. I have mostly minor remarks:
Whitespace after =
"The string identifier" instead? :)
No newline.
First comment line too long.
Also:
- Are you not applying this to the locale() lookup due to the speed required there?
- Do we have an idea of how much slower does this make importing a big .po file for example?
- Do you think we can have tests for the new classes (without the whole Drupal system being tested like we do now with the .po imports/exports and edits)?
Comment #11
jose reyero commented@Gabor,
Yes, this is applied to the locale lookup too. I don't know whether the query builder will mean some performance loss but the queries themselves should look the same, which makes the query builder a bit more complex but it should produce optimized queries.
This new version of the patch:
- Addresses the code style issues above #10
- Moves the query builder one level down, into LocaleString class so it can be used for both LocaleSource and LocaleTranslation object adding a good deal of flexibility.
- Renames and simplifies query options that were a bit ugly in the previous version. This needed some improvements to support all the search options / combinations in the module.
- Replaces drupal_write_object() with db_insert / db_update that was causing inconsistent defaults when used with typed objects. (I think this is an issue in drupal_write_object)
- Adds a few utility methods to string classes (setDefaultValues, getFieldValues) and moves some other methods around looking for consistency.
- Adds some unit tests for the API, maybe a bit more would be good.
- Fixes the 'duplicated strings' issue, that needed to be supported by this API, #1789090: Warnings when exporting templates: addcslashes() expects parameter 1 to be string
Pending (help wanted):
- Benchmark against current locale.
Comment #12
gábor hojtsyWant to post a patch at #1789090: Warnings when exporting templates: addcslashes() expects parameter 1 to be string as well for that bug specifically or mark it a duplicate in favor of this bigger improvement?
Comment #13
lars toomre commentedBelow are the notes that I made while reviewing this patch. I am unable to roll a patch at this time so I am unable to re-roll a patch that incorporates these comments. Hopefully, someone else will be able to.
Aside from the comments below, consistently throughout this code the one line descriptions need to be changed to active tense (e.g 'Gets' instead of 'Get').
Perhaps 'Loads strings by locale ID.' Also this docblock needs type hinted @param and @return directives.
Perhaps 'Loads strings by source and optional context.' Needs @param and @return directives too.
Can we add type hint 'array|object'?
Needs to be active verb.. 'Sets'
Missing type hinted @return directive.
Ibid. Occurs elsewhere in patch too.
Missing @param and @return directives.
s/Check/Checks/ and needs @return directive.
Should be rewrapped for 80 characters. Add type hinting to each @param. Add '(optional)' to start of descriptions for $fields and $options. Add missing @return directive.
Please add type hinting and '(optional)' at start of descriptions of $fields and $options.
Missing @param and @return directives.
Missing @return directive.
Missing @return directive.
Missing @param and @return directives.
Missing @var directive.
Ibid.
Can we add @return type hint here?
Missing @return directive.
Perhaps rewrite as '@param bool $is_new' and '(optional) TRUE if the string is new; otherwise, FALSE. Defaults to TRUE.'
Also needs @return directive.
Needs @return directive and type hint as well as all descriptions should end in a period.
Not sure about the ordering here... does not seem 'sane' according to #1624564: Coding standards for "use" statements.
Missing @var directive.
Comment #14
jose reyero commented@Gábor,
Added a comment on the other issue, I don't think we should mark it as duplicate yet. There's the other part that needs to be fixed on the PoItem class and I don't feel like extending the scope of this one (yet). Fixing the duplicates issue was just checking whether this new API was up to the task, and apparently it is :-)
@Lars Toomre,
Thanks for the review, I will be fixing these issues myself.
Comment #15
jose reyero commentedFixed code style issues in #14, and some more code cleanup.
Comment #16
lars toomre commentedHere are my comments from reviewing the patch in #15. In general, this looks much better than before. Hopefully, these can be incorporated in the next re-roll.
I think this should be 'Drupal\locale\LocaleSource|null'.
Should start with '(optional)' and then include what happens in the default case.
@return needs '|null' appended.
Missing @return directive.
Ibid.
Ibid.
Ibid.
What happens in default condition?
Ibid.
Needs a blank line before @return.
Suggest 'with any of the following optional keys:'.
Missing @param description.
Missing @return description.
Missing @return directive.
Missing @return directive.
Should start with '(optional) '.
s/Load/Loads/
I don't think this @return is needed.
Missing @return directive. Also needs to start with '(optional)'.
Ibid.
This looks strange. Perhaps '$target->save()'?
s/Build/Builds/. also needs @return directive.
Comment #17
gábor hojtsyI think the latest patch looks like a good general improvement, and would indeed unblock further work on #1777070: Refactor and clean up source string location handling which is a major piece. So Jose, if you have time to do the cleanups suggested by Lars, I don't see any other missing pieces that we'd need to deal with anymore. The patch looks pretty good :)
Comment #18
jose reyero commentedUpdate:
- Fixed all code style issues in #17.
- Run some quick t() benchmarks agains the old version, no significant differences seen (which makes sense since the queries thrown are just the same and the only additional overhead should be the query builder).
If anyone wants to try, this is the code for benchmarking, which should translate all strings in your locales sorce table once:
Comment #19
jose reyero commentedYes, I know, I've just realized I should have disabled locale caching for the benchmarks. Running it again (without caching) and getting some differences, studying the results deeper.
Comment #20
jose reyero commentedAfter some more benchmarking, disabling all caches, these are the findings:
- The patched version is slower, as much as 3x (loading around 6000 translations takes 3000 ms as opposed to 1100 - 1200 with the old version)
- This is due to Drupal's query builder which is surprisingly slow: Just replacing the current db_query() with a db_select() causes all that delay. (!!!!!!)
Though this shouldn't be a major performance issues as we never load that many translations in a single page and all translations are cached for regular page requests (thus with caching enabled the difference is not noticeable), I don't think we should make things any slower (we have all the other new APIs already doing that ;-) ) so I'll be rewriting some parts of the patch using straight queries for the most often used functions (loadById, loadBySource).
Comment #21
gábor hojtsyHa, that is pretty unfortunate, although I kind of expected it :/ While doing these changes, can you also add a couple line of comments above where the direct queries are done to something like:
Something like that (wrapped to 80 chars properly :).
Comment #22
jose reyero commentedOk, here's the patch that:
- Replaces query builder by fast query for LocaleTranslation's loadBySource (the one used by t and po import) and loadById (used when editing strings)
- Adds Gabor's comment in #21, properly wrapped :p
- Since we are not passing anymore the fieds to load (that was intended for the query builder to build faster queries) simplified options all around, not needing $fields array anymore...
- Some minor code cleanups and simplifications (less options, less code...).
The new benchmarks:
- Difference is negligible (1200 ms vs 1100 ms when translating 6000+ strings),
(that minor difference is due to the extra field loaded in order for the LocaleTranslation::loadBySource() to be reusable by the po import, so it needs 'customized' field too, and I don't think this is worth making it more complex)
Comment #24
jose reyero commented#22: locale_string_object-1785086-22.patch queued for re-testing.
Comment #26
jose reyero commentedThe problem with the tests seems to be like this:
In the upgrade test, there seems to be a function using t() with a Drupal 7 database (which fails because it doesn't have the customized field). Ay idea?
The testbot error page, when running the test in my box, attached screenshot:
Comment #27
andypostJose, there's issue explaining db_select performance #1067802: Compare $connection->query() and $connection->select() performance
Also there's a comment in DrupalDatabaseCache::getMultimple()
I think it's abd idea to allow hook_execution in t() it could be used in early bootstrap and probably could lead to unpredictable results
Comment #28
jose reyero commentedFixed issues / marginally improved performance by adding a new API function for this quick translation searches (that is reused too for po imports too).
Simplified the query builder still a bit more, removing unneeded 'join' and 'fetch class' options.
Moved around loadMultiple() functions that make more sense on their respective classes.
Added tests for the new LocaleTranslation::findTranslation() function.
Minor improvement (API consistency). LocaleTranslation's methods loadById and loadBySource now return only string objects fully populated (since they're not used anymore for critical queries...)
@andypost,
Thanks, I've added my comments there. About hook_execution, no idea.. While I think there's something wrong with that tests and/or the update functionality using t() function, I don't have the time to look into that and anyway all it takes on our side is some minor API change (which is anyway a minor performance improvement).
Comment #29
gábor hojtsyThanks for brining the performance of this up to what was there before. I think this is a great cleanup and would serve as well in Drupal 8. It also serves as a base API for #1777070: Refactor and clean up source string location handling which is a major task and targeted at the D8 feature freeze.
Comment #30
catchThe database connection should be injected here, rather than using the procedural helpers.
If it's a base class it should have a 'Base' suffix - so
LocaleStringBase.There's no interface here at all but this looks like a public API that people will be using. Why not?
The static functions make this harder to dependency inject. I assume the reason they're static is because they have nothing to do with the state in this class (string IDs etc.). With entities we've handled this by having storage controllers separate from the classed object itself - why not the same pattern here? At the moment this feels like it's doing too many things at once in the same class.
Same with this one. This also has the same issue that the database isn't injected.
Since we cache locale strings, I'm fine for the change to the select query builder from a performance standpoint, but thanks very, very much for actually checking the difference :)
Comment #31
gábor hojtsy@catch: thanks for the review. To put this issue into perspective, we bumped into needing to touch locale tables in #1777070: Refactor and clean up source string location handling and Jose decided to finally tackle a more general API for locale string management instead of just copy-pasting a couple specific locale queries to the new place scattering that even more. I don't think we have a vested interest per-say in introducing this now and it does not give us any features we don't have now, it merely cleans up code. So if you prefer the current one-off queries and do not consider the patch an improvement, then we can go and postpone this to after December 1st (or Drupal 9) and just keep doing one-off direct locale table queries to speed up the actual features we are working on. Those are subject to the December 1st cut-off, so instead of perfecting this spin-off with storage controllers and dependency injection, we can focus on the real problems we are trying to solve.
Comment #32
catchI don't think we need to tackle dependency injection here, that's not properly happening in core yet anywhere but people are starting to push for it when new stuff goes in so I brought it up.
But splitting the class into storage vs. data feels necessary prior to commit and should not be much work either.
Comment #33
catchAlso indicating you'll drop work on refactoring patches every time I push back doesn't incline me to want to bother reviewing things in a timely fashion at all, nor to commit new features if they're going to introduce maintenance overhead.
Comment #34
gábor hojtsyFact is, there are 5 months of refactoring planned into the release timeline and 9 weeks before that in which we can still introduce new features, so I'm focusing on these 9 weeks, not those 5 months at this point.
Comment #35
gábor hojtsyAll right, discussed this with @catch on IRC, since #1777070: Refactor and clean up source string location handling only touches 2 locale queries and adds 2 new ones (and it is a new feature vs. this patch), it would make sense to get that done instead and have this be done (possibly even after December 1st). Moving off of the sprint for that. Let's return to our real feature at #1777070: Refactor and clean up source string location handling instead of this side-track unless @Jose Reyero wants to rework this ASAP.
(Moving off of the sprint for that).
Comment #36
effulgentsia commentedI agree with catch that for normal priority feature requests that aren't blockers for other issues, patches need to incorporate legitimate feedback before being committed. I also agree with Gabor that Jose and other D8MI leaders/experts have higher priority things to work on before feature freeze. That does create an unfortunate situation that good (but not fully refined) patches can sit in limbo for a while or not make it in to D8 at all. To combat this, I'd like to try out an "Across the finish line" tag (thanks to webchick for coming up with that name). I'm hoping that there are existing or new core contributors out there who want to help get cool improvements like this in, but who don't yet have the expertise (or time) to work on issues like this from scratch, and who want to build up their expertise by helping to finish these kinds of issues. Note that this is different from the Novice tag, as these kinds of issues may require more Drupal experience or time than what we typically use the Novice tag for.
Please help spread the word about this tag, and apply it to other similar issues.
Comment #37
jose reyero commentedHey, just fyi, I'm almost done with that refactoring, which looks pretty interesting :-)
So I will be posting that updated patch for review soon, I think that will be my last try at this one :D
Comment #38
webchickRestoring tag.
Comment #39
effulgentsia commentedRestoring correct tag :)
Comment #40
jose reyero commentedPretty close but not yet there (some issues with query builder mainly, tests not passing yet). Working on that.
Done some important rework:
- Locale string storage is retrieved from locale_storage(), which is an actual object.
- Strings are bound to their storage so you can still run save() or delete() operations on them.
- There are now StringInterface, StringStorageInterface and StringDatabaseStorage.
- Some methods redefined to be as simple as possible...
- Kept the high performance query functions, only now they are in the Storage class (which is where they belong so they can be optimized for storage). See findString() and findTranslation() methods in StringStorageInterface.
- Added back $fields parameters for string loading methods. Since storage is abstracted now it cannot take anymore db table related parameters (nor any database related anything), so using just 'fields' 'values', 'filters', etc...
@Gábor Hojtsy,
If you can take a look at it and let me know whether the API changes look ok to you....
@catch,
Now locale storage can be injected and there's a whole new set of interfaces. Does the class & interface layout look ok?
Comment #41
gábor hojtsyComment #42
gábor hojtsySo the current class/interface hierarchy is:
This is quite a few levels of abstraction added compared to the direct queries we had before the patch, but it certainly provides for more flexibility and looks logical as-is.
Given that all of these are in the locale namespace anyway, would it make sense to rename LocaleSource to SourceString and LocaleTranslation to TranslationString? Or just Source and Translation? They do not have any naming relation to the string interfaces / base classes they extend anyway.
Plus one minor thing, noticed that the StringBase file level comment says "Definition of Drupal\locale\LocaleSource". Should be fixed.
Comment #44
jose reyero commentedAnd this is the final version - I hope :-)
- See notes in #40
- Fixed naming issues as suggested by @Gábor Hojtsy in #41
- Simplified the fast query builder, now using it only for findTranslation, not for findString wich uses the reguar queries, but anyway that function is not used in the code yet, it is there just for completion of the interface.
New API, usage examples:
Comment #45
gábor hojtsyTook care of concerns from catch, looks good to me.
Comment #46
gábor hojtsyPutting back on sprint merely as a tracking helper. Also, for some reason lost the language-ui tag.
Comment #47
dries commentedAssigning this to catch as he did an in-depth review in #30. I'll leave it to him to commit (if ready). Thanks!
Comment #48
catchI think this has just been broken by cache prefix clears removal (because the parameters to __construct() for CacheArray changed), sending for re-test.
Comment #49
catch#44: locale_string_object-1785086-43.patch queued for re-testing.
Comment #50
catchOK a few more comments. I saw several issues with documentation when reading through again, but I left those for now.
I'm not sure why the patch continues to pass despite the __construct() arguments being incompatible.
Why isn't this using db_select()?
This one could just be a straight db_query() though since it's not dynamic at all.
Same question here.
Why is it performance critical how many fields are loaded? Since strings are cached anyway it feels like it's probably not, but would be good to know why this optimization is here if that's not the case.
Comment #51
andypostI think usage of db_select is required only in places where query actually requires to be altered, all other usage of db_select is just a performance overhead and dependency on hook subsystem
Comment #52
jose reyero commented@catch,
If you mean LocaleLookup, the class overrides the parent's constructor (not by this patch, it was like that before, we just add one more argument here). And anyway, whatever patch was committed should have taken care of that (previously overridden constructor)
That produces the performance critical query mentioned above (#20), comments about that are in the interface definition.
Similar queries happen to be used too from other parts of the module (js translation, po imports) with different parameters, that's why we are using an ad-hoc query builder here.
All the usages of this query may produce thousands of queries on a single page request. Yes, translations are cached, but when the cache is flushed (every time a translation is updated) it is rebuilt upon demand on next request so caching won't help at this point.
About the other issues (using db_query instead of db_select), ok, I'll get them fixed tomorrow. Thanks for the review.
Comment #53
jose reyero commentedThinking better, doing it today.
Replaced db_select() by db_query() as suggested in #50, #51
Comment #54
gábor hojtsyResolved or explained reasons for all of @catch's concerns. Should be back there then.
Comment #55
catchSorry I don't really think this is performance critical, the results are cached and it's not a slow query (assuming it hasn't changed when converted to the query build), just PHP overhead from db_select(). We should try to optimize db_select() but working around it should only be used in extreme cases (like the database cache backend where it completely destroyed cached page performance).
I'm wondering a bit if we could optimize some of the query building a bit - i.e. create a stub select query object then fill it in with the specifics each call to that method, would that help at all? If it's OK let's put the db_select() back in here than open a follow-up to try to either optimize db_select() or see if there's a way to avoid duplicating some of the specific query building.
Adding/changing translations should be quite rare, especially if they're done in a staging environment then imported. Additionally if we wanted to optimize translation cache clears we could potentially write through to the cache object with the updated translation rather than clearing the whole lot.
With only selecting some of the fields, I was asking why it's performance critical that only some fields are selected - again when the results of the most performance-critical query are cached anyway. Have any benchmarks been done on whether excluding fields actually affects performance measurably here? Right now it's introducing inconsistency in return results (i.e. "the results of this may not be suitable for CRUD operation" with no tangible benefit. We might even be able to save some time in the query builder by just doing a SELECT * instead of individually adding fields, should be less function calls at least.
The changes from ->select() to ->query() the other way look great, thanks for those.
Comment #56
andypostSo it needs benchmarks?
As I pointer above - there's no way to make db_select() none-alterable, so it makes whole translation system dependent on full bootstrap and hook sub-system
Comment #57
jose reyero commentedThe new version of the patch fixes some comments and cleans up the internal functions of db storage saving some code (all db related ones, are now dbXXX which helps seeing at a glance which are the ones interacting with the database backend).
Now about open questions:
@catch,
I really think I'm missing something here. First you asked for an StorageInterface, and here it is, then we agreed for critical queries (that may run thousands of times in a page) we wanted db_query() instead of db_select() and that's what we've done (but for the complex query builder now in dbSelect().
About whether they are performance critical I can tell you every time you update a translation, the next page request is noticeably slower. Of course, it needs to rebuild the full translation cache, the javascript translations (which need js file parsing, etc...)
Whether that workflow can be optimized, I think yes, but anyway that should be the subject of a different patch, I believe.
> "Adding/changing translations should be quite rare, especially if they're done in a staging environment then imported",
I think is a strong assumption I wouldn't make. And if I made one from my experience it would be the opposite, as for most sites I've seen the translators work right on the live site (just because we don't have a workflow to really stage translation updates other than manual export / import).
So basically we are facing the scenario of the site being way slower the week the translation team is reviewing the translations (yes, believe it or not, translations being updated on the live site every few minutes).
About the pseudo-query-builder in findTranslation(). It may look ugly but given the performance constraints above we are deling with requests with different conditions to an StorageInterface.
Let me say this is a really abstracted StorageInterface, the kind that doesn't let the caller even know whether this is a database or what, so we need to map 'storage agnostic' conditions (or simple field =>value mappins) to a database backend which (I thought we had agreeement on that, I don't know anymore) needs to have some speed optimizations.
Moreover: As this is an storage interface (which doesn't assume a database), queries shouldn't be alterable as long as possible.
(Note EntityStorage interfaces are not *complete* ones as there's code everywhere accessing the db directly, which doesn't happen in this case as we've abstracted *every single storage access*)
Btw, the 'stub query' option, I've already tried it and performance is somewhere in between (around 2x slower than db_query, since every query has different conditions so there's not a bit part you can reuse so you need to go through the query builder anyway)
@andypost,
We already have some above but if you want to try 'loading all fields' vs 'loading just the needed ones' that may help given catch's conerns.
Just keep in mind we are facing the 'locale cache rebuilding scenario' so it is not about many requests, but about a request doing thousands of queries. See my example code in #18
Comment #58
gábor hojtsyComment #59
catch@Jose I think I had the original change the wrong way 'round. I thought the patch had changed from building the query with concatenation to using the query builder, because despite being slower the strings are cached anyway. Sorry for any misunderstanding but despite the query builder being slower, we absolutely have to use that for dynamic queries.
That's a poor workflow on the site then, or we need to find a way to flush translation caches less often like writing back to them.
Comment #60
gábor hojtsy@catch: that sounds like you suggest we take the performance regression here in favor of better looking code then.
Comment #61
catchYes, we have db_select() and that's mandated for dynamic queries. We have one or two highly commented exceptions to this where there's an otherwise static query with a dynamic table name (i.e. in the dbtng cache backend), because it's right in the critical path even on cached pages and was such a bad performance regression without it. However actual dynamic query building there's really no option - we might as well rip out db_select() altogether if we're going to start doing that. Also this query isn't in the critical path at all - it only runs (albeit loads of times) on a cache miss.
I'd be interested in:
- does the db_select() overhead reduce if the field optimization is taken out.
- it sounds like Jose tried the stub query and that helped a bit.
Also this issue reminds me a bit of sun's attempt to rewrite t() - if t() instantiated an object with the original string, then didn't try to get any translations until a __toString() method was called, then potentially we could try to query all the translations on a page at once the first time that happens. That's not strictly related to this issue but in short there's potentially other ways to optimize this rather than avoiding db_select().
Comment #62
jose reyero commentedOk, I think I got it now, sorry for some misunderstanding on my side too:
Then I'll be rewriting the patch with these premises:
- Dynamic queries *must* use db_select(), no hackish query builders allowed.
- We can take some (as small as possible) performance regression in exchange for cleaner architecting.
That should certainly save us some code and make the remaining look better. Then we need to look into ways of optimizing the locale caching on a follow up issue (Maybe there are ways of not flushing the whole cache, etc..).
Comment #63
catchOne more thing with the performance issue and db_select() again. Apologies for not seeing all these things at once...
Here's all the usage of findTranslation I could find:
I don't see any problem with adding an optimized method to the interface (i..e for returning a translated string given a source string, language and context), and using db_query() for that, then keeping the query builder for rarer operations where it saves code duplication. We have similar helpers for entities like user_load_by_name() or whatever. Would that help here?
Comment #64
jose reyero commentedDone some important cleanup of the patch:
- Using db_select() for all queries discussed above.
- Loading all fields by default (no noticeable performance loss).
- Simplified conditions and options all around keeping just the absolutely needed ones. Moved 'translated' from being an option to a condition, which makes all the code using the API more readable.
- Introduced a StringStorageException, similar to existing StorageExceptions (config, entity)
- Replaced the 'deleteLanguage' storage method by two more powerful ones that can take field conditions: deleteStrings(), deleteTranslations().
- Overall, a much cleaner and consistent StorageInterface with StorageExceptions, better function names, etc...
- Kept the 'exact fields to select' option, but now it's just and aditional option, not a parameter needed everywhere for some reasons:
a) Very minimal performance gain from locale lookup, a few ms.
b) Noticeable performance improvement, 10% - 20%, when doing mass-loading operations like loading all strings to export in a po file.
c) preventing the D7 upgrade from crashing, see #26
(Loading all fields by default anyway, that one is only used from LocaleLookup atm but may need to be used from other upgrade scripts in the future)
Note: Stub query didn't help at all since all the queries take too many arguments to be fully reusable thus all I could do was cloning a very basic pre-built query, that still needs all the joins and arguments. (my tests before were with a fixed one so not really a 'real life' situation).
About query building options, I've really tried a lot, only to find the only noticeable performance gain comes from using db_query vs db_select.
Comment #65
jose reyero commented@catch,
We were posting at the same time, it seems, just seen your post.
About introducing a specific function I think we can live without it for now, and look into optimizing other module parts (like not refreshing the whole cache when updating just a string, that should help performance more and will make this a non issue), and then see later, in the D8 cleanup and optimization phase, we can add it back if we didn't find a better solution in the meanwhile (Or the query builder didn't improve either).
Comment #67
jose reyero commentedNow I really feel stupid :D (because of previous patch failing tests).
Guess what: The D7 upgrade scripts do rebuild the js translations too !? (no further comments about that) and this is where the option to select just a few fields comes handy (again).
One more try after fixing that one.
Comment #68
gábor hojtsyHad a hard time reviewing the changes since no interdiff was posted, however there are no db_query()'s left at all in the code (only in the removed hunks :), and the remaining feedback was also taken care of as much as I can tell. We could use the improvements here in the major CMI multilingual tasks and time is pressing for us to get these improvements in, so if there are no more issues with the patch, getting it land would be great!
Thanks all!
Comment #69
catchGabor asked me to take a look at this again in irc. I don't see anything pressing at first glance - looks like most or all of my concerns were addressed, but don't have enough time at the minute to do a solid review prior to commit.
Unassigning me since anyone can commit at this point, I'll try to get this in next time I'm doing a commit spree if no-one beats me to it.
Comment #70
webchickI had a look through this patch with Jose and Gábor on IRC. In general this seems to clean up quite a bit of stuff and make the result much, much easier to read.
Here is some feedback from my review. The only one that needs to be resolved pre-commit is the docs for SourceString and TranslationString, but Jose and I are working on that in IRC right now. The rest are small nitpicks and could be a novice follow-up.
These are the two biggest new vocabulary words added with this patch; it'd be really nice to see more explanation here as to what they are, how they relate, how to know if my module needs to work with them.
This one too. Why else might we have to implement this class?
(nitpick) Can we move this below getStorage()? I almost missed it in my review.
(nitpick) Can we remove those two spaces after the count?
We talked a bit about whether 'target' should be passed in to locale_storage() as a parameter, but in the end decided that if someone needs a non-default target, they could create their own implementation. I was confused about how said implementation even gets *into* this function, given that there is no $storage_class parameter (or what have you), but Jose said it happens via the DIC. I'm not totally up to speed on that stuff, so I'm going to assume this is true and move on. :D
Comment #71
webchickOk, Jose and I worked on the docs for SourceString/TranslatedString on IRC, and came up with the following:
...
These aren't perfect descriptions, but at least a bit more info so someone coming into this brand new will understand the difference between them.
With that, I Committed and pushed this to 8.x. Yay! The remaining feedback in #70 (the stuff prefixed with "nitpick") is Novice material, so tagging for that and re-categorizing accordingly. Since this is just internal Locale module refactoring, Jose didn't think we needed a change notice for this. I did ask him to start a follow-up about that 'target' stuff, though... we should be consistent about that in core.
Comment #72
jose reyero commentedFollow up issue about storage controllers / target database, #1806756: How to register storage controllers / 'target' database parameter (Looking for a common standard)
Comment #73
jose reyero commentedThis is a follow-up patch that fixes all the issues found by @webchick in #71, some other small ones, and also includes some minor interface simplifications in the StringDatabaseStorage:
- Added missing query options in dbSelect() method, fixed test line using the wrong result for the assertion.
- About getStorage() function that had to be moved, added it into the interface (it was a private method before) so we've got now getStorage()/setStorage(), for interface completion and consistency.
- Simplifies the query builder dropping the 'fields' option and the related $options parameters, that are not needed anymore, all around. By building the query in the right order, we can create 'upgrade safe' queries, that is commented in the code.
About this last one, queries causing trouble with the upgrade, which was the reason we had that extra 'fields' parameter, created a new issue here, #1807272: Mixed locale issues with upgrade scripts, unit tests, 'Table simpletest..locales_source doesn't exist', etc...
About the locale_storage() function, I think I finally found the solution, though that (seems to be the standard approach) doesn't seem to be safe for install/upgrade, so ellaborating on that here #1806756: How to register storage controllers / 'target' database parameter (Looking for a common standard)
(These two issues seem to be related and mostly caused by the locale system triggered during updates, which is the first one, we may find a common solution for both.)
Comment #74
gábor hojtsy"its not bound to an storage" => "it is not bound to a storage"
Comment #75
jose reyero commentedThis one would need to be postponed for a while until this other is fixed, then we'll be able to drop the query hacks to get fields in the right order.
See #1809962: Move some locale updates to update.inc for a safe language upgrade.
Comment #76
jose reyero commentedSince previous patch went in, we are fine now for this cleanup. Changes from #73
- Fixed code formatting issues pointed out by @Gábor in #74
- Removed query ordering hacks, we don't need them anymore (cleaner query builder).
Comment #77
lars toomre commentedSmall nit if this gets re-rolled again. Otherwise, this looks good from a documentation perspective.
I believe that this method needs to document the exception possibility with a @throws directive.
Comment #78
jose reyero commented@Lars Toomre,
That is documented on the interface, see StringInterface's save() and delete() methods.
Comment #79
gábor hojtsyGreat cleanup, even including whitespace fixes in the tests :) Thanks!
Comment #80
webchickAwesome, thanks!
Committed and pushed to 8.x.
Restoring issue properties.
Comment #81
gábor hojtsyGreat, thanks all!