1+ <?php
2+
3+ namespace Sprocketbox \Toolkit \Operations ;
4+
5+ use Illuminate \Container \Container ;
6+ use Illuminate \Contracts \Container \BindingResolutionException ;
7+ use Illuminate \Support \Str ;
8+ use InvalidArgumentException ;
9+
10+ abstract class Operation implements Contracts \Operation
11+ {
12+ /**
13+ * @return static
14+ */
15+ public static function start (): self
16+ {
17+ try {
18+ return Container::getInstance ()->make (__CLASS__ , func_get_args ());
19+ } catch (BindingResolutionException $ e ) {
20+ report ($ e );
21+ }
22+ }
23+
24+ /**
25+ * Handle any calls to setters.
26+ *
27+ * Match the called setter name to a property name.
28+ *
29+ * @param $name
30+ * @param $arguments
31+ *
32+ * @return self
33+ */
34+ public function __call ($ name , $ arguments ): self
35+ {
36+ // Error if there are no arguments provided
37+ if (count ($ arguments ) === 0 ) {
38+ throw new InvalidArgumentException ('Must provide a property value ' );
39+ }
40+
41+ // If the property doesn't exist we're going to want to error
42+ // There's no nice way to check if a property is actually accessible without using reflection
43+ // which is overkill here, so we're going to let it error naturally
44+ if (! property_exists ($ this , $ name )) {
45+ throw new InvalidArgumentException ('Invalid operation property ' );
46+ }
47+
48+ $ this ->$ name = count ($ arguments ) === 1 ? $ arguments [0 ] : $ arguments ;
49+
50+ return $ this ;
51+ }
52+
53+ /**
54+ * Get an array of attributes using class properties, optionally skipping null entries.
55+ *
56+ * @param array<string> $properties An array of properties to snake case and use as array keys
57+ * @param bool|array<string> $skipIfNull True to skip null, false to not, or an array of properties to skip if null
58+ *
59+ * @return array
60+ */
61+ protected function getAttributes (array $ properties , $ skipIfNull = false ): array
62+ {
63+ $ attributes = [];
64+
65+ foreach ($ properties as $ property ) {
66+ $ property = Str::camel ($ property );
67+
68+ if (! property_exists ($ this , $ property )) {
69+ throw new InvalidArgumentException (sprintf ('Property %s on %s does not exist ' , self ::class, $ property ));
70+ }
71+
72+ if ($ this ->shouldSkip ($ property , $ skipIfNull )) {
73+ continue ;
74+ }
75+
76+ /** @noinspection NullCoalescingOperatorCanBeUsedInspection */
77+ $ attributes [Str::snake ($ property )] = isset ($ this ->{$ property }) ? $ this ->{$ property } : null ;
78+ }
79+
80+ return $ attributes ;
81+ }
82+
83+ /**
84+ * Check if the property should be skipped.
85+ *
86+ * @param string $property
87+ * @param bool|array<string> $skipIfNull
88+ *
89+ * @return bool
90+ */
91+ private function shouldSkip (string $ property , $ skipIfNull = false ): bool
92+ {
93+ return (! isset ($ this ->{$ property }) && $ this ->{$ property } === null )
94+ && ($ skipIfNull === true || (is_array ($ skipIfNull ) && in_array ($ property , $ skipIfNull , true )));
95+ }
96+ }
0 commit comments