Dynamically grab latest post OctoberCMS Blog plugin - php

I asked this question in the October forums but 12 hours later the post still says "unapproved" and I don't believe it's visible. Here's a copy-paste:
What I want to do is grab the latest blog post and display it on the homepage of the website. I can do it currently with my own post partial and the posts variable injected by the blogPosts component like so:
[blogPosts]
pageNumber = "{{ :page }}"
postsPerPage = 10
noPostsMessage = "No posts found"
sortOrder = "published_at desc"
categoryPage = "blog/category"
postPage = "blog/post"
==
{% partial 'site/blogpost' post=posts|last %}
However, I'd like to do this with the default blogpost component that comes with the plugin, but the only way to pass the post to the component seems to be by using the slug in the url, which doesn't really work for the homepage. How can I achieve this?

It is possible to use blogPost component but fetching last post slug and pass to it seems not good practice
what you do is you can use [blogPosts] component and set proper setting there to get latest/last blog
to make it possible
Posts per page : 1 [ as we need only last latest post ]
Post Order : Published(desc) [ you can change as you need ]
now just use proper markup to render it use default or just override to customise it.
Note : It will return list of post but in list there will be only 1 post as demanded so for custom markup just take care of that.
if any doubt please comment.

So, as with most things when it comes to development... RTFM.
All the info I needed was in the Components section of the October CMS docs, and of course I was only looking in the plugin docs. What I ended up doing was overriding the default component partial with my own and then passing the slug to the component. My original reason for wanting to use the default partial was that my custom partial wasn't rendering images, but the default would. I just needed to steal the line <p>{{ post.content_html|raw }}</p> to get that to work.
[blogPost]
==
...
{% component 'blogPost' slug=posts|last.slug %}
Additional info: With the above solution your template pulls all blog posts in the database, which means if you have a lot of posts this could (and most likely will) affect performance. Turns out October templates have a PHP section. The proper thing to do is to remove the blogPosts component and grab the latest post Model like so:
[blogPost]
==
<?
use RainLab\Blog\Models\Post;
function onStart()
{
$this['latestPost'] = Post::latest()->first();
}
?>
==
{% component 'blogPost' slug=latestPost.slug %}
Note: The blogPost component injects a post variable which will override a post variable defined in the PHP section. This is way the variable is labeled latestPost.

Related

How to replicate a shortcode inside template

In wordpress functions.php file I have a shortcode that allows me to display the order ID when I'm on the view-order.php page. The shortcode works fine.
What I am trying to do is find a more comfortable alternative to this. So I would like to take advantage of the Twig template, so I'm doing some testing. I'm actually viewing the order ID, but it stays the same for every order I decide to view.
Example:
if I view the order 001, the ID 001 is shown (correct)
if I view the order 002, the ID 001 is shown (incorrect)
With the shortcode this does not happen, I can correctly display the ID of each order. Can anyone tell me where I'm doing wrong?
I've already done the same thing with my-orders page and my-downloads page, it worked fine, but for some reason it's not working with view-order.php page.
I appreciate any response, thanks.
add_shortcode( 'view_order_id' , 'view_order_00' );
function view_order_00(){
$order_id = absint( get_query_var('view-order') );
$order = new WC_Order( $order_id );
return $order->get_id();
}
{% set post = system.get.order_id|php('get_post') %}
{% set order = post.ID|php('wc_get_order') %}
{% for item in order.get_items %}
{% for download in order.get_downloadable_items %}
<div>{{post.ID}}</div>
{%endfor%}
{% endfor %}
I am using a third party plugin called e-addons, this offers many widgets for elementor, including Twig Template.
I contacted plugin support and they told me that I would have to pass the order ID in $ _GET to fix the problem. Furthermore, all this must be done in a dedicated elementor page and not in the view-order.php template as I was doing initially.
So here is a brief explanation of what I did step by step to fix the problem. I hope it will be useful to anyone who has had the same difficulties as me.
1. I created a new page with elementor titled test page. The
2. I copied the permalink of the newly created page (test-page) and put it in a filter in the functions.php file, here it is below.
// When you click on view order, this filter allows you to redirect from view-order (original woocommerce endpoint) to a custom page created with elementor.
function filter_woocommerce_get_endpoint_url( $url, $endpoint, $value, $permalink ) {
// Specific endpoint: If in the advanced settings of woocommerce you have changed the endpoint view order, then below you have to replace view-order with the one you have chosen in the advanced settings wi WC
if ( $endpoint === 'view-order' ) {
// New URL: change test-page with permalink of the page you created earlier. The /?order_id= part should not be removed.
$url = $permalink . 'test-page/?order_id=' . $value;
}
return $url;
}
add_filter( 'woocommerce_get_endpoint_url', 'filter_woocommerce_get_endpoint_url', 10, 4 );
3. After setting the filter with the permalink we need to modify the new page with elementor. Once in the editor I selected the e-Addons Posts Query widget and dragged it to the page area.
Step 3 opens here, follow these steps to configure the widget correctly, only change what is mentioned below:
Go to the Query Tab of the query posts widget
Query
In query type select Post Type
In options> post type select order
in post status select Any
Query Filter
in "By" select Meta Key
in Mtakey Filters add new and modify as follows
in Post Field custom meta key select _customer_user
in Value Type select Numeric
in Compare operator select "="
in Post Field Value select User Field
If you do everything correctly in step 3, the user will be able to view the orders, otherwise if you do something wrong you get nothing.
Here ends step 3.
4. Then go to the first tab of the widget entitled Content. Here you have to go to the menu item titled Post Items, and this is where I played with the Twig template. So the code I originally posted in my question now works.
{% set post = system.get.order_id|php('get_post') %}
{% set order = post.ID|php('wc_get_order') %}
{% for item in order.get_items %}
{% for download in order.get_downloadable_items %}
<div>{{post.ID}}</div>
{%endfor%}
{% endfor %}
Now, when I am on the order history page and click on view order I am redirected correctly to the specific order page which for example is mywebsite.com/account/test-page?order_id=xxxxxx

