DuplicateMembersMerger::merge()   F
last analyzed

Complexity

Conditions 34
Paths > 20000

Size

Total Lines 124
Code Lines 77

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 34
eloc 77
c 1
b 0
f 0
nc 66600
nop 1
dl 0
loc 124
rs 0

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
namespace LeKoala\DevToolkit\Helpers;
4
5
use Exception;
6
use SilverStripe\ORM\DB;
7
use SilverStripe\ORM\DataList;
8
use SilverStripe\Core\ClassInfo;
9
use SilverStripe\ORM\DataObject;
10
use SilverStripe\Security\Member;
11
use SilverStripe\Core\Config\Config;
12
use SilverStripe\Subsites\Model\Subsite;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Subsites\Model\Subsite was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
14
/**
15
 * Merge members
16
 *
17
 * @author Koala
18
 */
19
class DuplicateMembersMerger
20
{
21
22
    /**
23
     * @param DataList $records
24
     * @return void
25
     */
26
    public static function merge($records)
27
    {
28
        $all            = array();
29
        $all_but_oldest = array();
30
        $all_but_latest = array();
31
32
        $latest = null;
33
        $oldest = null;
34
        foreach ($records as $r) {
35
            if (!is_object($r)) {
36
                $r = (object) $r;
37
            }
38
            if (!$r instanceof Member) {
39
                $r = Member::get()->byID($r->ID);
40
            }
41
            if (!$latest) {
42
                $latest = $r;
43
            } else {
44
                if (strtotime($r->LastEdited) > strtotime($latest->LastEdited)) {
45
                    $latest = $r;
46
                }
47
            }
48
            if (!$oldest) {
49
                $oldest = $r;
50
            } else {
51
                if ($r->ID < $oldest->ID) {
52
                    $oldest = $r->ID;
53
                }
54
            }
55
56
            $all[] = $r;
57
        }
58
59
        foreach ($all as $a) {
60
            if ($a->ID == $oldest->ID) {
61
                continue;
62
            }
63
            $all_but_oldest[] = $a;
64
        }
65
66
        foreach ($all as $a) {
67
            if ($a->ID == $latest->ID) {
68
                continue;
69
            }
70
            $all_but_latest[] = $a;
71
        }
72
73
        if (class_exists('Subsite')) {
74
            Subsite::$disable_subsite_filter = true;
75
        }
76
77
        Config::modify()->set(DataObject::class, 'validation_enabled', false);
78
79
        // Rewrite all relations so everything is pointing to oldest
80
        // For some reason, the code in merge fails to do this properly
81
        $tables  = DataObject::getSchema()->getTableNames();
82
        $objects = ClassInfo::subclassesFor('DataObject');
83
        foreach ($objects as $o) {
84
            $config = $o::config();
85
            if ($config->has_one) {
86
                foreach ($config->has_one as $name => $class) {
87
                    if ($class == 'Member') {
88
                        $table = ClassInfo::table_for_object_field(
0 ignored issues
show
Bug introduced by
The method table_for_object_field() does not exist on SilverStripe\Core\ClassInfo. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
                        /** @scrutinizer ignore-call */ 
89
                        $table = ClassInfo::table_for_object_field(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
89
                            $o,
90
                            $name . 'ID'
91
                        );
92
                        if ($table && in_array(strtolower($table), $tables)) {
93
                            foreach ($all_but_oldest as $a) {
94
                                $sql = "UPDATE $table SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID;
95
                                DB::alteration_message($sql);
96
                                DB::query($sql);
97
                            }
98
                        }
99
                    }
100
                }
101
            }
102
            if ($config->has_many) {
103
                foreach ($config->has_many as $name => $class) {
104
                    if ($class == 'Member') {
105
                        $table = ClassInfo::table_for_object_field(
106
                            $o,
107
                            $name . 'ID'
108
                        );
109
                        if ($table && in_array(strtolower($table), $tables)) {
110
                            foreach ($all_but_oldest as $a) {
111
                                $sql = "UPDATE $table SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID;
112
                                DB::alteration_message($sql);
113
                                DB::query($sql);
114
                            }
115
                        }
116
                    }
117
                }
118
            }
119
            if ($config->many_many) {
120
                foreach ($config->many_many as $name => $class) {
121
                    if ($class == 'Member') {
122
                        $table = ClassInfo::table_for_object_field(
123
                            $o,
124
                            $name . 'ID'
125
                        );
126
                        if ($table && in_array(strtolower($table), $tables)) {
127
                            foreach ($all_but_oldest as $a) {
128
                                $sql = "UPDATE $table SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID;
129
                                DB::alteration_message($sql);
130
                                DB::query($sql);
131
                            }
132
                        }
133
                    }
134
                }
135
            }
136
        }
137
138
        // Now, we update to oldest record with the latest info
139
140
        $orgOldest = $oldest;
141
        $oldest->merge($latest, 'right', false);
142
        foreach ($all_but_oldest as $a) {
143
            $a->delete();
144
        }
145
146
        try {
147
            $oldest->write();
148
        } catch (Exception $ex) {
149
            $orgOldest->write();
150
        }
151
    }
152
}
153