XF 2.0 Building a widget

LPH

Well-known member
This seemed like such an easy side project that has taken up the better part of my day. Sigh.

Here is the code for the widget:

PHP:
namespace TRN\XenLate\XF\Widget;

use XF\Widget\AbstractWidget;

class LatestWordPressPosts extends AbstractWidget
{

   public function render()
   {
      $viewParams = [

      ];

      return $this->renderer('widget_trn_latest_wordpress_posts', $viewParams);
   }
}

The template has been created and tied to the addon.
Code:
<div class="block">
    <div class="block-container">
        <h3 class="block-minorHeader">Title</h3>
        <div class="block-body">
            <div class="block-row">
                Hello
            </div>
        </div>
    </div>
</div>

The board is in debug.
Go to Add Widget >> Pull down and choose the widget name

The following error is received:

Template admin:widget_def_options_trn_xenlate_latest_posts: Template admin:widget_def_options_trn_xenlate_latest_posts is unknown (src/XF/Template/Templater.php:583)

Comment out debug mode and the above error goes away and the widget appears to be saved in the position. However, nothing is showing in the forum list (the chosen position).

Any suggestions on what I'm doing wrong?
 
I haven't worked with widgets in a while, but I think you need to create an admin template for configuring the widget options. If your widget doesn't require any options, you can simply return an empty string in the getOptionsTemplate() method of your widget class and that error should go away. That might be a separate issue from the widget not appearing though, but nothing obvious jumps out at me there.
 
If your widget doesn't require any options, you can simply return an empty string in the getOptionsTemplate() method of your widget class and that error should go away. That might be a separate issue from the widget not appearing though.

^ I agree with this if that is the reason for the error which for me I had a similar error on my first attempt with the widget but added a getOptionsTemplate() method and simply returned it null and the error went away. More so I glanced at the source code for widgets that were already made without options and found the same method in it returning null and just mimicked the other widget which is how I figured it out.
 
  • Like
Reactions: LPH
Thank you both. I've added the getOptionsTempate() and set it to null. I'm now getting the widget showing and the WordPress blog posts showing in the widget. Wahoo!

The CSS needs work and some of the conditionals in the templates need to be updated. For example, if an excerpt is empty then don't try to show an excerpt. Otherwise, it's a matter of deciding if options should be added and I'm not sure how to do that yet.

Additionally, I'm trying to figure out the next steps to package this for others to be able to use. It's meant as a free add-on.
 

Attachments

  • WordPress blog posts.webp
    WordPress blog posts.webp
    12.8 KB · Views: 76
The CSS work is going fine but I'm struggling with how to show the date.

This is in the template.
Code:
<li><xf:date time="{$latestpost.postDate}" /></li>

This is the postDate format
Code:
"postDate" => "2018-07-11 11:43:22"

But all posts are returning December 31, 1969WordPress Latest Blog Post Date Wrong.webp
 
Last edited:
You will turn postDate into unix timestamp.

Fantastic!

The strtotime() worked like a charm!

Update: Drats. It's 7 hours off. Sigh.

Update 2: Turns out if post_date_gmt is pulled instead of post_date then the date and time are correct.
 
Last edited:
This isn't perfect but it's time to move to the next step.

The PHP files are done.
Widget definition is done.
The Templates are built in the style (not the master).

What do I do next to prepare this for others?

And as someone answers or I figure it out from the development manual, maybe I'll add an options page for absolute path to WordPress, number of posts to show, etc.

Cool feature: If no featured image in the WordPress post then the avatar is shown next to the blog post title.
 

Attachments

  • WordPress Blog Posts July 12 Alpha.webp
    WordPress Blog Posts July 12 Alpha.webp
    43.6 KB · Views: 71
Last edited:
Adding options for the number of Blog entries to show was freaking easy! It's been the easiest step so far.

@Chris D or anyone else,

Update: A positive integer setting doesn't work if the default is zero. It'll set but once increased to 1 then cannot decrease back to zero. I've set to integer but then there can be a negative. Any suggestions?
 

Attachments

  • XenLate Options.webp
    XenLate Options.webp
    14.7 KB · Views: 57
Last edited:
The Templates are built in the style (not the master).

What do I do next to prepare this for others?
Depending on what you mean with "in the style", you might have trouble associating your templates to your addon. AFAIR you can only bind your templates to an addon if it's present in the master style.
 
Depending on what you mean with "in the style", you might have trouble associating your templates to your addon. AFAIR you can only bind your templates to an addon if it's present in the master style.

Agreed. Copied the three over to the master and tied them to the addon.

(1) I need to add the option for the absolute path
(2) figure out how to set zero as default and not accept negative integers
(3) figure out how to prepare the addon for others.
 
Update: A positive integer setting doesn't work if the default is zero. It'll set but once increased to 1 then cannot decrease back to zero. I've set to integer but then there can be a negative. Any suggestions?
Take unsigned int with Format parameters min=0.
 
I don't use WP but does esc_url escape the url? If so wouldn't it be better for the XF's template system to escape the url?
 
I don't use WP but does esc_url escape the url? If so wouldn't it be better for the XF's template system to escape the url?

This is a good question. I was just optimizing the code for the array. This is basically the array you are questioning:

PHP:
$LatestPosts[]       = array( 'postTitle'        => \XF::app()->stringFormatter()->wholeWordTrim( $LatestWPPost['post_title'], '55' ),
                              'postAuthor'       => \XF::app()->find('XF:User', $LatestWPPost['post_author'])->username,
                              'postAuthorUser'   => \XF::app()->find('XF:User', $LatestWPPost['post_author']),
                              'postDate'         => strtotime( $LatestWPPost['post_date_gmt'] ),
                              'postUrl'          => esc_url( get_permalink( $LatestWPPost['ID'] ) ),
                              'postExcerpt'      => $LatestWPPost['post_excerpt'],
                              'postThumbnailUrl' => get_the_post_thumbnail_url( $LatestWPPost['ID'], array( 50, 50 ) )
);

Specifically,

PHP:
'postUrl'          => esc_url( get_permalink( $LatestWPPost['ID'] ) ),

Update: Would it be built like this?

PHP:
\XF::escapeString(get_permalink( $LatestWPPost['ID'] ));
 
Last edited:
Top Bottom