Completed
Push — master ( 797960...471166 )
by Loz
11:55
created

DataObjectDuplicationTest::testDuplicateUnsaved()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
nc 1
nop 0
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use SilverStripe\ORM\DataObject;
6
use SilverStripe\Dev\SapphireTest;
7
use SilverStripe\ORM\FieldType\DBDatetime;
8
9
class DataObjectDuplicationTest extends SapphireTest
10
{
11
12
    protected $usesDatabase = true;
13
14
    protected static $extra_dataobjects = array(
15
        DataObjectDuplicationTest\Class1::class,
16
        DataObjectDuplicationTest\Class2::class,
17
        DataObjectDuplicationTest\Class3::class,
18
        DataObjectDuplicationTest\Class4::class,
19
    );
20
21
    public function testDuplicate()
22
    {
23
        DBDatetime::set_mock_now('2016-01-01 01:01:01');
24
        $orig = new DataObjectDuplicationTest\Class1();
25
        $orig->text = 'foo';
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class1>. 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...
26
        $orig->write();
27
        DBDatetime::set_mock_now('2016-01-02 01:01:01');
28
        $duplicate = $orig->duplicate();
29
        $this->assertInstanceOf(
30
            DataObjectDuplicationTest\Class1::class,
31
            $duplicate,
32
            'Creates the correct type'
33
        );
34
        $this->assertNotEquals(
35
            $duplicate->ID,
36
            $orig->ID,
37
            'Creates a unique record'
38
        );
39
        $this->assertEquals(
40
            'foo',
41
            $duplicate->text,
42
            'Copies fields'
43
        );
44
        $this->assertEquals(
45
            2,
46
            DataObjectDuplicationTest\Class1::get()->Count(),
47
            'Only creates a single duplicate'
48
        );
49
        $this->assertEquals(DBDatetime::now()->Nice(), $duplicate->dbObject('Created')->Nice());
50
        $this->assertNotEquals($orig->dbObject('Created')->Nice(), $duplicate->dbObject('Created')->Nice());
51
    }
52
53
    public function testDuplicateHasOne()
54
    {
55
        $relationObj = new DataObjectDuplicationTest\Class1();
56
        $relationObj->text = 'class1';
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class1>. 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...
57
        $relationObj->write();
58
59
        $orig = new DataObjectDuplicationTest\Class2();
60
        $orig->text = 'class2';
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class2>. 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...
61
        $orig->oneID = $relationObj->ID;
0 ignored issues
show
Documentation introduced by
The property oneID does not exist on object<SilverStripe\ORM\...DuplicationTest\Class2>. 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...
62
        $orig->write();
63
64
        $duplicate = $orig->duplicate();
65
        $this->assertEquals(
66
            $relationObj->ID,
67
            $duplicate->oneID,
68
            'Copies has_one relationship'
69
        );
70
        $this->assertEquals(
71
            2,
72
            DataObjectDuplicationTest\Class2::get()->Count(),
73
            'Only creates a single duplicate'
74
        );
75
        $this->assertEquals(
76
            1,
77
            DataObjectDuplicationTest\Class1::get()->Count(),
78
            'Does not create duplicate of has_one relationship'
79
        );
80
    }
81
82
83
    public function testDuplicateManyManyClasses()
84
    {
85
        //create new test classes below
86
        $one = new DataObjectDuplicationTest\Class1();
87
        $two = new DataObjectDuplicationTest\Class2();
88
        $three = new DataObjectDuplicationTest\Class3();
89
90
        //set some simple fields
91
        $text1 = "Test Text 1";
92
        $text2 = "Test Text 2";
93
        $text3 = "Test Text 3";
94
        $one->text = $text1;
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class1>. 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...
95
        $two->text = $text2;
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class2>. 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...
96
        $three->text = $text3;
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class3>. 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...
97
98
        //write the to DB
99
        $one->write();
100
        $two->write();
101
        $three->write();
102
103
        //create relations
104
        $one->twos()->add($two);
105
        $one->threes()->add($three);
106
107
        $one = DataObject::get_by_id(DataObjectDuplicationTest\Class1::class, $one->ID);
108
        $two = DataObject::get_by_id(DataObjectDuplicationTest\Class2::class, $two->ID);
109
        $three = DataObject::get_by_id(DataObjectDuplicationTest\Class3::class, $three->ID);
110
111
        //test duplication
112
        $oneCopy = $one->duplicate(true, true);
113
        $twoCopy = $two->duplicate(true, true);
114
        $threeCopy = $three->duplicate(true, true);
115
116
        $oneCopy = DataObject::get_by_id(DataObjectDuplicationTest\Class1::class, $oneCopy->ID);
117
        $twoCopy = DataObject::get_by_id(DataObjectDuplicationTest\Class2::class, $twoCopy->ID);
118
        $threeCopy = DataObject::get_by_id(DataObjectDuplicationTest\Class3::class, $threeCopy->ID);
119
120
        $this->assertNotNull($oneCopy, "Copy of 1 exists");
121
        $this->assertNotNull($twoCopy, "Copy of 2 exists");
122
        $this->assertNotNull($threeCopy, "Copy of 3 exists");
123
124
        $this->assertEquals($text1, $oneCopy->text);
125
        $this->assertEquals($text2, $twoCopy->text);
126
        $this->assertEquals($text3, $threeCopy->text);
127
128
        $this->assertNotEquals(
129
            $one->twos()->Count(),
130
            $oneCopy->twos()->Count(),
131
            "Many-to-one relation not copied (has_many)"
132
        );
133
        $this->assertEquals(
134
            $one->threes()->Count(),
135
            $oneCopy->threes()->Count(),
136
            "Object has the correct number of relations"
137
        );
138
        $this->assertEquals(
139
            $three->ones()->Count(),
140
            $threeCopy->ones()->Count(),
141
            "Object has the correct number of relations"
142
        );
143
144
        $this->assertEquals(
145
            $one->ID,
146
            $twoCopy->one()->ID,
147
            "Match between relation of copy and the original"
148
        );
149
        $this->assertEquals(
150
            0,
151
            $oneCopy->twos()->Count(),
152
            "Many-to-one relation not copied (has_many)"
153
        );
154
        $this->assertEquals(
155
            $three->ID,
156
            $oneCopy->threes()->First()->ID,
157
            "Match between relation of copy and the original"
158
        );
159
        $this->assertEquals(
160
            $one->ID,
161
            $threeCopy->ones()->First()->ID,
162
            "Match between relation of copy and the original"
163
        );
164
    }
165
166
    public function testDuplicateManyManyFiltered()
167
    {
168
        $parent = new DataObjectDuplicationTest\Class4();
169
        $parent->Title = 'Parent';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<SilverStripe\ORM\...DuplicationTest\Class4>. 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...
170
        $parent->write();
171
172
        $child = new DataObjectDuplicationTest\Class4();
173
        $child->Title = 'Child';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<SilverStripe\ORM\...DuplicationTest\Class4>. 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...
174
        $child->write();
175
176
        $grandChild = new DataObjectDuplicationTest\Class4();
177
        $grandChild->Title = 'GrandChild';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<SilverStripe\ORM\...DuplicationTest\Class4>. 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...
178
        $grandChild->write();
179
180
        $parent->Children()->add($child);
181
        $child->Children()->add($grandChild);
182
183
        // Duplcating $child should only duplicate grandchild
184
        $childDuplicate = $child->duplicate(true, 'many_many');
185
        $this->assertEquals(0, $childDuplicate->Parents()->count());
186
        $this->assertDOSEquals(
187
            [['Title' => 'GrandChild']],
188
            $childDuplicate->Children()
189
        );
190
191
        // Duplicate belongs_many_many only
192
        $belongsDuplicate = $child->duplicate(true, 'belongs_many_many');
193
        $this->assertEquals(0, $belongsDuplicate->Children()->count());
194
        $this->assertDOSEquals(
195
            [['Title' => 'Parent']],
196
            $belongsDuplicate->Parents()
197
        );
198
199
        // Duplicate all
200
        $allDuplicate = $child->duplicate(true, true);
201
        $this->assertDOSEquals(
202
            [['Title' => 'Parent']],
203
            $allDuplicate->Parents()
204
        );
205
        $this->assertDOSEquals(
206
            [['Title' => 'GrandChild']],
207
            $allDuplicate->Children()
208
        );
209
    }
210
211
    /**
212
     * Test duplication of UnsavedRelations
213
     */
214
    public function testDuplicateUnsaved()
215
    {
216
        $one = new DataObjectDuplicationTest\Class1();
217
        $one->text = "Test Text 1";
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class1>. 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...
218
        $three = new DataObjectDuplicationTest\Class3();
219
        $three->text = "Test Text 3";
0 ignored issues
show
Documentation introduced by
The property text does not exist on object<SilverStripe\ORM\...DuplicationTest\Class3>. 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...
220
        $one->threes()->add($three);
221
        $this->assertDOSEquals(
222
            [['text' => 'Test Text 3']],
223
            $one->threes()
224
        );
225
        // Test duplicate
226
        $dupe = $one->duplicate(false, true);
227
        $this->assertEquals('Test Text 1', $dupe->text);
228
        $this->assertDOSEquals(
229
            [['text' => 'Test Text 3']],
230
            $dupe->threes()
231
        );
232
    }
233
}
234