Completed
Push — taxonomies ( 2adc93...017915 )
by Arnaud
07:56
created

TaxonomiesCreate::collectTermsFromPages()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.7537
c 0
b 0
f 0
cc 6
nc 7
nop 0
1
<?php
2
/*
3
 * Copyright (c) Arnaud Ligny <[email protected]>
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Cecil\Step;
10
11
use Cecil\Collection\Page\Page;
12
use Cecil\Collection\Taxonomy\Collection as VocabulariesCollection;
13
use Cecil\Collection\Taxonomy\Term as Term;
14
use Cecil\Collection\Taxonomy\Vocabulary as Vocabulary;
15
use Cecil\Exception\Exception;
16
17
/**
18
 * Create taxonomies collection.
19
 */
20
class TaxonomiesCreate extends AbstractStep
21
{
22
    /**
23
     * @var VocabulariesCollection
24
     */
25
    protected $vocabulariesCollection;
26
27
    /**
28
     * {@inheritdoc}
29
     */
30
    public function process()
31
    {
32
        if ($this->config->get('site.taxonomies')) {
33
            $this->createVocabulariesCollection();
34
            $this->collectTermsFromPages();
35
        }
36
37
        $this->builder->setTaxonomies($this->vocabulariesCollection);
38
39
        // DEBUG
40
        /*foreach ($this->builder->getTaxonomies() as $key => $value) {
41
            echo "$value:\n";
42
            foreach ($value as $k => $v) {
43
                echo "  - $v\n";
44
            }
45
        }*/
46
    }
47
48
    /**
49
     * Create a collection from the vocabularies configuration.
50
     */
51
    protected function createVocabulariesCollection()
52
    {
53
        // create an empty a vocabularies collection
54
        $this->vocabulariesCollection = new VocabulariesCollection('taxonomies');
55
        /*
56
         * Adds each vocabulary to the collection.
57
         * ie:
58
         *   taxonomies:
59
         *     - tags: tag
60
         *     - categories: category
61
         */
62
        foreach (array_keys($this->config->get('site.taxonomies')) as $vocabulary) {
63
            /*
64
             * Disabled vocabulary?
65
             * ie:
66
             *   taxonomies:
67
             *     tags: disabled
68
             */
69
            if ($this->config->get("site.taxonomies.$vocabulary") == 'disabled') {
70
                continue;
71
            }
72
73
            $this->vocabulariesCollection->add(new Vocabulary($vocabulary));
74
        }
75
    }
76
77
    /**
78
     * Collects vocabularies/terms from pages frontmatter.
79
     */
80
    protected function collectTermsFromPages()
81
    {
82
        /* @var $page Page */
83
        $pages = $this->builder->getPages()->sortByDate();
84
        foreach ($pages as $page) {
85
            // ie: tags
86
            foreach ($this->vocabulariesCollection as $vocabulary) {
87
                $plural = $vocabulary->getId();
88
                /*
89
                 * ie:
90
                 *   tags: Tag 1, Tag 2
91
                 */
92
                if ($page->hasVariable($plural)) {
93
                    // converts a string list to an array
94
                    if (!is_array($page->getVariable($plural))) {
95
                        $page->setVariable($plural, [$page->getVariable($plural)]);
96
                    }
97
                    // adds each term to the vocabulary collection...
98
                    foreach ($page->getVariable($plural) as $termName) {
99
                        $termId = Page::slugify($termName);
100
                        $term = (new Term($termId))->setName($termName);
101
                        $this->vocabulariesCollection
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Cecil\Collection\ItemInterface as the method add() does only exist in the following implementations of said interface: Cecil\Collection\Menu\Menu, Cecil\Collection\Taxonomy\Term, Cecil\Collection\Taxonomy\Vocabulary.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
102
                            ->get($plural)
103
                            ->add($term);
104
                        // ... and adds page to the term collection
105
                        $this->vocabulariesCollection
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Cecil\Collection\ItemInterface as the method get() does only exist in the following implementations of said interface: Cecil\Collection\Menu\Menu, Cecil\Collection\Taxonomy\Term, Cecil\Collection\Taxonomy\Vocabulary.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
106
                            ->get($plural)
107
                            ->get($termId)
108
                            ->add($page);
109
                    }
110
                }
111
            }
112
        }
113
    }
114
}
115