Community Forums › Forums › Archived Forums › General Discussion › More Specific Placements Than Hooks Can Provide
- This topic has 11 replies, 2 voices, and was last updated 11 years, 8 months ago by
Lord_Devi.
-
AuthorPosts
-
August 23, 2013 at 5:28 pm #58537August 25, 2013 at 6:41 pm #58803
Gary Jones
MemberIn wp-includes/comment-template.php, look around like 1626 and you should see a filter called
comment_form_default_fields
. This takes an array of fields, where each value is the markup that displays the field. You could filter it with something like (untested, and made-up in terms of what functions the review plugin wants you to use):add_filter( 'comment_form_default_fields', 'prefix_add_review_fields' ); /** * Add some made-up review plugin's stars output function underneath existing comment fields. * * @param array $fields Existing fields * * @return array Amended fields. */ function prefix_add_review_fields( array $fields ) { $fields[] = '<p class="comment-form-review-stars">' . review_plugin_stars() . '</p>'; return $fields; }
If using Genesis with an XHTML theme, you'll need to filter
genesis_comment_form_args
instead, which is an array with one of the keys calledfields
. If you want some function to output in between other fields, you'll need to do some array manipulation to make space for it.
WordPress Engineer, and key contributor the Genesis Framework | @GaryJ
August 26, 2013 at 5:10 pm #58941Lord_Devi
ParticipantOk ok.. I'm looking at that comment-template.php file you showed me. I see what you are talking about. If you would be willing, or anyone else, a little mini walk through in what you are doing while you construct that statement would go a long way with me!
With my understanding of what you are doing I adapted the following snippet you provided me with into this:
add_filter( 'comment_form_default_fields', 'comment_form_review_fields' ); function comment_form_review_fields( array $fields ) { $fields[] = '<p class="comment-form-review-fields">' . myrp_api_ratings_form_table( $post_id = null, $return = false ) . '</p>'; return $fields; }
1. If I am creating a functions or variables I like to go from the general to the specific, so I renamed the function to "comment_form_review_fields".
2. Editing the class for the review fields to be specific to the custom fields seemed appropriate.
3. The API code I need to generate the fields is "myrp_api_ratings_form_table( $post_id = null, $return = false )" so I put that where you indicated.It did indeed show up! And mostly worked. However, this inserts the fields in a very similar fashion to what I would get by trying to assign it to the "genesis_comment_form" hook. That is, the fields still appear outside of the #respond <div> 🙁 I need it to appear inside "#respond div #commentform form" element.
I'm attaching a screenshot of the relevant section of the site being examined with Firebug to help provide some more helpful information.
I've already included the snippet of code I am using to try and get this stuff appearing where it needs to be.
Thanks for the help and insight you have already provided me with by the way!
The highlighted line in the image are the fields I need inserted into the #respond <div> beneath it.
August 26, 2013 at 6:39 pm #58956Gary Jones
MemberTo address your points:
1. Prefix everything. (Google Nacin's post for just that phrase.) If your function is within a theme called "Devi", then call it devi_comment_form_add_review_field(). If it's in a plugin called "Foobar", then call it foobar_comment_form_add_review_fields(). "prefix" in my example is a hint that it should be replaced, not dropped altogether. The purpose of the prefix is to help avoid namespace collisions - that is, two sets of code trying to create two functions (or classes etc.) with the same name.
The inclusion of the verb "add" gives a clue as to what you're doing with the review fields - you could be adding them, removing them, amending them, or some other action - so making the code a little more self-documenting is not a bad thing.
3. When calling a function, you don't need to assign arguments to variables, so instead of
myrp_api_ratings_form_table( $post_id = null, $return = false )
you can just domyrp_api_ratings_form_table( null, false )
. However...4. Your accidental inclusion of the variable names can help me to help you solve why it's appearing in the wrong place. In short, the table is being echo'd immediately, instead of being assigned to the $fields array for later displaying. We can change that
$return
from false to true.Since I now know that it outputs a table, we can drop the paragraph element from wrapping it, since that would be invalid markup.
One further point that I missed in my quick suggested code, is that you should always check that a function from a plugin actually exists before using it - if you later deactivate the plugin for whatever reason, the site won't die of a fatal error.
All in all then, try the following as the function:
add_filter( 'comment_form_default_fields', 'prefix_add_review_fields' ); /** * Add some made-up review plugin's stars output function underneath existing comment fields. * * @param array $fields Existing fields * * @return array Amended fields. */ function prefix_add_review_fields( array $fields ) { // If plugin function doesn't exist, abort if ( ! function_exists( 'myrp_api_ratings_form_table' ) ) return $fields; // Add in the ratings table as one of the fields, returning it (true) $fields[] = myrp_api_ratings_form_table( null, true ); return $fields; }
I don't know the inner workings of that plugin function, but if you get an issue where the ratings don't seem to be applying to the right post, swap out that
null
and replace it withget_the_ID()
.
WordPress Engineer, and key contributor the Genesis Framework | @GaryJ
August 26, 2013 at 7:11 pm #58967Lord_Devi
ParticipantOh ok! Good pointers for your naming conventions. I also like the addition of the function test, to make sure it's there. I would have totally forgotten to do that.
I admit again, php is new to me, and I didn't know that about not needing to assign variables to arguments. I just pulled that line of code out of the MyReviewPlugin API directly.
I'm understanding better I think now, what you are doing how this works. I just think I may be having some added difficulty being added by this particular plugin or the fact the fields are a table.
I tried your code snippet again (as is this time), and was greeted with no extra field table at all 🙁 Outside or in.
so I tried a few different versions of what you suggested, trying to make my best educated guesses on what it could be that I could.
Namely I only altered the:
$fields[] = myrp_api_ratings_form_table( null, true );
Line. I tried the following variations, and in any instance where "true" was used, the table just did not display at all.
In all other instances, where "false" was used, the table appeared, but outside the actual form #respond <div> still. =/
$fields[] = myrp_api_ratings_form_table( null, true ); $fields[] = myrp_api_ratings_form_table( get_the_ID(), true ); $fields[] = myrp_api_ratings_form_table( $post_id = null, $return = false ); $fields[] = myrp_api_ratings_form_table( null, false ); $fields[] = myrp_api_ratings_form_table( get_the_ID(), false );
I also thought it might be prudent to try and see if I could remove the table and stuff as a possible complication factor. So I thought I would try to use your method to just output some generic text. So I could see if I could get some text to appear inside the comment form using it. But I must be doing something wrong, because I could not get this to display all anywhere! :
add_filter( 'comment_form_default_fields', 'prefix_add_review_fields' ); function prefix_add_review_fields( array $fields ) { $fields[] = '<p class="comment-form-review-fields">TESTTESTTEST</p>'; return $fields; }
You've been very helpful so far still Garyl! Thank you very much for taking the time to respond. =)
August 26, 2013 at 7:34 pm #58973Gary Jones
MemberAre you viewing the site whilst logged in? If so, it may not be appearing. Open a private browsing session and then check your site. I just throw your test filter into http://azzag.co.uk/multi-page and it shows up for non-logged in guests.
WordPress Engineer, and key contributor the Genesis Framework | @GaryJ
August 27, 2013 at 1:58 am #59009Lord_Devi
ParticipantYes! That was totally it!
I logged out and it was right there where it ought to be. Phew!
Thank you so much for your help Garyl.
I was able to extract from your help some better information about how to go about creating functions. How to find the information inside the code I need to use them effectively, and some good naming conventions. It'll take some practice of course, but it was very informative!
Using what you showed me, I expanded on it a bit to utilize this function available inside of Dynamik Website Builder for Genesis (I love that child theme SO much) to have the function also check for a custom conditional.
I nested it so that first the function checks for the existence of the plugin, like you showed; then it moves on to check if the post has had the label 'review' applied to it or not, and if so, THEN to display the comment form.
And it seems to be working great!
Here is the final product:
/*------------------------------------*/ /* MyReviewPlugin Comment Review Form */ /*------------------------------------*/ add_filter( 'comment_form_default_fields', 'prefix_add_review_fields' ); function prefix_add_review_fields( array $fields ) { // Verify the plugin is installed. if ( ! function_exists( 'myrp_api_ratings_form_table' ) ) { return $fields; } // Add review form only if the label "Review" has been applied to the page. elseif (dynamik_has_label('review')) { $fields[] = myrp_api_ratings_form_table( null, true ); return $fields; } return $fields; }
I admit a little confusion in a way though. This method seems to work fine, but it is different from what I was seeing around on my.studiopress.com. I was looking at their collection of snippets to modify comments, trying to figure out how to work with this.. and I noticed they were using a filter "genesis_comment_form_args" a lot to modify the form.
You can see examples of this over at: my.studiopress.com.
An example is someone using the following code to modify the "Speak Your Mind" text:
add_filter( 'genesis_comment_form_args', 'sp_comment_form_args' ); function sp_comment_form_args($args) { $args['title_reply'] = 'Leave a Comment'; return $args; }
I don't suppose you (or someone else) could explain to me the difference here between using "genesis_comment_form_args" and "comment_form_default_fields". Or even if one could use either methods..
It SEEMED to me, like genesis_comment_form_args is a way to do perform similar (if not identical) tasks. And I thought if Genesis has an API to be doing such things, I should probably be using it.
In my stumbling ignorance, I tried to adapt the genesis_comment_form_args to do the same thing Garyl's code does, but was unsuccessful. =/
August 27, 2013 at 3:12 am #59017Lord_Devi
ParticipantOk one more post here...
I have been going through comment-template.php, the WordPress codex, Genesis snippets, and I have one other related problem I am unable to solve. I was hoping that by fixing the above problem I would learn enough to fix the second issue, but it is not coming to me.
The review plugin also displays each comment's associated rating if it has one. Currently I have this assigned with a hook bound to "genesis_after_comment", but the rating is then appearing BENEATH the "reply" button, and I need it above the reply button.
I don't know if I need to use a "replace_action" function or something here or not...
But here is a picture of what the comment looks like now, and you can see how the star ratings are beneath the "Reply" link.
How can I have this appear above the Reply button?
This is the current code I am using to summon the stored rankings:
myrp_api_comments_ratings_table( $comment_id = null, $post_id = null, $return = false )
And the image of the problematic result:
August 27, 2013 at 5:07 am #59026Gary Jones
MemberThere's several levels of filters going on here.
*
comment_form_default_fields
is from WordPress, and edits just the fields found in the comment form.
*comment_form_defaults
is another WP one, that allows filtering of all of the comment form arguments (which happens to include the fields as well).
* Genesis creates its own filter function (genesis_comment_form_args()
) that hooks intocomment_form_defaults
.Before Genesis 2.0, it re-built the fields to be a little more accessible over the WP default markup, and tweaked a few of the other labels. To make it easy for developers to tweak what Genesis has said should be the defaults (over what WP said should be the defaults), the
genesis_comment_form_args
filter was added.
Since Genesis 2.0 however, for HTML5 themes, Genesis defers back to the WP defaults for HTML5 markup, and only maintains the XHTML markup (and use of thegenesis_comment_form_args
) for older child themes. Since you're using Dynamik which I believe is a HTML5 theme, then filtering ongenesis_comment_form_args
would never have worked, as it simply doesn't get called. Look at genesis/lib/structure/comments.php line 382 and you can see that if genesis_html5() is true, the rest of the function is ignored, including the filter at the bottom of it.In terms of your second question regarding displaying the rating - you're right, in that
genesis_after_comment
is fired after the reply button is displayed. What we need to do, is create a custom comment callback, and tell Genesis to use that instead of it's own one. The steps are:1. Copy the function
genesis_html5_comment_callback()
into your functions.php file, and rename it with your own prefix.
2. Tweak the function so that your rating appears where you want it.
3. Filtergenesis_comment_list_args
so that your custom callback is used./** * Custom comment callback for genesis_default_list_comments() if HTML5 is active. * * Does <code>genesis_before_comment</code> and <code>genesis_after_comment</code> actions. * * Applies <code>comment_author_says_text</code> and <code>genesis_comment_awaiting_moderation</code> filters. * * @param stdClass $comment Comment object. * @param array $args Comment args. * @param integer $depth Depth of current comment. */ function prefix_html5_comment_callback( $comment, array $args, $depth ) { $GLOBALS['comment'] = $comment; ?> <li <?php comment_class(); ?> id="comment-<?php comment_ID(); ?>"> <article <?php echo genesis_attr( 'comment' ); ?>> <?php do_action( 'genesis_before_comment' ); ?> <header class="comment-header"> <p <?php echo genesis_attr( 'comment-author' ); ?>> <?php echo get_avatar( $comment, $args['avatar_size'] ); $author = get_comment_author(); $url = get_comment_author_url(); if ( ! empty( $url ) && 'http://' !== $url ) { $author = sprintf( '<a href="""%s""" rel="""external"">%s</a>', esc_url( $url ), $author ); } printf( '<span itemprop="name">%s</span> <span class="says">%s</span>', $author, apply_filters( 'comment_author_says_text', __( 'says', 'genesis' ) ) ); ?> </p> <p class="comment-meta"> <?php $pattern = '<time itemprop="commentTime" datetime="%s"><a href="""%s""">%s %s %s</a></time>'; printf( $pattern, esc_attr( get_comment_time( 'c' ) ), esc_url( get_comment_link( $comment->comment_ID ) ), esc_html( get_comment_date() ), __( 'at', 'genesis' ), esc_html( get_comment_time() ) ); edit_comment_link( __( '(Edit)', 'genesis' ), ' ' ); ?> </p> </header> <div class="comment-content" itemprop="commentText"> <?php if ( ! $comment->comment_approved ) : ?> <p class="alert"><?php echo apply_filters( 'genesis_comment_awaiting_moderation', __( 'Your comment is awaiting moderation.', 'genesis' ) ); ?></p> <?php endif; ?> <?php comment_text(); ?> </div> <?php // Display ratings if ( function_exists( 'myrp_api_comments_ratings_table' ) ) { echo '<div class="comment-rating">'; myrp_api_comments_ratings_table(); echo '</div>'; } comment_reply_link( array_merge( $args, array( 'depth' => $depth, 'before' => '<div class="comment-reply">', 'after' => '</div>', ) ) ); ?> <?php do_action( 'genesis_after_comment' ); ?> </article> <?php //* No ending </li> tag because of comment threading } add_filter( 'genesis_comment_list_args', 'prefix_comment_list_args' ); /** * Tell Genesis to use our custom comment callback. * * (Only deals with HTML5 here.) * * @param array $defaults Existing defaults. * * @return array Amended defaults. */ function prefix_comment_list_args( array $defaults ) { $defaults['callback'] = 'prefix_html5_comment_callback'; return $defaults; }
WordPress Engineer, and key contributor the Genesis Framework | @GaryJ
August 27, 2013 at 5:40 am #59030Lord_Devi
ParticipantAha ok! Yeah I thought that was what needed to be done!
I was actually just trying really hard to parse lib/structure/comments.php when I got a ping that this thread was updated. =) I admit I was having a difficult time finding exactly what part needed the replacing.
But I've been trying to go through Nick The Geek's Genesis Explained series to get a better grasp of these things, and it DID seem to me that what I needed to do was copy a function directly, an action anyway.. and then add it to my own custom function list (renaming it), and then manually changing what was there.
Trying to find my way around all this code is confusing though, I suspect it may take a bit to get right. At least I have years of Linux BASH scripting under my belt to help with the programmatic side of things!
Anyway, thank you very much for clearing up for me the
genesis_comment_form_args()
and such as well. I understand that way better now.A question though. Did you know to use the
html5_comment_callback
action just out of experience... or do you have a resource one can use to help find these actions..? -- I'm happy I was on the right track. It means I'm actually picking this up! But I am dismayed a bit at just how difficult of a time I am having finding the components I need to modify. (At least I know about the structure of lib/structure now!).And one last question if I may:
Taking an ENTIRE function, the whole action like this, and then making my own version of it.. and then creating a custom function using the entire (sometimes hefty) block of original code as the starting point
If I need to create modifications like this, that is: Taking an ENTIRE function (sometimes hefty in size), create my own custom function using the ENTIRE original function as a template, and the applying my own (perhaps 1 line at times) tweak to the entire function... am I doing it the best way?
It seems to me, if Genesis comes out with major updates or anything, I may end up having to redo this function. Or other things I can't think of. I mean, it just seems like an awfully lot of code I'm copying for just one minor change.
Thanks again for walking me through some of these little points I was missing from the available documentation again! It's helping me a ton, that's for sure!
I hope you don't mind some of the extra questions I've asked either. I've just learned from experience that it's a good idea to try and avoid NOT learning best-practice approaches the first time around. There may be many ways to skin a cat, but a lot of the time, only a few ways are correct.
P.S.: Thanks to you Garyl, my comment form's extra fields are working and exactly where I want them. My rating stars are right where I need them.. Everything is well. And I now have a much better idea about not only how to work with genesis filters and actions, and I also know enough to reliably get stuff done with all the fun API's out there I've been forced to gloss over in the past from lack of knowledge.
Thanks a ton Garyl!
August 27, 2013 at 5:48 pm #59134Gary Jones
MemberI have years of Linux BASH scripting under my belt
Maybe you could suggest how I could improve https://github.com/GaryJones/wordpress-plugin-git-flow-svn-deploy then 😉
Did you know...
I'm one of the (key) contributors for Genesis, and I've probably spent more time looking at and working on the code within Genesis than anyone else. I've got a pretty good grasp with how it all fits together 🙂 In terms of changes between 1.9 and 2.0, I literally wrote the book on it (see my signature!).
There's no canonical reference for actions and filters within Genesis, but I'm co-authoring a pair of ebooks that should do exactly that. In the meantime, search for Genesis Visual Hook Guiide (the site and the plugin) to get a better idea of what's available.
Taking an ENTIRE function...
Ideally, Genesis would have an action hook at exactly the place you want it, but it doesn't so cloning a function and tweaking it is the next best thing (in fact, it's the only solution available). In this particular case, it doesn't matter if Genesis 2.1 amends the original function in some way - your site won't break, and you'll continue to use your custom callback for displaying each comment. You can then, in your own time, update your theme to include any amendments that Genesis introduces, if you wish.
P.s. It's GaryJ, not GaryI 🙂
WordPress Engineer, and key contributor the Genesis Framework | @GaryJ
August 27, 2013 at 8:26 pm #59151Lord_Devi
ParticipantHaha... Yeah.. Well BASH scripting is a bit of old obsession. I'm a bit of a control freak. =) (Or power user if you prefer. 😉
Used to spend days working on little scripts just to help automatically encode video files, organizing images.. all sorts of silly little tasks. I've learnt something about that though... There is ALWAYS a way to improve a script =)
Anyway, just taking a quick look at your svn => wp plugin installer, looks pretty clean to me! You certainly code in an easy to understand manner, I love that.
The only comment I may have is that you allow the user to enter in custom paths and options to the script, but then do not verify them afterwards.
Does the directory they enter for the SVN path actually exist? That kinda thing.
Oh and one more item I guess is that removing the trailing slash from a user entered variable is actually pretty simple as well.
Just changing:
SVNPATH="${input:-$default_svnpath}"
to
SVNPATH="${input%/:-$default_svnpath}"
Should do it. (See Here and Here.)
Anyway yeah, I would enjoy reading those books of yours when they come out. Is there a place I can subscribe or anything to receive any updates in that regard?
And thanks again for the help! Good to know about the function cloning system. This is still way easier than what I am used to. (Used to use Joomla 😛 )
Updating the custom clone later on isn't so bad really. At least it's an easy to maintain and manage system. Especially when combined with Dynamik Website Builder. I love that particular marriage SO much!! Finally makes me feel in control of my websites.
Anyway, I don't suppose you might know of any good sites or documentation sources on learning Genesis fundamentals better? A little extra reading material perhaps...
I've looked around and I find a decent amount of snippets, everyone has a list of hooks.. But I am surprised at how difficult it is for me to find good documentation on Genesis. The closest I've found so far is by "Nick The Geek". A series titled "Genesis Explained" (Found here.)
But honestly, and no offense to nick at all for trying so hard, but I find his material very difficult to understand. =/
Thanks again GaryJ! =)
-
AuthorPosts
- The forum ‘General Discussion’ is closed to new topics and replies.