Using archive-page instead of single-page improper?

I want to display all my custom post type project images on a template page, such as single-project.php, but the url doesn't display like I want it to.
It should be 'sitename/projects/' but it displays like 'sitename/projects/slug-of-post'.
Is there a way to modify the 'slug-of-post' ?
OR should I be creating an archive-projects instead to achieve that url since it does display 'sitename/project/' ? or is that wrong to use it like that?
If you want to display the images on a page through using a page template you will be able to choose the page slug as you please.
Then what you want is a page template file like this: https://developer.wordpress.org/themes/template-files-section/page-template-files/#creating-custom-page-templates-for-global-use
This will have something like this in the file header:
<?php /* Template Name: Example Template */ ?>
Alternatively, yes, have an archive-projects.php to display an archive (collection of all content) of the post type.
Make sure your custom post type has an archive.
See has_archive in the documentation of register_post_type():
https://developer.wordpress.org/reference/functions/register_post_type/
This can also be changed for already registered post types (eg if a plugin registered the post type)

Export a list of users in OctoberCMS to CSV

I have read tutorial about using the import and export functionality in OctoberCMS.
But with the rainlab-users plugin, these guidelines don't work. I also tried to install the plugin vojtasvoboda-userimportexport, but it exports all users, not filtered ones.
class Users extends \RainLab\User\Controllers\Users
{
public $implement = [
'Backend.Behaviors.FormController',
'Backend.Behaviors.ListController',
'Backend.Behaviors.ImportExportController',
];
....
}
When I added this code into Users.php controller, I got an error:
Class .....\User\Controllers\Users has already been extended with Backend\Behaviors\ImportExportController.
When I try export without code above, I got error:
Call to undefined method October\Rain\Database\QueryBuilder::export()
I think its little difficult as we are not having access to user plugin toolbar to add button so.
But YES we can do it, we need to try little harder :) lets start
End result
To add export button we need to Extend rainlab.user plugin. So from your own plugin you need to it.
1. Adding Extension code to your plugin's Boot method
class Plugin extends PluginBase
{
use \System\Traits\ConfigMaker; // trait to read config
public function boot() {
\RainLab\Users\Controllers\Users::extend(function($controller) {
// we only extend if its not already extended with ImportExport Behavior
if(!$controller->isClassExtendedWith('Backend.Behaviors.ImportExportController')) {
$controller->implement[] = 'Backend.Behaviors.ImportExportController';
// make sure you replace this path to your plugin directory
$extensionPath = '$/hardiksatasiya/stackdemo/user_extension_files/';
$controller->addDynamicProperty(
'importExportConfig',
$extensionPath . 'config_import_export.yaml'
);
$newListConfig = $this->makeConfig(
'$/rainlab/user/controllers/users/config_list.yaml'
);
$newListConfig->toolbar['buttons'] =
$extensionPath . '_new_list_toolbar.htm';
$controller->listConfig = $newListConfig;
}
});
}
....
2. Creating folder and files
Create folder inside your plugin's root directory and name it user_extension_files
Inside that directory
Add config_import_export.yaml with content
export:
useList: true
Add _new_list_toolbar.htm with content [ It will be just copy of plugins/rainlab/user/controllers/users/_list_toolbar.htm with slight modification]
With adding Our Brand New Shiny Export button not pasting whole code it will be too long so just pasting fragment of it.
<div data-control="toolbar">
... copied code ...
<!-- our export button -->
<a
href="<?= Backend::url('rainlab/user/users/export') ?>"
class="btn btn-primary oc-icon-sign-out">
Export
</a>
</div>
Now, when you click on export button it should export records and It will also
respect all the applied filters.
#NOTE: we are copying code to _new_list_toolbar.htm, So in future if user plugin is getting updated and they decide to add new buttons in tool-bar then we are not able to have that changes. So in that time we just need to copy & paste code from plugins/rainlab/user/controllers/users/_list_toolbar.htm to our file _new_list_toolbar.htm again. We are back in business again :) .
if any doubts please comment.
So I actually solved something like this in a different way than in the controller. I make make a decoupled front end admin system. So website owners never have to log into the backend. Which trust me has saved numerous headaches and mistakes by users that mess with things they shouldn't. So here is how I have solved this:
Install plugin Content Type by Sozonov Alexey
Make a CMS Page and make sure it has .csv at the end of the url. You
should see that the content type plugin added a content type tab in
the page settings. You can leave the html selection alone but add
text/csv as your own to the right of it.
Here is an example on how the template of the page looks like.
{% spaceless %}
NAME,EMAIL
{% for row in csv %}
{{ row.name }},{{ row.email }}
{% endfor %}
{% endspaceless %}
Here is how the CMS Page PHP Code section would look. This can allow you to do queries on the list and filter as desired. You could then check to see if the client is logged into the backend or is logged in as a user and maybe is an admin or moderator. Of course you can make a plugin and component then attach it to this page.
use Rainlab\User\Models\User;
function onStart() {
$users = User::all();
$this['csv'] = $users;
}
Side note I have used this same technique to create dynamic css, javascript, or rss feeds. I make the site map using this as well.

Passing a field name from CFS wordpress plugin through to twig

so I'm very new to PHP and I'm having a little trouble passing a field name through.
I am using custom fields (cfs) and writing in twig for php.
Currently, I just have in my page.twig. The idea being, if an image has been set in Wordpress, the image will display in location set in page.twig.
The field name is header_image
{%if header_image %}
{{header_image}}
{% endif %}
When using Timber you can easily pass variables from your PHP controller through to your twig view. There are 2 ways to do this:
1) In functions.php you can pass variables globally to the context. The Timber Starter theme has this in it for reference. Your add_to_content function, should look like:
function add_to_context( $context ) {
global $cfs;
$context['header_image'] = $cfs->get('header_image');
Think of $context as a giant variable that passes through your variables into that actual view.
Remember: this makes your variables globally accessible, so you will need to name your CFS id's uniquely. For example global_phone_number.
2) To better structure your code, you should pass through your variables to the context, via the controller for that page. This helps ensure that you don't pass around variables that aren't being used.
In your page.twig file, you will need to add:
$context['header_image'] = $cfs->get('header_image');
Remember: the $context name is what you use in your twig file, and $cfs name is what you called it in Custom Field Suite.
Lastly:
The {% if header_image %} is good, as this will check whether a variable has been set, and then decided whether to show this block.
However, in CFS, when an image is uploaded, it gives you the option to select File URL or Attachment ID. This means you will need to handle this result in your twig file.
For example, by choosing File URL, you will need to output the {{header_image}} as:
<img src="{{header_image}}" />
You may also then want to add in the alt attribute based on the images alt text set in Wordpress media library.

How to use PHP in the header of a drupal view?

I have a drupal view, which displays a content type filtered by a url argmuent (e.g. category). Now i'd like to add a link in top of my view, which allows my users to add a new node. In the add form the argument field should be prepopulated with the value from the filter.
I think to archive this, i have to install the prepopulate module and add some php-code to the header section of my view, which generates the link.
Any suggestions how to manage this?
If you are wanting to add php code to get the arguments passed to views in the views header section, do the following:
Make sure that the PHP filter is turned on; this is a module that can be enabled
In the header section use the following code:
$view = views_get_current_view();
// [0] is first arg, [1] is second etc.
$argumentOutput = $view-> args[0];
Remember to have the input format set to PHP code. This will get you the argument passed to views.
It would be a lot easier to override the template for the view and insert the code/markup there. Check out the Theming infomation inside the view to find out what to call your template.

Categories