CopyFactory::setIgnoreFields()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
4
class CopyFactory extends Object
5
{
6
7
    /**
8
     * saves all the changes to the debug::log file..
9
     * needs to be set manually
10
     * @var Boolean
11
     */
12
    private static $debug = false;
13
14
    /**
15
     * is this a real copy event?
16
     * @var Boolean
17
     */
18
    private static $for_real = false;
19
20
    /**
21
     * the time the copy was started.
22
     * @var Int
23
     */
24
    private static $start_time = 0;
25
26
    /**
27
     * list of classes and their preferred title field
28
     * e.g.
29
     * MyDataObject => "FancyTitle"
30
     *
31
     * @var Array
32
     */
33
    private static $title_map_for_display_of_record_name = array();
34
35
    /**
36
     * The part at the start of the copy field
37
     * e.g. MyDataObject becomes CopyMyDataObject.
38
     *
39
     * @var String
40
     */
41
    private static $copy_fields_prefix = "Copy";
42
43
    /**
44
     * the field where we save the ID of the completed copy
45
     * action should be the same of the field where we saved the original
46
     * dataobject to be copied + an appendix.
47
     * e.g. CopyMyDataObject becomes CopyMyDataObject_Completed.
48
     *
49
     * @var String
50
     */
51
    private static $completed_field_appendix = "_Completed";
52
53
    /**
54
     * holds all the singletons
55
     * @var array
56
     */
57
    private static $singleton_holder = array();
58
59
    /**
60
     * base name for session variables...
61
     * @var String
62
     */
63
    private static $dry_run_for_session_base_name = "CopyFactorySessionVariable";
64
65
    /**
66
     * static variable that holds the details for the current dry run...
67
     * @var string
68
     */
69
    private static $dry_run_for_class_name = "";
70
71
    /**
72
     * static variable that holds the details for the current dry run...
73
     * @var string
74
     */
75
    private static $dry_run_for_id = "";
76
77
    /**
78
     * returns a CopyFactory specific to a Class.
79
     * You must provide an object class name.
80
     *
81
     * @param DataObject $obj
0 ignored issues
show
Bug introduced by
There is no parameter named $obj. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
82
     *
83
     * @return CopyFactory
84
     */
85
    public static function create()
86
    {
87
        //allow up to ten minutes for copy ...
88
        increase_time_limit_to(600);
89
        $args = func_get_args();
90
        if (!$args || count($args) != 1) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $args of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91
            user_error("Please provide an Object for your CopyFactory - like this: CopyFactory::create($myDataObject);");
0 ignored issues
show
Bug introduced by
The variable $myDataObject does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
92
        }
93
        $obj = array_shift($args);
94
        if (!($obj instanceof DataObject)) {
95
            user_error("First argument provided should be a DataObject.");
96
        }
97
        //set basic details if no copy has run thus far ...
98
        if (count(self::$singleton_holder) == 0) {
99
            $startTime = time();
100
            Config::inst()->update("CopyFactory", "dry_run_for_class_name", $obj->ClassName);
101
            Config::inst()->update("CopyFactory", "dry_run_for_id", $obj->ID);
102
            Config::inst()->update("CopyFactory", "start_time", $startTime);
103
            // dry run only...
104 View Code Duplication
            if (SiteConfig::current_site_config()->AllowCopyingOfRecords == 1) {
0 ignored issues
show
Bug introduced by
The property AllowCopyingOfRecords does not seem to exist. Did you mean record?

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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
105
                Config::inst()->update("CopyFactory", "for_real", false);
106
                self::add_to_session("
107
                    ===========================================================
108
                    Starting dry run: ".date("r", $startTime)."
109
                    ===========================================================
110
                    ===========================================================
111
                ");
112
            }
113
            // for real ...
114 View Code Duplication
            if (SiteConfig::current_site_config()->AllowCopyingOfRecords == 2) {
0 ignored issues
show
Bug introduced by
The property AllowCopyingOfRecords does not seem to exist. Did you mean record?

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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
                Config::inst()->update("CopyFactory", "for_real", true);
116
                // we cant do too many writes ... in a live environment
117
                self::add_to_session("
118
                    ===========================================================
119
                    Starting real copy task: ".date("r", $startTime)."
120
                    ===========================================================
121
                    ===========================================================
122
                ");
123
            }
124
        }
125
        if (!isset(self::$singleton_holder[$obj->ClassName])) {
126
            self::$singleton_holder[$obj->ClassName] = new CopyFactory();
127
        }
128
129
        self::$singleton_holder[$obj->ClassName]->myClassName = $obj->ClassName;
130
        self::$singleton_holder[$obj->ClassName]->isForReal = Config::inst()->get("CopyFactory", "for_real") ? true : false;
131
        if (Director::isDev()) {
132
            self::$singleton_holder[$obj->ClassName]->recordSession = true;
133
        } else {
134
            self::$singleton_holder[$obj->ClassName]->recordSession = self::$singleton_holder[$obj->ClassName]->isForReal;
135
        }
136
        return self::$singleton_holder[$obj->ClassName];
137
    }
138
139
140
    /**
141
     * adds additional info to current session
142
     * @param String $action
143
     * @param DataObject $copyFrom
0 ignored issues
show
Documentation introduced by
Should the type for parameter $copyFrom not be DataObject|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
144
     * @param DataObject $copyInto
0 ignored issues
show
Documentation introduced by
Should the type for parameter $copyInto not be DataObject|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
145
     */
146
    protected static function add_to_session($action, $copyFrom = null, $copyInto = null)
147
    {
148
        $obj = new CopyFactoryLog();
149
        $obj->Type = Config::inst()->get("CopyFactory", "for_real") ? "Real" : "Fake";
0 ignored issues
show
Documentation introduced by
The property Type does not exist on object<CopyFactoryLog>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
150
        $obj->StartTime = Config::inst()->get("CopyFactory", "start_time");
0 ignored issues
show
Documentation introduced by
The property StartTime does not exist on object<CopyFactoryLog>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
151
        $obj->CopyCausingClassName = Config::inst()->get("CopyFactory", "dry_run_for_class_name");
0 ignored issues
show
Bug introduced by
The property CopyCausingClassName does not seem to exist. Did you mean ClassName?

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...
152
        $obj->CopyCausingClassNameID = Config::inst()->get("CopyFactory", "dry_run_for_id");
0 ignored issues
show
Bug introduced by
The property CopyCausingClassNameID does not seem to exist. Did you mean ClassName?

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...
153
        if ($copyFrom) {
154
            $obj->CopyFromClassNameID = $copyFrom->ID;
0 ignored issues
show
Bug introduced by
The property CopyFromClassNameID does not seem to exist. Did you mean ClassName?

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...
155
        }
156
        if ($copyInto) {
157
            $obj->CopyIntoClassName = $copyInto->ClassName;
0 ignored issues
show
Bug introduced by
The property CopyIntoClassName does not seem to exist. Did you mean ClassName?

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...
158
            $obj->CopyIntoClassNameID = $copyInto->ID;
0 ignored issues
show
Bug introduced by
The property CopyIntoClassNameID does not seem to exist. Did you mean ClassName?

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...
159
        }
160
        $obj->Action = $action;
0 ignored issues
show
Bug introduced by
The property Action does not seem to exist. Did you mean allowed_actions?

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...
161
        $obj->write();
162
        if (Config::inst()->get("CopyFactory", "debug")) {
163
            $copyFromLine = "";
164 View Code Duplication
            if ($copyFrom && $copyFrom->exists()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165
                $copyFromLine = "FROM: ".self::title_for_object($copyFrom)." - ".$copyFrom->ClassName.".".$copyFrom->ID."\n";
166
            }
167
            $copyIntoLine = "";
168 View Code Duplication
            if ($copyInto && $copyInto->exists()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
                $copyIntoLine = "INTO: ".self::title_for_object($copyInto)." - ".$copyInto->ClassName.".".$copyInto->ID."\n";
170
            }
171
            debug::log(
172
                $copyFromLine.
173
                $copyIntoLine.
174
                $action
175
            );
176
        }
177
    }
178
179
180
    /**
181
     * provides a meaningful title for an object
182
     * @return String ...
183
     */
184 View Code Duplication
    public static function title_for_object($obj)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
    {
186
        $methodOrField = self::preferred_title_field($obj);
187
        if ($obj->hasMethod($methodOrField)) {
188
            return $obj->$methodOrField();
189
        } elseif ($obj->hasMethod("get".$methodOrField)) {
190
            $methodName = "get".$methodOrField;
191
            return $obj->$methodName();
192
        } else {
193
            return $obj->$methodOrField;
194
        }
195
    }
196
197
    /**
198
     * returns the name of a method / db field
199
     * that can be used to describe the object ...
200
     *
201
     * @param DataObject $object
0 ignored issues
show
Bug introduced by
There is no parameter named $object. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
202
     *
203
     * @return String
204
     */
205
    public static function preferred_title_field($obj)
206
    {
207
        $titleMap = Config::inst()->get("CopyFactory", "title_map_for_display_of_record_name");
208
        if (isset($titleMap[$obj->ClassName])) {
209
            return $titleMap[$obj->ClassName];
210
        }
211
        return "Title";
212
    }
213
214
    /**
215
     * are records actually been written ...
216
     *
217
     * @var Boolean
218
     */
219
    protected $isForReal = "";
220
221
    /**
222
     * used for reference only
223
     * saves the class of the current singleton instance
224
     * that initiated the copy
225
     *
226
     * @var String
227
     */
228
    protected $recordSession = "";
229
230
    /**
231
     * used for reference only
232
     * saves the class of the current singleton instance
233
     * that initiated the copy
234
     *
235
     * @var String
236
     */
237
    protected $myClassName = "";
238
239
    /**
240
     * fields that are never copied
241
     * @var array
242
     */
243
    protected $baseIgnoreFields = array(
244
        "Created",
245
        "LastEdited",
246
        "ID"
247
    );
248
249
    /**
250
     * set a list of fields that should always be ignored ...
251
     * we add the base array to it at the same time ...
252
     * @param Array $array
253
     */
254
    public function setIgnoreFields($array)
255
    {
256
        $this->ignoreFields = array_merge($this->baseIgnoreFields, $array);
0 ignored issues
show
Bug introduced by
The property ignoreFields does not seem to exist. Did you mean baseIgnoreFields?

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...
257
    }
258
259
    /**
260
     * add one field to ignore
261
     * @param String $fieldName
262
     */
263
    public function addIgnoreField($fieldName)
264
    {
265
        $this->ignoreFields[] = $fieldName;
0 ignored issues
show
Bug introduced by
The property ignoreFields does not seem to exist. Did you mean baseIgnoreFields?

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...
266
    }
267
268
    /**
269
     *
270
     * @param Boolean $b
271
     *
272
     * @return CopyFactory
273
     */
274
    public function setIsForReal($b)
275
    {
276
        return $this->isForReal = $b;
277
        return $this;
0 ignored issues
show
Unused Code introduced by
return $this; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
278
    }
279
280
    /**
281
     *
282
     * @return Boolean
283
     */
284
    public function getIsForReal()
285
    {
286
        return $this->isForReal;
287
    }
288
289
    /**
290
     *
291
     * @return String
292
     */
293
    protected function getCopyFactorySessionName()
294
    {
295
        return
296
            $this->Config()->get("dry_run_for_session_base_name")
297
            ."_".
298
            $this->Config()->get("dry_run_for_class_name")
299
            ."_".
300
            $this->Config()->get("dry_run_for_id");
301
    }
302
303
304
305
    /*****************************************************
306
     *  COPYING METHODS
307
     *****************************************************/
308
309
    /**
310
     * Copy one object into another including has-one fields
311
     *
312
     * @param DataObject $copyFrom
313
     * @param DataObject $newObject
314
     * @param Boolean $overwriteValues - overwrite values that exist
315
     *
316
     * @return CopyFactory
317
     */
318
    public function copyObject($copyFrom, $newObject, $overwriteValues = true)
319
    {
320
321
        //get ignore fields
322
        if ($newObject->hasMethod("getIgnoreInCopyFields")) {
323
            $this->setIgnoreFields($newObject->getIgnoreInCopyFields());
324
        } elseif ($array = Config::inst()->get($newObject->ClassName, "ignore_in_copy_fields")) {
325
            if (is_array($array) && count($array)) {
326
                $this->setIgnoreFields($array);
327
            }
328
        }
329
330
        //get copy field
331
        $this->addIgnoreField($newObject->CopyFromFieldName($withID = true));
332
        $this->addIgnoreField($newObject->CopiedFromFieldName($withID = true));
333
334
        //get copy-able fields
335
        $dbFields = Config::inst()->get($copyFrom->ClassName, "db");
336
        $hasOneFields = Config::inst()->get($copyFrom->ClassName, "has_one");
337
338
        //has-one fields fixup
339
        foreach ($hasOneFields as $key => $field) {
0 ignored issues
show
Bug introduced by
The expression $hasOneFields of type array|integer|double|string|boolean 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...
340
            $hasOneFields[$key."ID"] = $field;
341
            unset($hasOneFields[$key]);
342
        }
343
        $fields = $dbFields + $hasOneFields;
344
        //remove ignore fields ...
345
        foreach ($this->ignoreFields as $ignoreField) {
0 ignored issues
show
Bug introduced by
The property ignoreFields does not seem to exist. Did you mean baseIgnoreFields?

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...
346
            unset($fields[$ignoreField]);
347
        }
348
        //flip
349
        $fields = array_keys($fields);
350
        if ($this->recordSession) {
351
            self::add_to_session(
352
                "
353
                    ====================================
354
                    *** COPYING INTO
355
                    ".($this->myClassName != $copyFrom->ClassName ? "ERROR: ClassName mismatch: ".$this->myClassName." != ".$copyFrom->ClassName : "")."
356
                    Values will ".($overwriteValues ? "" : "NOT")." be overridden.
357
                    DB Fields: ".implode(", ", array_keys($dbFields))."
358
                    HAS ONE Fields: ".implode(", ", array_keys($hasOneFields))."
359
                    IGNORE Fields: ".implode(", ", $this->ignoreFields)."
0 ignored issues
show
Bug introduced by
The property ignoreFields does not seem to exist. Did you mean baseIgnoreFields?

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...
360
                    FINAL Fields: ".implode(", ", $fields)."
361
                    ====================================
362
                ",
363
                $copyFrom,
364
                $newObject
365
            );
366
        }
367
        if ($this->recordSession) {
368
            $copySessionRecording = "";
369
        }
370
        foreach ($fields as $field) {
371
            if (!$newObject->$field || $overwriteValues) {
372
                $value = $copyFrom->$field;
373
                if (is_object($value)) {
374
                    $value = $value->raw();
375
                }
376
                if ($this->recordSession) {
377
                    $copySessionRecording .= "\r\nSetting '$field' to '$value'";
0 ignored issues
show
Bug introduced by
The variable $copySessionRecording does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
378
                }
379
                if ($this->isForReal) {
380
                    $newObject->$field = $value;
381
                }
382
            }
383
        }
384
        $copyField = $newObject->CopyFromFieldName($withID = true);
385
        $copyFieldCompleted = $newObject->CopiedFromFieldName($withID = true);
386
        //important - reset, so that it does not get into a loop.
387
        if ($this->recordSession) {
388
            self::add_to_session(
389
                "
390
                $copySessionRecording
391
                setting '$copyField' to zero
392
                setting '$copyFieldCompleted' to '".$copyFrom->ID."'",
393
                $copyFrom,
394
                $newObject
395
            );
396
        }
397
        if ($this->isForReal) {
398
            $newObject->$copyFieldCompleted = $copyFrom->ID;
399
            if ($newObject->exists()) {
400
                $newObject->$copyField = 0;
401
            }
402
            $newObject->write();
403
        }
404
        //now we do all the other methods ...
405
        if ($newObject->hasMethod("doCopyFactory")) {
406
            if ($this->recordSession) {
407
                self::add_to_session("Now calling doCopyFactory ... ", $copyFrom, $newObject);
408
            }
409
            $newObject->doCopyFactory($this, $copyFrom);
410
        }
411
        return $this;
412
    }
413
414
    /**
415
     * From a copied object, copy the has-one of the copyFrom Object to the newObject.
416
     * Old and new copy point to the same has-one record.
417
     *
418
     * @param DataObject $copyFromParent
419
     * @param DataObject $newObjectParent
420
     * @param String $relationalFieldForChildWithoutID - e.g. MyImage
421
     *
422
     * @return CopyFactory
423
     */
424
    public function copyOriginalHasOneItem($copyFromParent, $newObjectParent, $relationalFieldForChildWithoutID)
425
    {
426
        if ($this->recordSession) {
427
            self::add_to_session(
428
                "
429
                    ====================================
430
                    COPY ORIGINAL HAS-ONE RELATION: $relationalFieldForChildWithoutID
431
                    Children will link to original record (will not be copied)
432
                    ====================================
433
                ",
434
                $copyFromParent,
435
                $newObjectParent
436
            );
437
        }
438
        $relationalFieldForChildWithID = $relationalFieldForChildWithoutID . "ID";
439
        if ($this->isForReal) {
440
            $newObjectParent->$relationalFieldForChildWithID = $copyFromParent->$relationalFieldForChildWithID;
441
            $newObjectParent->write();
442
        }
443
        return $this;
444
    }
445
446
    /**
447
     * Usage: an object has one child
448
     * and we want to also copy the child and add it to the
449
     * copied into parent ...
450
     *
451
     * @param DataObject $copyFromParent
452
     * @param DataObject $newObjectParent
453
     * @param String $relationalFieldForChildWithoutID -
454
     * @param String $relationalFieldForParentWithoutID - if it is a has_one to has_one relationship only!!!
455
     *    this is the field on the parent that provides
456
     *    its child (the single-child / has one child )WITHOUT the ID part.
457
     *
458
     * @return CopyFactory
459
     */
460
    public function copyHasOneRelation($copyFromParent, $newObjectParent, $relationalFieldForChildWithoutID, $relationalFieldForParentWithoutID = "")
461
    {
462
        if ($this->recordSession) {
463
            self::add_to_session("
464
            ====================================
465
            COPY HAS-ONE RELATION: $relationalFieldForChildWithoutID
466
            ====================================
467
            ", $copyFromParent, $newObjectParent);
468
        }
469
        if ($copyFromChildObject = $copyFromParent->$relationalFieldForChildWithoutID()) {
470
            if ($copyFromChildObject->exists()) {
471
                $className = $copyFromChildObject->ClassName;
472
                // what are we going to do?
473
                if ($this->recordSession) {
474
                    self::add_to_session("Creating a new object '$className' linking to '$relationalFieldForChildWithoutID' in parent.", $copyFromParent, $newObjectParent);
475
                }
476
477
                //create object and set parent ...
478
                $newObjectChildObject = $className::create();
479
                $newObjectChildObject->ClassName = $className;
480
                //does the child also copy ...
481
                //we copy the data here so that we dont run into validation errors
482
                $obj = CopyFactory::create($newObjectChildObject);
483
                $obj->copyObject($copyFromChildObject, $newObjectChildObject);
484
485
                if ($this->isForReal) {
486
                    if ($relationalFieldForParentWithoutID) {
487
                        $relationalFieldForParentWithID = $relationalFieldForParentWithoutID."ID";
488
                        $newObjectChildObject->$relationalFieldForParentWithID = $newObjectParent->ID;
489
                    }
490
                    $newObjectChildObject->write();
491
                    $newObjectChildObject = $className::get()->byID($newObjectChildObject->ID);
492
                    //attach to parent ...
493
                    $relationalFieldForChildWithID = $relationalFieldForChildWithoutID."ID";
494
                    $newObjectParent->$relationalFieldForChildWithID = $newObjectChildObject->ID;
495
                    $newObjectParent->write();
496
                }
497
498
                // setting child again - just in case ...
499
                if ($this->isForReal) {
500
                    $newObjectParent->$relationalFieldForChildWithID = $newObjectChildObject->ID;
0 ignored issues
show
Bug introduced by
The variable $relationalFieldForChildWithID does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
501
                    $newObjectParent->write();
502
                }
503 View Code Duplication
                if ($this->recordSession) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
504
                    if (!$newObjectChildObject) {
505
                        self::add_to_session("ERROR:  did not create object listed above", $copyFromChildObject, $newObjectChildObject);
506
                    } else {
507
                        self::add_to_session("CREATED object", $copyFromChildObject, $newObjectChildObject);
508
                    }
509
                    if ($newObjectParent->$relationalFieldForChildWithID != $newObjectChildObject->ID) {
510
                        self::add_to_session(
511
                            "ERROR: broken link ... '".$newObjectParent->$relationalFieldForChildWithID."' is not equal to '".$newObjectChildObject->ID."'",
512
                            $copyFromChildObject,
513
                            $newObjectChildObject
514
                        );
515
                    //hack fix
516
                    } else {
517
                        self::add_to_session("Saved with correct new parent field ($relationFieldForParentWithID) ID: ".$newObjectChildObject->$relationFieldForParentWithID, $copyFromChildObject, $newObjectChildObject);
0 ignored issues
show
Bug introduced by
The variable $relationFieldForParentWithID does not exist. Did you mean $relationalFieldForParentWithoutID?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
518
                    }
519
                }
520
            }
521
        }
522
        return $this;
523
    }
524
525
    /**
526
     * Usage: Find the copied ("NEW") equivalent of the old has-one relation and attach it to the newObject ...
527
     * @param DataObject $copyFrom
528
     * @param DataObject $newObject
529
     * @param String $hasOneMethod - the fieldname (method) of the has one relations (e.g. MyOtherDataObject)
530
     * @param DataList $dataListToChooseFrom
531
     *
532
     * @return CopyFactory
533
     */
534
    public function attachToMoreRelevantHasOne($copyFrom, $newObject, $hasOneMethod, $dataListToChooseFrom)
535
    {
536
        $fieldNameWithID = $hasOneMethod."ID";
537
        if ($this->recordSession) {
538
            self::add_to_session(
539
                "
540
                    ====================================
541
                    ATTACH TO MORE RELEVANT HAS-ONE
542
                    FIELD $hasOneMethod
543
                    OBJECTS TO CHOOSE FROM: ".$dataListToChooseFrom->sql()."
544
                    ====================================
545
                ",
546
                $copyFrom,
547
                $newObject
548
            );
549
        }
550
        if ($copyFrom->$fieldNameWithID) {
551
            //find out field to choose from
552
            $firstObject = $dataListToChooseFrom->first();
553
            if ($firstObject) {
554
                $dataListToChooseFrom = $dataListToChooseFrom
555
                    ->filter(array($firstObject->CopiedFromFieldName($withID = true) => $copyFrom->$fieldNameWithID))
556
                    ->Sort("Created DESC");
557
                $count = $dataListToChooseFrom->count();
558
                if ($count == 1 && $newAttachment = $dataListToChooseFrom->First()) {
559
                    if ($this->recordSession) {
560
                        self::add_to_session("Found Matching record.", $copyFrom, $newObject);
561
                    }
562
                    if ($this->isForReal) {
563
                        $newObject->$fieldNameWithID = $newAttachment->ID;
564
                        $newObject->write();
565
                    }
566
                } else {
567
                    if ($this->recordSession) {
568
                        if ($count > 1) {
569
                            self::add_to_session("ERROR: found too many Matching records.", $copyFrom, $newObject);
570
                        } elseif ($count == 0) {
571
                            self::add_to_session("ERROR: Could not find any Matching records.", $copyFrom, $newObject);
572
                        } else {
573
                            self::add_to_session("ERROR: There was an error retrieving the matching record.", $copyFrom, $newObject);
574
                        }
575
                    }
576
                    if ($this->isForReal) {
577
                        $newObject->$fieldNameWithID = 0;
578
                        $newObject->write();
579
                    }
580
                }
581
            } else {
582
                self::add_to_session("ERROR: Could not find any Matching records from base DataList.", $copyFrom, $newObject);
583
                $newObject->$fieldNameWithID = 0;
584
                $newObject->write();
585
            }
586
        } else {
587
            if ($this->recordSession) {
588
                self::add_to_session("copyFrom object does not have a value for: $fieldNameWithID", $copyFrom, $newObject);
589
            }
590
        }
591
        if ($this->recordSession) {
592
            self::add_to_session("*** END OF attachToMoreRelevantHasOne ***", $copyFrom, $newObject);
593
        }
594
        return $this;
595
    }
596
597
    /**
598
     * Usage: an object has many children but we do NOT copy the children ...
599
     *
600
     * @param DataObject $copyFromParent
601
     * @param DataObject $newObjectParent
602
     * @param String $relationalFieldForChildren - this is the field on the parent that provides the children (e.g. Children or Images) WITHOUT the ID part.
603
     * @param String $relationFieldForParent - this is the field on the children that links them back to the parent.
0 ignored issues
show
Documentation introduced by
There is no parameter named $relationFieldForParent. Did you maybe mean $relationFieldForParentWithoutID?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
604
     *
605
     *  @return CopyFactory
0 ignored issues
show
Documentation introduced by
Should the return type not be CopyFactory|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
606
     */
607
    public function copyOriginalHasManyItems($copyFromParent, $newObjectParent, $relationalFieldForChildren, $relationFieldForParentWithoutID)
0 ignored issues
show
Unused Code introduced by
The parameter $copyFromParent is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $newObjectParent is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $relationalFieldForChildren is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $relationFieldForParentWithoutID is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
608
    {
609
        user_error("This is not possible, because the many-side can't link to two objects (the copyFrom and copyInto part.");
610
    }
611
612
    /**
613
     * Usage: an object has many children
614
     * and we want to also copy the children and add them to the
615
     * copied into parent ...
616
     *
617
     * @param DataObject $copyFromParent
618
     * @param DataObject $newObjectParent
619
     * @param String $relationalFieldForChildren - this is the field on the parent that provides the children (e.g. Children or Images) WITHOUT the ID part.
620
     * @param String $relationFieldForParentWithoutID - this is the field on the children that links them back to the parent.
621
     *
622
     * @return CopyFactory
623
     */
624
    public function copyHasManyRelation($copyFromParent, $newObjectParent, $relationalFieldForChildren, $relationFieldForParentWithoutID)
625
    {
626
        if ($this->recordSession) {
627
            self::add_to_session(
628
                "
629
                ====================================
630
                COPY HAS-MANY RELATION:
631
                CHILDREN METHOD: '$relationalFieldForChildren' and
632
                PARENT METHOD: '$relationFieldForParentWithoutID'
633
                ====================================
634
                ",
635
                $copyFromParent,
636
                $newObjectParent
637
            );
638
        }
639
        foreach ($copyFromParent->$relationalFieldForChildren() as $copyFromChildObject) {
640
            $className = $copyFromChildObject->ClassName;
641
            $relationFieldForParentWithID = $relationFieldForParentWithoutID."ID";
642
            $childCopyField = $copyFromChildObject->CopyFromFieldName($withID = true);
0 ignored issues
show
Unused Code introduced by
$childCopyField 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...
643
            if ($this->recordSession) {
644
                self::add_to_session("Creating a new object '$className'; adding parent field ($relationFieldForParentWithID) ID: ".$newObjectParent->ID, $copyFromParent, $newObjectParent);
645
            }
646
            //create object and set parent ...
647
            $newObjectChildObject = $className::create();
648
            if ($this->isForReal) {
649
                $newObjectChildObject->$relationFieldForParentWithID = $newObjectParent->ID;
650
651
                //does the child also copy ...
652
                //we copy the data here so that we dont run into validation errors
653
                $obj = CopyFactory::create($newObjectChildObject);
654
                $obj->copyObject($copyFromChildObject, $newObjectChildObject);
655
                //we reset the copy field here so that the copy can run another
656
                //time and do the has-many and many-many parts
657
                //$newObjectChildObject->$childCopyField = intval($copyFromChildObject->ID);
658
                //$newObjectChildObject->write();
659
                //retrieve it again to set more details ...
660
                //$newObjectChildObject = $className::get()->byID($newObjectChildObject->ID);
661
662
                // setting parent again - just in case ...
663
                $newObjectChildObject->$relationFieldForParentWithID = $newObjectParent->ID;
664
                $newObjectChildObject->write();
665
            }
666 View Code Duplication
            if ($this->recordSession) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
667
                if (!$newObjectChildObject) {
668
                    self::add_to_session("ERROR: did not create object listed above", $copyFromChildObject, $newObjectChildObject);
669
                } else {
670
                    self::add_to_session("CREATED object", $copyFromChildObject, $newObjectChildObject);
671
                }
672
                if ($newObjectChildObject->$relationFieldForParentWithID != $newObjectParent->ID) {
673
                    self::add_to_session(
674
                        "
675
                        ERROR: broken link ...  '".$newObjectChildObject->$relationFieldForParentWithID."' is not equal to '".$newObjectParent->ID."'",
676
                        $copyFromChildObject,
677
                        $newObjectChildObject
678
                    );
679
                //hack fix
680
                } else {
681
                    self::add_to_session("Saved with correct new parent field ($relationFieldForParentWithID) ID: ".$newObjectChildObject->$relationFieldForParentWithID, $copyFromChildObject, $newObjectChildObject);
682
                }
683
            }
684
        }
685
        if ($this->recordSession) {
686
            self::add_to_session("*** END OF copyHasManyRelation ***", $copyFromParent, $newObjectParent);
687
        }
688
        return $this;
689
    }
690
691
    /**
692
     * Usage: an object has many children, the children have already been copied, but they are not pointing at the new parent object.
693
     *
694
     * @param DataObject $copyFromParent
695
     * @param DataObject $newObjectParent
696
     * @param String $relationalFieldForChildren - this is the field on the parent that provides the children (e.g. Children or Images) WITHOUT the ID part.
697
     * @param String $relationFieldForParentWithoutID - this is the field on the children that links them back to the parent.
698
     * @param DataList $dataListToChooseFrom - selection of children that are best matches ...
699
     *
700
     * @return CopyFactory
701
     */
702
    public function attachToMoreRelevantHasMany($copyFromParent, $newObjectParent, $relationalFieldForChildren, $relationFieldForParentWithoutID, $dataListToChooseFrom)
0 ignored issues
show
Unused Code introduced by
The parameter $copyFromParent is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $newObjectParent is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $relationalFieldForChildren is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $relationFieldForParentWithoutID is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $dataListToChooseFrom is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
703
    {
704
        user_error("The attachToMoreRelevantHasMany method is be completed.");
705
        return $this;
706
    }
707
708
    /**
709
     * copies Many-Many relationship Without copying the items linked to ...
710
     * @param DataObject $copyFrom
711
     * @param DataObject $newObject
712
     * @param String $manyManyMethod
713
     * @param Array $extraFields - e..g Field1, Field2
714
     *
715
     * @return CopyFactory
716
     */
717
    public function copyOriginalManyManyItems($copyFrom, $newObject, $manyManyMethod, $extraFields = array())
718
    {
719 View Code Duplication
        if ($this->recordSession) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
720
            self::add_to_session(
721
                "
722
                ====================================
723
                COPY Original Many Many Items
724
                MANY-MANY METHOD: '$manyManyMethod'
725
                EXTRAFIELDS: '".implode(", ", $extraFields)."'
726
                ====================================
727
                ",
728
                $copyFrom,
729
                $newObject
730
            );
731
        }
732
        //remove current ones on NewObject
733
        if ($this->isForReal) {
734
            $newObject->$manyManyMethod()->removeAll();
735
        }
736
        if ($this->isForReal) {
737
            if (count($extraFields) == 0) {
738
                $ids = $copyFrom->$manyManyMethod()->Column("ID");
739
                if ($this->recordSession) {
740
                    self::add_to_session("copying ".count($ids)." items into $manyManyMethod.", $copyFrom, $newObject);
741
                }
742
                $newObject->$manyManyMethod()->addMany($ids);
743
            } else {
744
                $count = 0;
745
                foreach ($copyFrom->$manyManyMethod() as $itemToAdd) {
746
                    $count++;
747
                    unset($newExtraFieldsArray);
748
                    $newExtraFieldsArray = array();
749
                    foreach ($extraFields as $extraField) {
750
                        $newExtraFieldsArray[$extraField] = $itemToAdd->$extraField;
751
                    }
752
                    $newObject->$manyManyMethod()->add($itemToAdd, $newExtraFieldsArray);
753
                }
754
                if ($this->recordSession) {
755
                    self::add_to_session("copying ".$count." items into $manyManyMethod, with extra Fields.", $copyFrom, $newObject);
756
                }
757
            }
758
        }
759
        return $this;
760
    }
