Skip to content

Commit a30b8c6

Browse files
committed
add Dont/ToString
1 parent ad15300 commit a30b8c6

File tree

9 files changed

+211
-5
lines changed

9 files changed

+211
-5
lines changed

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
language: php
22

33
php:
4-
- 7.1
5-
- 7.2
6-
- 7.3
4+
- 7.4
75

86
before_script:
97
- composer update

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The package currently provides the following traits:
2727
* `Dont\DontSet`
2828
* `Dont\DontCall`
2929
* `Dont\DontCallStatic`
30+
* `Dont\DontToString`
3031
* `Dont\JustDont`
3132

3233
Usage is straightforward:
@@ -45,5 +46,5 @@ serialize(new MyClass); // will throw an exception
4546
The same applies to `DontDeserialise`, but this
4647
time with `unserialize()`.
4748

48-
`Dont\JustDont` includes other seven traits and is the recommended one to use.
49+
`Dont\JustDont` includes other eight traits and is the recommended one to use.
4950

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
}
1717
],
1818
"require": {
19-
"php": "^7.1"
19+
"php": "^7.4"
2020
},
2121
"require-dev": {
2222
"phpunit/phpunit": "^7.5 || ^8.0",

src/Dont/DontToString.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dont;
6+
7+
use Dont\Exception\NonCloneableObject;
8+
use Dont\Exception\NonStringableObject;
9+
use Dont\Exception\TypeError;
10+
11+
trait DontToString
12+
{
13+
/**
14+
* @throws NonCloneableObject
15+
* @throws TypeError
16+
*/
17+
final public function __toString() : string
18+
{
19+
throw NonStringableObject::fromAttemptedToString($this);
20+
}
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dont\Exception;
6+
7+
use LogicException;
8+
9+
class NonStringableObject extends LogicException implements ExceptionInterface
10+
{
11+
private const ERROR_TEMPLATE = <<<'ERROR'
12+
The given object %s#%s is not designed to be stringable.
13+
14+
You tried to access a method called "__toString()".
15+
ERROR;
16+
17+
/**
18+
* @param object $object
19+
*
20+
* @return NonStringableObject
21+
*
22+
* @throws TypeError
23+
*/
24+
public static function fromAttemptedToString($object) : self
25+
{
26+
if (! is_object($object)) {
27+
throw TypeError::fromNonObject($object);
28+
}
29+
30+
$className = get_class($object);
31+
32+
return new self(sprintf(
33+
self::ERROR_TEMPLATE,
34+
$className,
35+
spl_object_hash($object)
36+
));
37+
}
38+
}

src/Dont/JustDont.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ trait JustDont
1313
use DontClone;
1414
use DontSerialise;
1515
use DontDeserialise;
16+
use DontToString;
1617
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DontTest;
6+
7+
use Dont\DontToString;
8+
use Dont\Exception\NonStringableObject;
9+
use DontTestAsset\DontDoIt;
10+
use DontTestAsset\NonStringable;
11+
use PHPUnit\Framework\TestCase;
12+
13+
/**
14+
* @covers \Dont\DontToString
15+
*/
16+
final class DontToStringTest extends TestCase
17+
{
18+
/**
19+
* @dataProvider nonStringableObject
20+
*
21+
* @param object $object
22+
*/
23+
public function testWillThrowOnToStringMethodAttempt($object) : void
24+
{
25+
$this->expectException(NonStringableObject::class);
26+
27+
$object->__toString();
28+
}
29+
30+
/**
31+
* @dataProvider nonStringableObject
32+
*
33+
* @param object $object
34+
*/
35+
public function testWillThrowOnStringCastAttempt($object) : void
36+
{
37+
$this->expectException(NonStringableObject::class);
38+
39+
(string) $object;
40+
}
41+
42+
/**
43+
* @return object[]
44+
*/
45+
public function nonStringableObject() : array
46+
{
47+
return [
48+
[new NonStringable()],
49+
[new DontDoIt()],
50+
];
51+
}
52+
53+
public function testToStringPreventionIsFinal() : void
54+
{
55+
self::assertTrue((new \ReflectionMethod(DontToString::class, '__toString'))->isFinal());
56+
}
57+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DontTest\Exception;
6+
7+
use Dont\Exception\ExceptionInterface;
8+
use Dont\Exception\NonCloneableObject;
9+
use Dont\Exception\NonStringableObject;
10+
use Dont\Exception\TypeError;
11+
use LogicException;
12+
use PHPUnit\Framework\TestCase;
13+
use stdClass;
14+
15+
/**
16+
* @covers \Dont\Exception\NonStringableObject
17+
*/
18+
final class NonStringableObjectTest extends TestCase
19+
{
20+
/**
21+
* @dataProvider objectProvider
22+
*
23+
* @param object $object
24+
*/
25+
public function testFromAttemptedCloning($object) : void
26+
{
27+
$exception = NonStringableObject::fromAttemptedToString($object);
28+
29+
self::assertInstanceOf(NonStringableObject::class, $exception);
30+
self::assertInstanceOf(LogicException::class, $exception);
31+
self::assertInstanceOf(ExceptionInterface::class, $exception);
32+
33+
$expected = 'The given object ' . get_class($object)
34+
. '#' . spl_object_hash($object) . " is not designed to be stringable.\n\n"
35+
. "You tried to access a method called \"__toString()\".";
36+
37+
self::assertSame($expected, $exception->getMessage());
38+
}
39+
40+
/**
41+
* @return object[][]
42+
*/
43+
public function objectProvider() : array
44+
{
45+
return [
46+
[new stdClass()],
47+
[$this],
48+
];
49+
}
50+
51+
/**
52+
* @dataProvider nonObjectProvider
53+
*
54+
* @param mixed $nonObject
55+
*/
56+
public function testWillThrowOnNonObject($nonObject) : void
57+
{
58+
$this->expectException(TypeError::class);
59+
60+
NonStringableObject::fromAttemptedToString($nonObject);
61+
}
62+
63+
/**
64+
* @return mixed[][]
65+
*/
66+
public function nonObjectProvider() : array
67+
{
68+
return [
69+
[null],
70+
[true],
71+
[123],
72+
[12.3],
73+
['foo'],
74+
[[]],
75+
[STDERR],
76+
];
77+
}
78+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DontTestAsset;
6+
7+
use Dont\DontToString;
8+
9+
final class NonStringable
10+
{
11+
use DontToString;
12+
}

0 commit comments

Comments
 (0)