• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wp-graphql / wp-graphql / 13316763745

13 Feb 2025 08:45PM UTC coverage: 82.712% (-0.3%) from 83.023%
13316763745

push

github

web-flow
Merge pull request #3307 from wp-graphql/release/v2.0.0

release: v2.0.0

195 of 270 new or added lines in 20 files covered. (72.22%)

180 existing lines in 42 files now uncovered.

13836 of 16728 relevant lines covered (82.71%)

299.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.03
/src/Data/Cursor/TermObjectCursor.php
1
<?php
2
namespace WPGraphQL\Data\Cursor;
3

4
use WP_Term;
5

6
class TermObjectCursor extends AbstractCursor {
7

8
        /**
9
         * @var ?\WP_Term ;
10
         */
11
        public $cursor_node;
12

13
        /**
14
         * Counter for meta value joins
15
         *
16
         * @var int
17
         */
18
        public $meta_join_alias = 0;
19

20
        /**
21
         * {@inheritDoc}
22
         *
23
         * @var string
24
         */
25
        protected $id_key = 't.term_id';
26

27
        /**
28
         * Deprecated in favor of get_query_var()
29
         *
30
         * @param string $name The name of the query var to get
31
         *
32
         * @deprecated 1.9.0
33
         *
34
         * @return mixed|null
35
         */
UNCOV
36
        public function get_query_arg( string $name ) {
×
37
                _deprecated_function( __METHOD__, '1.9.0', self::class . '::get_query_var()' );
×
38

39
                return $this->get_query_var( $name );
×
40
        }
41

42
        /**
43
         * {@inheritDoc}
44
         *
45
         * @return ?\WP_Term ;
46
         */
47
        public function get_cursor_node() {
60✔
48
                // Bail if no offset.
49
                if ( ! $this->cursor_offset ) {
60✔
50
                        return null;
60✔
51
                }
52

53
                /**
54
                 * If pre-hooked, return filtered node.
55
                 *
56
                 * @param \WP_Term|null                           $pre_term The pre-filtered term node.
57
                 * @param int                                     $offset   The cursor offset.
58
                 * @param \WPGraphQL\Data\Cursor\TermObjectCursor $node     The cursor instance.
59
                 *
60
                 * @return \WP_Term|null
61
                 */
62
                $pre_term = apply_filters( 'graphql_pre_term_cursor_node', null, $this->cursor_offset, $this );
9✔
63
                if ( null !== $pre_term ) {
9✔
64
                        return $pre_term;
×
65
                }
66

67
                // Get cursor node.
68
                $term = WP_Term::get_instance( $this->cursor_offset );
9✔
69

70
                return $term instanceof WP_Term ? $term : null;
9✔
71
        }
72

73
        /**
74
         * Deprecated in favor of get_cursor_node().
75
         *
76
         * @return ?\WP_Term
77
         * @deprecated 1.9.0
78
         */
UNCOV
79
        public function get_cursor_term() {
×
80
                _deprecated_function( __METHOD__, '1.9.0', self::class . '::get_cursor_node()' );
×
81

82
                return $this->cursor_node;
×
83
        }
84

85
        /**
86
         * {@inheritDoc}
87
         *
88
         * @param array<array<string,mixed>>[]|null $fields The fields from the CursorBuilder to convert to SQL.
89
         */
90
        public function to_sql( $fields = null ) {
9✔
91
                $sql = $this->builder->to_sql( $fields );
9✔
92
                if ( empty( $sql ) ) {
9✔
93
                        return '';
×
94
                }
95
                return ' AND ' . $sql;
9✔
96
        }
97

98
        /**
99
         * {@inheritDoc}
100
         */
101
        public function get_where() {
9✔
102
                // If we have a bad cursor, just skip.
103
                if ( ! $this->is_valid_offset_and_node() ) {
9✔
104
                        return '';
×
105
                }
106

107
                $orderby = $this->get_query_var( 'orderby' );
9✔
108
                $order   = $this->get_query_var( 'order' );
9✔
109

110
                if ( 'name' === $orderby ) {
9✔
111
                        if ( '>' === $this->compare ) {
8✔
112
                                $order         = 'DESC';
6✔
113
                                $this->compare = '<';
6✔
114
                        } elseif ( '<' === $this->compare ) {
6✔
115
                                $this->compare = '>';
6✔
116
                                $order         = 'ASC';
6✔
117
                        }
118
                }
119

120
                /**
121
                 * If $orderby is just a string just compare with it directly as DESC
122
                 */
123
                if ( ! empty( $orderby ) && is_string( $orderby ) ) {
9✔
124
                        $this->compare_with( $orderby, $order );
9✔
125
                }
126

127
                /**
128
                 * If there's no orderby specified yet, compare with the following fields.
129
                 */
130
                if ( ! $this->builder->has_fields() ) {
9✔
131
                        $this->compare_with_cursor_fields();
×
132
                }
133

134
                /**
135
                 * Stabilize cursor by consistently comparing with the ID.
136
                 */
137
                $this->compare_with_id_field();
9✔
138

139
                return $this->to_sql();
9✔
140
        }
141

142
        /**
143
         * Get AND operator for given order by key
144
         *
145
         * @param string $by    The order by key
146
         * @param string $order The order direction ASC or DESC
147
         *
148
         * @return void
149
         */
150
        private function compare_with( string $by, string $order ) {
9✔
151

152
                // Bail early, if "key" and "value" provided in query_vars.
153
                $key   = $this->get_query_var( "graphql_cursor_compare_by_{$by}_key" );
9✔
154
                $value = $this->get_query_var( "graphql_cursor_compare_by_{$by}_value" );
9✔
155
                if ( ! empty( $key ) && ! empty( $value ) ) {
9✔
156
                        $this->builder->add_field( $key, $value, null, $order );
×
157
                        return;
×
158
                }
159

160
                // Set "key" as term table column and get "value" from cursor node.
161
                $key   = "t.{$by}";
9✔
162
                $value = $this->cursor_node->{$by};
9✔
163

164
                /**
165
                 * If key or value are null, check whether this is a meta key based ordering before bailing.
166
                 */
167
                if ( null === $value ) {
9✔
168
                        $meta_key = $this->get_meta_key( $by );
×
169
                        if ( $meta_key ) {
×
170
                                $this->compare_with_meta_field( $meta_key, $order );
×
171
                        }
172
                        return;
×
173
                }
174

175
                $this->builder->add_field( $key, $value, null, $order );
9✔
176
        }
177

178
        /**
179
         * Compare with meta key field
180
         *
181
         * @param string $meta_key meta key
182
         * @param string $order    The comparison string
183
         *
184
         * @return void
185
         */
UNCOV
186
        private function compare_with_meta_field( string $meta_key, string $order ) {
×
187
                $meta_type  = $this->get_query_var( 'meta_type' );
×
188
                $meta_value = get_term_meta( $this->cursor_offset, $meta_key, true );
×
189

190
                $key = "{$this->wpdb->termmeta}.meta_value";
×
191

192
                /**
193
                 * WP uses mt1, mt2 etc. style aliases for additional meta value joins.
194
                 */
195
                if ( 0 !== $this->meta_join_alias ) {
×
196
                        $key = "mt{$this->meta_join_alias}.meta_value";
×
197
                }
198

199
                ++$this->meta_join_alias;
×
200

201
                $this->builder->add_field( $key, $meta_value, $meta_type, $order, $this );
×
202
        }
203

204
        /**
205
         * Get the actual meta key if any
206
         *
207
         * @param string $by The order by key
208
         *
209
         * @return string|null
210
         */
UNCOV
211
        private function get_meta_key( string $by ) {
×
212
                if ( 'meta_value' === $by || 'meta_value_num' === $by ) {
×
213
                        return $this->get_query_var( 'meta_key' );
×
214
                }
215

216
                /**
217
                 * Check for the WP 4.2+ style meta clauses
218
                 * https://make.wordpress.org/core/2015/03/30/query-improvements-in-wp-4-2-orderby-and-meta_query/
219
                 */
220
                if ( ! isset( $this->query_vars['meta_query'][ $by ] ) ) {
×
221
                        return null;
×
222
                }
223

224
                $clause = $this->query_vars['meta_query'][ $by ];
×
225

226
                return empty( $clause['key'] ) ? null : $clause['key'];
×
227
        }
228
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc