PluginProbe
WPGraphQL / trunk
WPGraphQL vtrunk
2.22.3 2.22.2 2.22.1 2.22.0 2.21.1 2.21.0 2.20.0 2.19.0 2.18.0 2.17.0 2.16.0 2.15.1 2.15.0 2.14.1 2.14.0 2.13.0 2.2.0 2.3.0 2.3.3 2.3.6 2.3.8 2.5.0 2.5.1 2.5.2 2.5.3 All 177 releases
wp-graphql / src / Model / MenuItem.php

MenuItem.php in WPGraphQL trunk, at src/Model/MenuItem.php

201 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPGraphQL\Model;
4
5 use Exception;
6 use GraphQL\Error\UserError;
7 use GraphQLRelay\Relay;
8 use WP_Post;
9
10 /**
11 * Class MenuItem - Models the data for the MenuItem object type
12 *
13 * @property string[] $cssClasses
14 * @property int $databaseId
15 * @property ?string $description
16 * @property ?string $id
17 * @property ?string $label
18 * @property ?string $linkRelationship
19 * @property string[]|null $locations
20 * @property ?int $menuDatabaseId
21 * @property ?string $menuId
22 * @property int $objectId
23 * @property ?int $parentDatabaseId
24 * @property ?string $parentId
25 * @property ?string $target
26 * @property ?string $title
27 * @property ?string $uri
28 * @property ?string $url
29 *
30 * @package WPGraphQL\Model
31 *
32 * @extends \WPGraphQL\Model\Model<object|mixed>
33 */
34 class MenuItem extends Model {
35 /**
36 * MenuItem constructor.
37 *
38 * @param \WP_Post $post The incoming WP_Post object that needs modeling
39 *
40 * @return void
41 */
42 public function __construct( WP_Post $post ) {
43 $this->data = wp_setup_nav_menu_item( $post );
44 parent::__construct();
45 }
46
47 /**
48 * {@inheritDoc}
49 *
50 * If a MenuItem is not connected to a menu that's assigned to a location
51 * it's not considered a public node.
52 *
53 * @throws \Exception
54 */
55 public function is_private() {
56
57 // If the current user can edit theme options, consider the menu item public
58 if ( current_user_can( 'edit_theme_options' ) ) {
59 return false;
60 }
61
62 // Get menu locations for the active theme
63 $locations = get_theme_mod( 'nav_menu_locations' );
64
65 // If there are no menu locations, consider the MenuItem private
66 if ( empty( $locations ) ) {
67 return true;
68 }
69
70 // Get the values of the locations
71 $location_ids = array_values( $locations );
72 $menus = wp_get_object_terms( $this->data->ID, 'nav_menu', [ 'fields' => 'ids' ] );
73
74 // If there are no menus
75 if ( empty( $menus ) ) {
76 return true;
77 }
78
79 if ( is_wp_error( $menus ) ) {
80 // translators: %s is the menu item ID.
81 throw new Exception( esc_html( sprintf( __( 'No menus could be found for menu item %s', 'wp-graphql' ), $this->data->ID ) ) );
82 }
83
84 $menu_id = $menus[0];
85 if ( empty( $location_ids ) || ! in_array( $menu_id, $location_ids, true ) ) {
86 return true;
87 }
88
89 return false;
90 }
91
92 /**
93 * {@inheritDoc}
94 */
95 protected function init() {
96 if ( empty( $this->fields ) ) {
97 $this->fields = [
98 'cssClasses' => function () {
99 // If all we have is a non-array or an array with one empty
100 // string, return an empty array.
101 if ( ! isset( $this->data->classes ) || ! is_array( $this->data->classes ) || empty( $this->data->classes ) || empty( $this->data->classes[0] ) ) {
102 return [];
103 }
104
105 return $this->data->classes;
106 },
107 'databaseId' => function () {
108 return absint( $this->data->ID );
109 },
110 'description' => function () {
111 return ! empty( $this->data->description ) ? $this->data->description : null;
112 },
113 'id' => function () {
114 return ! empty( $this->databaseId ) ? Relay::toGlobalId( 'post', (string) $this->databaseId ) : null;
115 },
116 'label' => function () {
117 return ! empty( $this->data->title ) ? $this->html_entity_decode( $this->data->title, 'label', true ) : null;
118 },
119 'linkRelationship' => function () {
120 return ! empty( $this->data->xfn ) ? $this->data->xfn : null;
121 },
122 'locations' => function () {
123 if ( empty( $this->menuDatabaseId ) ) {
124 return null;
125 }
126
127 $menu_locations = get_theme_mod( 'nav_menu_locations' );
128
129 if ( empty( $menu_locations ) || ! is_array( $menu_locations ) ) {
130 return null;
131 }
132
133 $locations = null;
134 foreach ( $menu_locations as $location => $id ) {
135 if ( absint( $id ) === ( $this->menuDatabaseId ) ) {
136 $locations[] = $location;
137 }
138 }
139
140 return $locations;
141 },
142 'menuDatabaseId' => function () {
143 $menus = wp_get_object_terms( $this->data->ID, 'nav_menu' );
144 if ( is_wp_error( $menus ) ) {
145 throw new UserError( esc_html( $menus->get_error_message() ) );
146 }
147
148 return ! empty( $menus[0]->term_id ) ? $menus[0]->term_id : null;
149 },
150 'menuId' => function () {
151 return ! empty( $this->menuDatabaseId ) ? Relay::toGlobalId( 'term', (string) $this->menuDatabaseId ) : null;
152 },
153 'objectId' => function () {
154 return absint( $this->data->object_id );
155 },
156 'order' => function () {
157 return $this->data->menu_order;
158 },
159 'parentDatabaseId' => function () {
160 return $this->data->menu_item_parent;
161 },
162 'parentId' => function () {
163 return ! empty( $this->parentDatabaseId ) ? Relay::toGlobalId( 'post', (string) $this->parentDatabaseId ) : null;
164 },
165 'path' => function () {
166 $url = $this->url;
167
168 if ( ! empty( $url ) ) {
169 /** @var array<string,mixed> $parsed */
170 $parsed = wp_parse_url( $url );
171 if ( isset( $parsed['host'] ) && strpos( home_url(), $parsed['host'] ) ) {
172 return $parsed['path'];
173 }
174 }
175
176 return $url;
177 },
178 'target' => function () {
179 return ! empty( $this->data->target ) ? $this->data->target : null;
180 },
181 'title' => function () {
182 return ( ! empty( $this->data->attr_title ) ) ? $this->data->attr_title : null;
183 },
184 'uri' => function () {
185 $url = $this->url;
186
187 return ! empty( $url ) ? str_ireplace( home_url(), '', $url ) : null;
188 },
189 'url' => function () {
190 return ! empty( $this->data->url ) ? $this->data->url : null;
191 },
192
193 // Deprecated.
194 'menuItemId' => function () {
195 return $this->databaseId;
196 },
197 ];
198 }
199 }
200 }
201