761
762
    /***
763
     * finds copied items for a many-many relationship
764
     * make sure the many-many relation is also copy-able
765
     * @param DataObject $copyFrom
766
     * @param DataObject $newObject
767
     * @param String $manyManyMethod
768
     * @param DataList $dataListToChooseFrom
769
     * @param Array $extraFields - many_many_ExtraFields
770
     *
771
     * @return CopyFactory
772
     */
773
    public function attachToMoreRelevantManyMany($copyFrom, $newObject, $manyManyMethod, $dataListToChooseFrom, $extraFields = array())
774
    {
775 View Code Duplication
        if ($this->recordSession) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
776
            self::add_to_session(
777
                "
778
                ====================================
779
                ATTACH TO MORE RELEVANT MANY-MANY
780
                MANY-MANY METHOD: $manyManyMethod
781
                OBJECTS TO CHOOSE FROM: ".$dataListToChooseFrom->count()."
782
                EXTRA-FIELDS: '".implode(", ", $extraFields)."'
783
                ====================================
784
                ",
785
                $copyFrom,
786
                $newObject
787
            );
788
        }
789
        //remove current ones on NewObject
790
        if ($this->isForReal) {
791
            $newObject->$manyManyMethod()->removeAll();
792
        }
793
        if ($copyFrom->$manyManyMethod()->count()) {
794
            foreach ($copyFrom->$manyManyMethod() as $manyManyRelation) {
795
                $myDataListToChooseFrom = $dataListToChooseFrom
796
                    ->filter(array($manyManyRelation->CopiedFromFieldName($withID = true) => $manyManyRelation->ID))
797
                    ->Sort("Created DESC");
798
                $count = $myDataListToChooseFrom->count();
799
                if ($count == 1 && $newAttachment = $myDataListToChooseFrom->First()) {
800
                    if ($this->recordSession) {
801
                        self::add_to_session("Found Matching record using ".$manyManyRelation->CopiedFromFieldName($withID = true)." with ID: ".$manyManyRelation->ID, $copyFrom, $newObject);
802
                    }
803
                    if ($extraFields && count($extraFields)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extraFields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
804
                        unset($newExtraFieldsArray);
805
                        $newExtraFieldsArray = array();
806
                        foreach ($extraFields as $extraField) {
807
                            $newExtraFieldsArray[$extraField] = $newAttachment->$extraField;
808
                        }
809
                        if ($this->isForReal) {
810
                            $newObject->$manyManyMethod()->add($newAttachment, $newExtraFieldsArray);
811
                        }
812
                    } else {
813
                        if ($this->isForReal) {
814
                            $newObject->$manyManyMethod()->add($newAttachment);
815
                        }
816
                    }
817
                } else {
818
                    if ($this->recordSession) {
819
                        $useStatement =  ", using '".$manyManyRelation->CopiedFromFieldName($withID = true)."' with ID: '".$manyManyRelation->ID."'.";
820
                        if ($count > 1) {
821
                            self::add_to_session("ERROR: found too many Matching records".$useStatement, $copyFrom, $newObject);
822
                        } elseif ($count == 0) {
823
                            self::add_to_session("ERROR: Could not find any Matching records".$useStatement, $copyFrom, $newObject);
824
                        } else {
825
                            self::add_to_session("ERROR: There was an error retrieving the matching record".$useStatement, $copyFrom, $newObject);
826
                        }
827
                    }
828
                    if ($this->isForReal) {
829
                        //nothing to do here as they have already been deleted.
830
                    }
831
                }
832
            }
833
        } else {
834
            if ($this->recordSession) {
835
                self::add_to_session("copyFrom object does not have a value for", $copyFrom, $newObject);
836
            }
837
        }
838
        if ($this->recordSession) {
839
            self::add_to_session("*** END OF attachToMoreRelevantManyMany ***", $copyFrom, $newObject);
840
        }
841
        return $this;
842
    }
843
}
844