MetaTagCMSFixImageLocations::run()   F
last analyzed

Complexity

Conditions 40
Paths 2304

Size

Total Lines 159
Code Lines 113

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 159
rs 2
c 0
b 0
f 0
cc 40
eloc 113
nc 2304
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
class MetaTagCMSFixImageLocations extends BuildTask
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
4
{
5
    public static function my_link()
6
    {
7
        return "/dev/tasks/MetaTagCMSFixImageLocations/";
8
    }
9
10
    protected $title = "Fix File Locations";
11
12
    protected $description = "This method is useful when most of your files end up in the 'Upload' folder.  This task will put all the HAS_ONE and HAS_MANY files into the following folders {CLASSNAME}_{FIELDNAME}.  You can run this task safely, as it will only execute with a special GET parameter (i.e. it defaults to run in test-mode only).";
13
14
    /**
15
     * Names of folders to ignore
16
     * @var Array
17
     */
18
    private static $folders_to_ignore = array();
0 ignored issues
show
Unused Code introduced by
The property $folders_to_ignore is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
19
20
    /**
21
     * automatically includes any child folders
22
     * @var array
23
     */
24
    private $listOfIgnoreFoldersArray = array();
25
26
    /**
27
     * is this task running 'for real' or as test only?
28
     * @var Boolean
29
     */
30
    private $forReal = false;
31
32
    /**
33
     * do one attachment type for real?
34
     * @var Boolean
35
     */
36
    private $doOne = false;
37
38
    /**
39
     * clean up folder?
40
     * This deletes the empty folders
41
     * @var Boolean
42
     */
43
    private $cleanupFolder = 0;
44
45
    /**
46
     * only show the summary OR the full details
47
     * summaries only is not available for non-test tasks
48
     * @var Boolean
49
     */
50
    private $summaryOnly = false;
51
52
    public function run($request)
0 ignored issues
show
Coding Style introduced by
run uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
53
    {
54
        if (isset($_GET["forreal"])) {
55
            $this->forReal = $_GET["forreal"];
56
        }
57
        if (isset($_GET["summaryonly"])) {
58
            $this->summaryOnly = $_GET["summaryonly"];
59
            DB::alteration_message("Prefer <a href=\"".$this->linkWithGetParameter("all", 1)."\">all details</a>?<hr />", "repaired");
60
        }
61
        if (isset($_GET["doone"])) {
62
            $this->forReal = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $forReal was declared of type boolean, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
63
            $this->doOne = urldecode($_GET["doone"]);
0 ignored issues
show
Documentation Bug introduced by
The property $doOne was declared of type boolean, but urldecode($_GET['doone']) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
64
        }
65
        if (isset($_GET["cleanupfolder"])) {
66
            $this->cleanupFolder = intval($_GET["cleanupfolder"]);
0 ignored issues
show
Documentation Bug introduced by
The property $cleanupFolder was declared of type boolean, but intval($_GET['cleanupfolder']) is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
67
        }
68
69
        //work out the folders to ignore...
70
        foreach ($this->Config()->get("folders_to_ignore") as $folderToIgnoreName) {
71
            $folderToIgnore = Folder::find_or_make($folderToIgnoreName);
72
            $this->addListOfIgnoreFoldersArray($folderToIgnore);
0 ignored issues
show
Documentation introduced by
$folderToIgnore is of type null|object<DataObject>, but the function expects a object<Folder>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
73
        }
74
        if (count($this->listOfIgnoreFoldersArray)) {
75
            DB::alteration_message("Files in the following Folders will be ignored: <br />&nbsp; &nbsp; &nbsp; - ".implode("<br />&nbsp; &nbsp; &nbsp; - ", $this->listOfIgnoreFoldersArray)."<hr />", "repaired");
76
        }
77
        if (!$this->cleanupFolder) {
78
            if (!$this->forReal) {
79
                DB::alteration_message("Apply <a href=\"".$this->linkWithGetParameter("forreal", 1)."\">all suggested changes</a>? CAREFUL!<hr />", "deleted");
80
            }
81
            if (!$this->summaryOnly) {
82
                DB::alteration_message("Prefer a <a href=\"".$this->linkWithGetParameter("summaryonly", 1)."\">summary only</a>?<hr />", "repaired");
83
            }
84
            $checks = MetaTagCMSControlFileUse::get()-where("\"ConnectionType\" IN ('HAS_ONE') AND \"IsLiveVersion\" = 0 AND \"DataObjectClassName\" <> 'File'");
85
            if ($checks && $checks->count()) {
0 ignored issues
show
Bug introduced by
The method count cannot be called on $checks (of type integer|double).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
86
                foreach ($checks as $check) {
0 ignored issues
show
Bug introduced by
The expression $checks of type integer|double is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
87
                    $folderName = $check->DataObjectClassName."_".$check->DataObjectFieldName;
88
                    if (!$this->doOne || $this->doOne == $folderName) {
89
                        $objectName = $check->DataObjectClassName;
90
                        $fieldName = $check->DataObjectFieldName."ID";
91
                        $fileClassName = $check->FileClassName;
0 ignored issues
show
Unused Code introduced by
$fileClassName 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...
92
                        $folder = null;
93
                        DB::alteration_message(
94
                            "<hr /><h3>All files attached to $objectName . $fieldName <a href=\"".$this->linkWithGetParameter("doone", $folderName)."\">can be moved to</a> <span style=\"color: green;\">$folderName</span></h3>"
95
                        );
96
                        if ($this->summaryOnly) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
97
                            //do nothing
98
                        } else {
99
                            $objects = null;
100
                            if ($check->FileIsFile) {
101
                                $objects = $objectName::get()->where("\"".$fieldName."\" > 0");
102
                            } elseif ($check->DataObjectIsFile) {
103
                                $objects = $objectName::get()->where("\"".$fieldName."\" > 0");
104
                            }
105
                            if ($objects && $objects->count()) {
106
                                foreach ($objects as $object) {
107
                                    if ($object instanceof File) {
108
                                        $file = $object;//do nothing
109
                                    } else {
110
                                        $file = File::get()->byID($object->$fieldName);
111
                                    }
112
                                    if ($file) {
113
                                        if ($file instanceof Folder) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
114
                                            //do nothing
115
                                        } else {
116
                                            if (!$folder) {
117
                                                $folder = Folder::find_or_make($folderName);
118
                                            }
119
                                            if ($file->ParentID == $folder->ID) {
120
                                                DB::alteration_message(
121
                                                    "OK ... ". $file->FileName,
122
                                                    "created"
123
                                                );
124
                                            } else {
125
                                                if (isset($this->listOfIgnoreFoldersArray[$file->ParentID])) {
126
                                                    DB::alteration_message(
127
                                                        "NOT MOVING (folder to be ignored): <br />/".$file->FileName." to <br />/assets/".$folderName."/".$file->Name."",
128
                                                        "repaired"
129
                                                    );
130
                                                } else {
131
                                                    DB::alteration_message(
132
                                                        "MOVING: <br />/".$file->FileName." to <br />/assets/".$folderName."/".$file->Name."",
133
                                                        "created"
134
                                                    );
135
                                                    if ($this->forReal) {
136
                                                        if ($file->exists()) {
137
                                                            if (file_exists($file->getFullPath())) {
138
                                                                $file->ParentID = $folder->ID;
139
                                                                $file->write();
140
                                                            } else {
141
                                                                DB::alteration_message(
142
                                                                    "ERROR: phyiscal file could not be found: ".$file->getFullPath()." ",
143
                                                                    "deleted"
144
                                                                );
145
                                                            }
146
                                                        } else {
147
                                                            DB::alteration_message(
148
                                                                "ERROR: file not found in database: /".$file->FileName." ",
149
                                                                "deleted"
150
                                                            );
151
                                                        }
152
                                                    }
153
                                                }
154
                                            }
155
                                        }
156
                                    } else {
157
                                        DB::alteration_message(
158
                                            "Could not find file referenced by ".$object->getTitle()." (".$object->class.", ".$object->ID.")",
159
                                            "deleted"
160
                                        );
161
                                    }
162
                                }
163
                            } else {
164
                                DB::alteration_message("No objects in $objectName $fieldName.", "deleted");
165
                            }
166
                        }
167
                    }
168
                }
169
            } else {
170
                DB::alteration_message("Could not find any checks, please run /dev/build/", "deleted");
171
            }
172
        } else {
173
            DB::alteration_message("We are now showing folders only; <a href=\"".$this->linkWithGetParameter("all", 1)."\">view all</a><hr />", "restored");
174
        }
175
        DB::alteration_message("---------------------------------------");
176
        DB::alteration_message("---------------------------------------");
177
        DB::alteration_message("CLEANING FOLDERS");
178
        DB::alteration_message("---------------------------------------");
179
        DB::alteration_message("---------------------------------------");
180
        $folders = Folder::get();
181
        $hasEmptyFolders = false;
182
        if ($folders && $folders->count()) {
183
            foreach ($folders as $folder) {
184
                if (!MetaTagCMSControlFileUse::file_usage_count($folder, true)) {
185
                    $hasEmptyFolders = true;
186
                    if (file_exists($folder->getFullPath())) {
187
                        if (($this->cleanupFolder != $folder->ID) && ($this->cleanupFolder != -1)) {
188
                            DB::alteration_message("found an empty folder: <strong>".$folder->FileName."</strong>; <a href=\"".$this->linkWithGetParameter("cleanupfolder", $folder->ID)."\">delete now</a>?", "restored");
189
                        }
190
                        if (($this->cleanupFolder == $folder->ID) || $this->cleanupFolder == -1) {
191
                            DB::alteration_message("
192
								Deleting empty folder: <strong>".$folder->FileName."</strong>",
193
                                "deleted"
194
                            );
195
                            $folder->delete();
196
                        }
197
                    } else {
198
                        DB::alteration_message("Could not find this phyiscal folder - it is empty can be deleted: ".$folder->getFullPath(), "deleted");
199
                    }
200
                }
201
            }
202
        } else {
203
            DB::alteration_message("Could not find any folders. There might be something wrong!", "deleted");
204
        }
205
        if (!$hasEmptyFolders) {
206
            DB::alteration_message("There are no empty folders!", "created");
207
        } else {
208
            DB::alteration_message("Delete <a href=\"".$this->linkWithGetParameter("cleanupfolder", -1)."\">all empty folders</a>?", "deleted");
209
        }
210
    }
211
212
    private function addListOfIgnoreFoldersArray(Folder $folderToIgnore)
213
    {
214
        $this->listOfIgnoreFoldersArray[$folderToIgnore->ID] = $folderToIgnore->FileName;
0 ignored issues
show
Bug introduced by
The property FileName does not seem to exist. Did you mean Filename?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
215
        $childFolders = Folder::get()->filter(array("ParentID" => $folderToIgnore->ID));
216
        if ($childFolders && $childFolders->count()) {
217
            foreach ($childFolders as $childFolder) {
218
                $this->addListOfIgnoreFoldersArray($childFolder);
219
            }
220
        }
221
    }
222
223
    private function linkWithGetParameter($var, $value)
224
    {
225
        return "/dev/tasks/MetaTagCMSFixImageLocations?$var=".urlencode($value);
226
    }
227
}
228