Completed
Push — master ( 7f0061...a30fc0 )
by Gino
01:53
created

RelatedPosts::getOrderByOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
1
<?php
2
3
namespace GinoPane\BlogTaxonomy\Components;
4
5
use DB;
6
use Cms\Classes\Page;
7
use RainLab\Blog\Models\Post;
8
use Cms\Classes\ComponentBase;
9
use GinoPane\BlogTaxonomy\Plugin;
10
use Illuminate\Database\Eloquent\Collection;
11
12
/**
13
 * Class RelatedPosts
14
 *
15
 * @package GinoPane\BlogTaxonomy\Components
16
 */
17
class RelatedPosts extends ComponentBase
18
{
19
    /**
20
     * @var Collection | array
21
     */
22
    public $posts = [];
23
24
    /**
25
     * Reference to the page name for linking to posts
26
     *
27
     * @var string
28
     */
29
    public $postPage;
30
31
    /**
32
     * Message to display when there are no posts
33
     *
34
     * @var string
35
     */
36
    public $noPostsMessage;
37
38
    /**
39
     * If the post list should be ordered by another attribute
40
     *
41
     * @var string
42
     */
43
    public $orderBy;
44
45
    /**
46
     * Limits the number of records to display
47
     *
48
     * @var int
49
     */
50
    public $limit;
51
52
    /**
53
     * Component Registration
54
     *
55
     * @return  array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
56
     */
57
    public function componentDetails()
58
    {
59
        return [
60
            'name'        => Plugin::LOCALIZATION_KEY . 'components.related_posts.name',
61
            'description' => Plugin::LOCALIZATION_KEY . 'components.related_posts.description'
62
        ];
63
    }
64
65
    /**
66
     * Component Properties
67
     *
68
     * @return  array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,string|false>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
69
     */
70
    public function defineProperties()
71
    {
72
        return [
73
            'slug' => [
74
                'title'             => 'rainlab.blog::lang.settings.post_slug',
75
                'description'       => 'rainlab.blog::lang.settings.post_slug_description',
76
                'default'           => '{{ :slug }}',
77
                'type'              => 'string'
78
            ],
79
80
            'limit' => [
81
                'title'             => Plugin::LOCALIZATION_KEY . 'components.tag_list.limit_title',
82
                'description'       => Plugin::LOCALIZATION_KEY . 'components.tag_list.limit_description',
83
                'type'              => 'string',
84
                'default'           => '0',
85
                'validationPattern' => '^[0-9]+$',
86
                'validationMessage' => Plugin::LOCALIZATION_KEY . 'components.tag_list.validation_message',
87
                'showExternalParam' => false
88
            ],
89
90
            'noPostsMessage' => [
91
                'title'        => 'rainlab.blog::lang.settings.posts_no_posts',
92
                'description'  => 'rainlab.blog::lang.settings.posts_no_posts_description',
93
                'type'         => 'string',
94
                'showExternalParam' => false
95
            ],
96
97
            'orderBy' => [
98
                'title'       => 'rainlab.blog::lang.settings.posts_order',
99
                'description' => 'rainlab.blog::lang.settings.posts_order_description',
100
                'type'        => 'dropdown',
101
                'default'     => 'published_at asc',
102
                'showExternalParam' => false
103
            ],
104
105
            'postPage' => [
106
                'title'       => 'Post page',
107
                'description' => 'Page to show linked posts',
108
                'type'        => 'dropdown',
109
                'default'     => 'blog/post',
110
                'group'       => 'Links',
111
            ],
112
        ];
113
    }
114
115
    /**
116
     * @see PostListAbstract::$postAllowedSortingOptions
117
     *
118
     * @return mixed
119
     */
120
    public function getOrderByOptions()
121
    {
122
        return array_merge(
123
            [
124
                'relevance asc' => Plugin::LOCALIZATION_KEY . 'order_options.relevance_asc',
125
                'relevance desc' => Plugin::LOCALIZATION_KEY . 'order_options.relevance_desc'
126
            ],
127
            PostListAbstract::$postAllowedSortingOptions
128
        );
129
    }
130
131
    protected function prepareVars()
132
    {
133
        $this->noPostsMessage = $this->page['noPostsMessage'] = $this->property('noPostsMessage');
134
        $this->orderBy = $this->page['orderBy'] = $this->property('orderBy');
135
136
        // Page links
137
        $this->postPage = $this->page['postPage' ] = $this->property('postPage');
138
    }
139
140
    public function getPostPageOptions()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
141
    {
142
        return Page::sortBy('baseFileName')->lists('baseFileName', 'baseFileName');
143
    }
144
145
    /**
146
     * Load post and start building query for related posts
147
     */
148
    public function onRun()
149
    {
150
        //Prepare vars
151
        $this->prepareVars();
152
153
        // Load the target post
154
        $post = Post::where('slug', $this->property('slug'))
155
            ->with('tags')
156
            ->first();
157
158
        // Abort if there is no source, or it has no tags
159
        if (!$post || (!$tagIds = $post->tags->lists('id')))
160
            return;
161
162
        // Start building our query for related posts
163
        $query = Post::isPublished()
164
            ->where('id', '<>', $post->id)
165
            ->whereHas('tags', function($tag) use ($tagIds) {
166
                $tag->whereIn('id', $tagIds);
167
            })
168
            ->with('tags');
169
170
        // Sort the related posts
171
        $subQuery = DB::raw('(
172
            select count(*)
173
            from `ginopane_blogtaxonomy_post_tag`
174
            where `ginopane_blogtaxonomy_post_tag`.`post_id` = `rainlab_blog_posts`.`id`
175
            and `ginopane_blogtaxonomy_post_tag`.`tag_id` in ('.implode(', ', $tagIds).')
176
        )');
177
178
        $key = $this->property('orderBy') ?: $subQuery;
179
        $query->orderBy($key, $this->property('direction'));
180
181
        // Limit the number of results
182
        if ($take = intval($this->property('results'))) {
183
            $query->take($take);
184
        }
185
186
        // Execute the query
187
        $posts = $query->get();
188
189
        /*
190
         * Add a "url" helper attribute for linking to each post
191
        */
192
        $posts->each(
193
            function($post)
194
            {
195
                $post->setUrl($this->postPage,$this->controller);
196
            }
197
        );
198
199
        $this->posts = $posts;
200
201
    }
202
}
203