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
Cover backlink to vendor #1805
Cover backlink to vendor #1805
Conversation
Thanks, @xmorave2! I'm not in the office this week, but I'll review this as soon as time permits. |
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.
A few questions and suggestions based on a quick review....
themes/bootstrap3/templates/RecordDriver/DefaultRecord/cover.phtml
Outdated
Show resolved
Hide resolved
Thanks for a review @demiankatz, this should be ready for next round. |
Thanks, @xmorave2; this looks good to me, but I'd like to try some hands-on testing before merging it. I should have time for that early next year (time is very short at the moment, unfortunately). |
@xmorave2, apologies for the delays -- I have a lot of post-holiday catch-up to do -- but I finally had time to try this out on my test server. Unfortunately, I cannot get it to work at all. The first thing I did was merge this with the latest dev branch and resolve conflicts. It's possible something was broken in that process (though the only conflicts had to do with the compiled CSS files). Is this still working for you on your end? In any case, to be more specific about my problems: I indexed the sample ObalkyKnih records you shared with me, and I confirmed that I get cover images for those records on the current dev branch, both with or without "ajaxcovers = true" in my config.ini. When I switch to this coverBacklink branch, however, turning on "ajaxcovers = true" results in lots of loading spinners; the covers never actually appear. If I set "ajaxcovers = false," I do at least see cover images, but there is no backlink included. I apologize if I'm just failing to set up my test environment correctly, but it seems there may be some larger problems here. Please let me know if this is enough to help you troubleshoot, or if you need me to provide more details or spend more time debugging on this end. Also note that I have slated this for the 8.0 milestone. Since the translation work for release 7.1 is already complete, and this adds new strings, it will have to wait for 8.0. Fortunately, since 7.1 should be released next month, 8.0 development will begin very soon... and assuming we can work the bugs out of this, I can merge it to the dev-8.0 branch as soon as it is working, if an early merge would be helpful. |
@demiankatz: I apologize for delay, but now this is ready for another round I hope. |
Thanks, @xmorave2, the bugs now seem to be fixed. However, I notice a couple inconsistencies: 1.) Cover backlinks show on the record view, but not in search results. (I'm guessing this might be intentional). 2.) Cover backlinks only show when AJAX cover loading is enabled. (This is, of course, a technical limitation). So this leads to some questions: 1.) Is there a bug regarding inconsistent display locations for the link? If the inconsistent display is intentional, should it be configurable? 2.) I understand why we need AJAX cover loading to display these links... but if displaying the links is a contractual requirement, this could be a problem. Should we add a mechanism that allows cover loaders to determine whether or not they are being used in an AJAX context and refuse to serve content (perhaps with a warning message to the log) if configured incorrectly? In any case, thanks for the progress on this -- it looks good and addresses a long-standing need! |
Thanks for review @demiankatz ad 1) Yes, it is intentional, inserting link into a link (the cover on results are links to records) does not work well... but I might try to move the source information out of link... (in fact, the similar manipulation is now done in covers.js, so it should not much work, I'll try it) ad 2) I do try to make some mechanism you are recommending, that does make sense, to ensure the legal requirements are met when using covers from external sources... |
@demiankatz I have tried to address both issues and this is so ready for another round |
This pull request introduces 1 alert when merging e33799a into 1267712 - view on LGTM.com new alerts:
|
Thanks, @xmorave2! I'll try to review this again later in the week. In the meantime, did you see the lgtm-com alert? Any thoughts on that? |
This pull request introduces 1 alert when merging 743ca28 into 1267712 - view on LGTM.com new alerts:
|
@demiankatz I just tried something like quick fix, which does not work ;) But i know how to fix it, it just need a bit of time, I will do it tomorrow |
@demiankatz LGTM issue is fixed |
Thanks for the progress on this! I'm requesting a review from @crhallberg in case he has any comments on the LESS/JS changes, and I will do a bit more review and testing of the remaining parts later today as time permits! |
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.
Thanks again -- things are working consistently for me now, though I still have a few questions...
themes/bootstrap3/js/covers.js
Outdated
var span = $('<span class="cover-source-text"' + response.data.backlink_text + '</span>'); | ||
source.append(span); | ||
} | ||
if (inlink === true && response.data.backlink_on_results === true) { |
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.
This seems a bit fragile -- in that the identification of whether the backlink is in results or not seems to be based on a variety of circumstances that might not be entirely specific. I wonder if we should just display backlinks everywhere and rely on CSS customization to hide them in unwanted places. Would that be simpler?
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 it is not the same (inlink vs search result). The reason I use this type of distinction is that, if a link is inserted into another link in html it simply does not work well and I need to make same dom manipulation to get the inner link out of outer link....
simple solution would be to rename the option to something like 'other the detail page'
or change the non-detail page logic somehow.... but then we may need much more options - channels, related tab, and possibly some more in future...
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 currently have cover size settings that can be configured based on template names: see these configurations. Perhaps we could use a similar mechanism for allowing the user to configure where backlinks appear. Maybe we could replace the mandatoryBacklinks boolean property with a mandatoryBacklinkLocations array, and then locations in this array could forcibly override user preferences for those locations (and when this is non-empty, that tells us we have to force AJAX covers).
I think that meets the use case and is flexible... but is it too complicated to implement? Should we go ahead with that approach, or should we do something simpler for now and refine as needed?
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 honest, this seems a bit overcomplicated for our current need, although I agree it would be much more flexible, and I could imagine such a implementation in the future, if it is OK for you, I would like this to be merged as is and probably continue with this on another PR in the future.
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 agree that we don't need to fully implement this to get the PR merged, but I wonder if moving a little bit in that direction would make the code simpler and more readable. For example, what if we replace the boolean isBacklinkMandatory()
and showBacklinksOnResults()
methods with a single mandatoryBacklinkLocations()
method that returns an array? Then current code that checks for the boolean can instead check for a non-empty array. For now, we can code this so that backlinks are only displayed when mandatory, which keeps other logic simple... but this makes it easier to add an additional configuration layer if we decide we need it in the future, and it also keeps the cover drivers more independent of the UI behavior -- they tell us details about the provider (where a backlink needs to be displayed, which is constant for each provider), but reconciling that with user preferences can be delegated to a higher layer of code. Does that make sense?
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.
That does make sense, I've done a bit of refactoring here.
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.
Thanks, this is definitely a step in the right direction! Would it be worth taking it a little bit farther and exposing the whole backlink_locations array to the JS instead of mapping it to the backlink_on_results boolean? Again, just trying to make this a little more generic if possible. I'm still not entirely comfortable with assuming things are in results just because of the presence of links around cover images, since I think there are some possible exceptions and edge cases there... but I'm willing to accept this as-is with a "TODO: make location detection more accurate/specific" comment if that's as far as you want to go right now!
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.
That makes sense @demiankatz. Now the whole backlink locations array is passed. I also tried to reuse the context for backlink display
themes/bootstrap3/js/covers.js
Outdated
if (typeof response.data.url !== 'undefined' && response.data.url !== false) { | ||
img.attr("src", response.data.url); | ||
container.children().not("img").hide(); | ||
var inlink = element.parent().is('a'); |
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.
Can we add a class to the expected link? This seems easy to trip with customizations. I can come back to this in the future if it proves to be especially tricky.
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.
@crhallberg How do you mean this? Do you think we should add a class into html template and use it then in covers.js for identification to be more specific? Or do you think add a class by this javascript code to be able to select manipulated elemetnt using CSS?
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.
@crhallberg can correct me if I'm wrong, but I suspect he's suggesting the former: adding a class into the HTML template to reduce the odds of this code hooking the wrong element because of a fairly broad selector.
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.
Thanks, I added class to templates
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.
Thanks! @crhallberg, are you happy with the record-link
class, or would you prefer cover-link
or something else? (I'm happy to make the change if necessary -- not trying to drive @xmorave2 crazy with nitpicky changes :-) ).
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 would prefer cover-link
or record-cover-link
but I don't think it's worth holding this up.
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.
Thanks, @crhallberg! Do you have a preference, @xmorave2? I hope to do final testing and merging of this PR next week, so I can adjust the class name at that time if you have a preference.
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 choose record-cover-link. I pushed a commit with this change
I also resolved the merge conflicts to get our green checkmark back on the build. :-) |
Thanks @demiankatz |
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.
Thanks for taking the time to work on this -- I think this is much, much more clear, and also a good foundation for greater flexibility in the future. I just have a few very minor comments. Once you have a chance to address them (and @crhallberg has had a chance to weigh in again), I think I should be able to merge this.
themes/bootstrap3/templates/RecordDriver/DefaultRecord/cover.phtml
Outdated
Show resolved
Hide resolved
This all looks good to me! |
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.
Thanks, @xmorave2 -- before I do my final test (and hopefully merge), I spotted one small potential issue that seems worth addressing before it potentially comes up again during static analysis. :-)
$metadata = $this->getMetadata( | ||
$driver, $size, $resolveDynamic, $testLoadImage | ||
); | ||
return $metadata['url'] ?? $metadata; |
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.
Should this be $metadata['url'] ?? false
? If $metadata['url']
is unset, then $metadata
is most likely an empty array, which is not one of the documented return types of this method.
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 is a bit more complicated - getMetadata from AbstractCover can return empty array, which is then passed from Router::getMetadata to Router::getUrl.
But Router::getMetadata can even return false or null values... we probably want these values to be passed and returned by getUrl I think...
I'll take a look on it and will see...
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 apologize if I just skipped a step in the code during my review -- that's very possible. If nothing else, it's a sign that we should add a comment here to clarify what is going on, so we don't ask ourselves this question again in the future.
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 tried to make it more clear and also added a case when empty array is returned from getMetadata, what do you think about it @demiankatz
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.
Thanks, @xmorave2. The comment helps to clarify what is going on, but I'm not sure if the implementation matches the comment. If $metadata is null
or false
, then empty($metadata)
will evaluate to true, and the code will normalize the return value to false. If you want to preserve the null return and be sure you never return an array, would it be better to change the !empty()
check to !is_array()
instead?
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 absolutely right @demiankatz, thanks for catching this. I've fixed it now
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.
Great, thank you! I believe we're all set now -- I've just merged this.
No description provided.