Completed
Push — master ( dea818...0141d3 )
by Mathieu
08:35
created

AbstractDocument::setFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Charcoal\Cms;
4
5
// Module `charcoal-base` dependencies
6
use \Charcoal\Object\Content;
7
use \Charcoal\Object\CategorizableInterface;
8
use \Charcoal\Object\CategorizableTrait;
9
10
// Module `charcoal-translation` dependencies
11
use \Charcoal\Translation\TranslationString;
12
13
// Intra-module `charcoal-cms` depdencies
14
use \Charcoal\Cms\DocumentInterface;
15
16
/**
17
 * Base document class.
18
 */
19
abstract class AbstractDocument extends Content implements
20
    CategorizableInterface,
21
    DocumentInterface
22
{
23
    use CategorizableTrait;
24
25
    /**
26
     * @var TranslationString $name
27
     */
28
    private $name;
29
30
    /**
31
     * @var string $file
32
     */
33
    private $file;
34
35
    /**
36
     * @var string $basePath
37
     */
38
    private $basePath;
39
40
    /**
41
     * @var string $baseUrl
42
     */
43
    private $baseUrl;
44
45
    /**
46
     * @param mixed $name The document name.
47
     * @return DocumentInterface Chainable
48
     */
49
    public function setName($name)
50
    {
51
        $this->name = new TranslationString($name);
52
        return $this;
53
    }
54
55
    /**
56
     * @return TranslationString
57
     */
58
    public function name()
59
    {
60
        return $this->name;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->name; (Charcoal\Translation\TranslationString) is incompatible with the return type declared by the interface Charcoal\Cms\DocumentInterface::name of type Charcoal\Cms\TranslationString.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
61
    }
62
63
    /**
64
     * @param string $file The file relative path / url.
65
     * @return DocumentInterface Chainable
66
     */
67
    public function setFile($file)
68
    {
69
        $this->file = $file;
70
        return $this;
71
    }
72
73
    /**
74
     * @return string
75
     */
76
    public function file()
77
    {
78
        return $this->file;
79
    }
80
81
    /**
82
     * @param string $path The document base path.
83
     * @return DocumentInterface Chainable
84
     */
85
    public function setBasePath($path)
86
    {
87
        $this->basePath = $path;
88
        return $this;
89
    }
90
91
    /**
92
     * Get the base path, with a trailing slash.
93
     *
94
     * @return string
95
     */
96
    public function basePath()
97
    {
98
        if (!$this->basePath) {
99
            $p = $this->property('file');
0 ignored issues
show
Unused Code introduced by
$p is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
100
            return '';
101
        }
102
        return rtrim($this->basePath, '/').'/';
103
    }
104
105
    /**
106
     * @param string $url The document base URL.
107
     * @return DocumentInterface Chainable
108
     */
109
    public function setBaseUrl($url)
110
    {
111
        $this->baseUrl = $url;
112
        return $this;
113
    }
114
115
    /**
116
     * Get the base url, with a trailing slash.
117
     *
118
     * @return string
119
     */
120
    public function baseUrl()
121
    {
122
        return rtrim($this->baseUrl, '/').'/';
123
    }
124
125
    /**
126
     * @return string
127
     */
128
    public function path()
129
    {
130
        return $this->basePath().$this->file();
131
    }
132
133
    /**
134
     * @return string
135
     */
136
    public function url()
137
    {
138
        return $this->baseUrl().$this->file();
139
    }
140
141
    /**
142
     * @return string
143
     */
144
    public function mimetype()
145
    {
146
        $p = $this->property('file');
147
        return $p->mimetype($this->file());
148
    }
149
150
    /**
151
     * Get the fiqlename (basename; without any path segment).
152
     *
153
     * @return string
154
     */
155
    public function filename()
156
    {
157
        return basename($this->file());
158
    }
159
160
    /**
161
     * Get the document's file size, in bytes.
162
     *
163
     * @return integer
164
     */
165
    public function filesize()
166
    {
167
        return filesize($this->path());
168
    }
169
}
170