PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.2.2
Pods – Custom Content Types and Fields v3.2.2
trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / src / Pods / Integrations / WPGraphQL / Field.php
pods / src / Pods / Integrations / WPGraphQL Last commit date
Connection_Resolver 3 years ago Connection.php 3 years ago Field.php 3 years ago Integration.php 3 years ago Service_Provider.php 3 years ago Settings.php 3 years ago
Field.php
312 lines
1 <?php
2
3 namespace Pods\Integrations\WPGraphQL;
4
5 use GraphQL\Type\Definition\ResolveInfo;
6 use Pods\Pod_Manager;
7 use Pods\Whatsit\Field as Pod_Field;
8 use Pods\Whatsit\Pod;
9 use WPGraphQL\AppContext;
10 use WPGraphQL\Data\Loader\PostObjectLoader;
11 use WPGraphQL\Model\Comment;
12 use WPGraphQL\Model\Menu;
13 use WPGraphQL\Model\MenuItem;
14 use WPGraphQL\Model\Model;
15 use WPGraphQL\Model\Post;
16 use WPGraphQL\Model\Term;
17 use WPGraphQL\Model\User;
18
19 /**
20 * Field interfacing functionality for GraphQL.
21 *
22 * @since 2.9.0
23 */
24 class Field {
25
26 /**
27 * The field data.
28 *
29 * @since 2.9.0
30 *
31 * @var Pod_Field
32 */
33 private $field;
34
35 /**
36 * The pod data.
37 *
38 * @since 2.9.0
39 *
40 * @var Pod
41 */
42 private $pod;
43
44 /**
45 * List of arguments.
46 *
47 * @since 2.9.0
48 *
49 * @var array
50 */
51 private $args;
52
53 /**
54 * List of connections that need to be registered later.
55 *
56 * @since 2.9.0
57 *
58 * @var array
59 */
60 private static $connections = [];
61
62 /**
63 * Field constructor.
64 *
65 * @since 2.9.0
66 *
67 * @param Pod_Field $field The field data.
68 * @param Pod $pod The pod data.
69 * @param array $args List of arguments to setup.
70 */
71 public function __construct( $field, $pod, $args ) {
72 $this->field = $field;
73 $this->pod = $pod;
74 $this->args = $args;
75
76 $required = [
77 'type_name',
78 'field_name',
79 'graphql_type',
80 ];
81
82 // If we are missing required arguments, don't register the field.
83 foreach ( $required as $arg ) {
84 if ( empty( $this->args[ $arg ] ) ) {
85 return;
86 }
87 }
88
89 // Register the field.
90 $this->register_field();
91 }
92
93 /**
94 * Register the field.
95 *
96 * @since 2.9.0
97 */
98 public function register_field() {
99 $is_connection = 'connection' === $this->args['graphql_format'] && ! empty( $this->args['related_type_name'] );
100 $is_multi = is_array( $this->args['graphql_type'] ) && isset( $this->args['graphql_type']['list_of'] );
101 $connection_name = null;
102
103 if ( $is_connection ) {
104 $connection_name = $this->args['type_name'] . '_' . $this->args['field_name'] . '_connection';
105
106 $this->args['graphql_type'] = $connection_name;
107
108 if ( $is_multi ) {
109 $this->args['graphql_type'] = [
110 'list_of' => $this->args['graphql_type'],
111 ];
112 }
113 }
114
115 $config = [
116 'type' => $this->args['graphql_type'],
117 'args' => [
118 'format' => [
119 'type' => 'PostObjectFieldFormatEnum',
120 'description' => __( 'Format of the field output', 'pods' ),
121 ],
122 ],
123 'resolve' => [ $this, 'get_field_value' ],
124 ];
125
126 // Remove the format arg if the type is not a string.
127 if ( 'String' !== $this->args['graphql_type'] && ( ! $is_multi || 'String' !== $this->args['graphql_type']['list_of'] ) ) {
128 unset( $config['args'] );
129 }
130
131 try {
132 // Save the config for reference later.
133 $this->args['config'] = $config;
134 $this->args['is_multi'] = $is_multi;
135
136 if ( ! $is_connection ) {
137 register_graphql_field( $this->args['type_name'], $this->args['field_name'], $config );
138 }
139
140 // Maybe add a connection to set up later.
141 if ( $is_connection ) {
142 self::$connections[] = [
143 'from' => $this->args['type_name'],
144 'from_field' => $this->args['field_name'],
145 'name' => $connection_name,
146 'to' => $this->args['related_type_name'],
147 'object_type' => $this->args['related_object_type'],
148 'object_name' => $this->args['related_object_name'],
149 'is_multi' => $is_multi,
150 'field' => $this,
151 ];
152 }
153 } catch ( Exception $exception ) {
154 // Connection was not registered.
155 throw $exception;
156 }
157 }
158
159 /**
160 * Get the ID from the model object.
161 *
162 * @since 2.9.0
163 *
164 * @param Model $source The model object.
165 *
166 * @return int|null The ID or null if not supported.
167 */
168 public function get_id_from_model( $source ) {
169 switch ( true ) {
170 case $source instanceof Term:
171 $id = $source->term_id;
172 break;
173 case $source instanceof Post:
174 $id = $source->ID;
175 break;
176 case $source instanceof MenuItem:
177 $id = $source->menuItemId;
178 break;
179 case $source instanceof Menu:
180 $id = $source->menuId;
181 break;
182 case $source instanceof User:
183 $id = $source->userId;
184 break;
185 case $source instanceof Comment:
186 $id = $source->comment_ID;
187 break;
188 default:
189 $id = null;
190 break;
191 }
192
193 return $id;
194 }
195
196 /**
197 * Get the ID from the root object.
198 *
199 * @since 2.9.0
200 *
201 * @param Model $source The source passed down from the resolve tree.
202 * @param array $args List of arguments input in the field as part of the GraphQL query.
203 * @param AppContext $context Object containing app context that gets passed down the resolve tree.
204 * @param ResolveInfo $info Info about fields passed down the resolve tree.
205 *
206 * @return mixed The field value.
207 */
208 public function get_field_value( $source, $args, $context, $info ) {
209 $id = $this->get_id_from_model( $source );
210
211 if ( null === $id ) {
212 return '';
213 }
214
215 $pod = pods_container( Pod_Manager::class )->get_pod( $this->pod->get_name(), $id );
216
217 $field_name = $this->field->get_name();
218
219 $format = pods_v( 'format', $args, 'rendered', true );
220
221 if ( in_array( $this->field['type'], [ 'pick', 'file' ], true ) ) {
222 $return_type = $this->args[ $this->field['type'] . '_format' ];
223
224 // Force different formats based on return type.
225 if ( 'connection' === $return_type ) {
226 $format = 'raw';
227 } elseif ( 'id' === $return_type ) {
228 $format = 'raw';
229 } elseif ( 'title' === $return_type ) {
230 $format = 'rendered';
231 } elseif ( in_array( $return_type, [ 'view-url', 'asset-url' ], true ) ) {
232 $format = 'raw';
233
234 $field_name .= '.permalink';
235 }
236 }
237
238 // Maybe return the raw field value.
239 if (
240 $this->args['is_multi']
241 || (
242 'String' !== $this->args['graphql_type']
243 && (
244 ! $this->args['is_multi']
245 || 'String' !== $this->args['graphql_type']['list_of']
246 )
247 )
248 ) {
249 $field_params = [
250 'name' => $field_name,
251 'output' => 'ids',
252 ];
253
254 // If this is a multi field and we need to get the rendered format, turn display on.
255 if ( $this->args['is_multi'] && 'rendered' === $format ) {
256 // Handle formatting.
257 $field_params['display'] = true;
258
259 // Format the values individually.
260 $field_params['display_process_individually'] = true;
261 }
262
263 $value = $pod->field( $field_params );
264
265 if ( ! $this->args['is_multi'] && is_array( $value ) ) {
266 // Maybe force a string.
267 $value = implode( ',', $value );
268 } elseif ( $this->args['is_multi'] && ! is_array( $value ) ) {
269 // Maybe force an array.
270 if ( '' === $value || null === $value ) {
271 $value = [];
272 } else {
273 $value = (array) $value;
274 }
275 }
276
277 return $value;
278 }
279
280 // Check if we are need the raw format.
281 if ( 'raw' === $format ) {
282 $field_params = [
283 'name' => $field_name,
284 'output' => 'ids',
285 ];
286
287 // Return the field in the raw context.
288 return $pod->field( $field_params );
289 }
290
291 // Return the field in the normal render context.
292 return $pod->display( $field_name );
293 }
294
295 /**
296 * Register the connections.
297 *
298 * @since 2.9.0
299 */
300 public static function register_connections() {
301 if ( empty( self::$connections ) ) {
302 return;
303 }
304
305 // Register the connections.
306 foreach ( self::$connections as $connection ) {
307 new Connection( $connection );
308 }
309 }
310
311 }
312