PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / trunk
Permalink Manager Lite vtrunk
2.5.4 2.5.3.4 2.2.18 2.2.19.2 2.2.19.3 2.2.19.3.1 2.2.2 2.2.20 2.2.20.1 2.2.20.3 2.2.4 2.2.5 2.2.6 2.2.7.2 2.2.7.3 2.2.7.5 2.2.7.6 2.2.8.4 2.2.8.5 2.2.8.6 2.2.8.7 2.2.8.9 2.2.9.1 2.2.9.2 2.2.9.2.1 2.2.9.3 2.2.9.4 2.2.9.6 2.2.9.7 2.2.9.9 2.3.0 2.3.1.1 2.4.0 2.4.1 2.4.1.2 2.4.1.3 2.4.1.4 2.4.1.5 2.4.1.6 2.4.2 2.4.2.1 2.4.3 2.4.3.1 2.4.3.2 2.4.3.3 2.4.3.4 2.4.4 2.4.4.1 2.4.4.2 2.4.4.3 2.5.0 2.5.1 2.5.1.1 2.5.1.2 2.5.1.3 2.5.1.4 2.5.2 2.5.2.1 2.5.2.2 2.5.2.3 2.5.2.4 2.5.3 2.5.3.1 2.5.3.2 2.5.3.3 trunk 0.2 0.3 0.3.1 0.3.2 0.3.3 0.3.4 0.4 0.4.1 0.4.2 0.4.3 0.4.4 0.4.6 0.4.7 0.4.8 0.4.9 0.5.3 0.5.4 1.0.0 1.0.1 1.0.4 1.1.0 1.1.1 1.1.2 1.11.6.3 2.0.0 2.0.3 2.0.4 2.0.4.3 2.0.5.1 2.0.5.2 2.0.5.3 2.0.5.3.1 2.0.5.4 2.0.5.4a 2.0.5.5 2.0.5.6 2.0.5.6.1 2.0.5.7 2.0.5.9a 2.0.6.2.1 2.0.6.2a 2.0.6.3 2.1.0 2.1.1 2.1.2.4 2.2.0 2.2.1.1 2.2.1.2 2.2.11 2.2.12 2.2.13.1 2.2.14 2.2.15.1 2.2.16 2.2.17
permalink-manager / includes / views / permalink-manager-uri-editor-post.php
permalink-manager / includes / views Last commit date
permalink-manager-debug.php 1 day ago permalink-manager-permastructures.php 2 months ago permalink-manager-settings.php 1 day ago permalink-manager-tools.php 3 months ago permalink-manager-ui-elements.php 1 day ago permalink-manager-uri-editor-post.php 1 day ago permalink-manager-uri-editor.php 1 day ago
permalink-manager-uri-editor-post.php
336 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 /**
8 * Use WP_List_Table to display the "Bulk URI Editor" for post items
9 */
10 class Permalink_Manager_URI_Editor_Post extends WP_List_Table {
11
12 public $displayed_post_types, $displayed_post_statuses;
13
14 public function __construct() {
15 global $permalink_manager_options, $permalink_manager_active_subsection;
16
17 parent::__construct( array(
18 'singular' => 'slug',
19 'plural' => 'slugs'
20 ) );
21
22 $this->displayed_post_statuses = ( isset( $permalink_manager_options['screen-options']['post_statuses'] ) ) ? Permalink_Manager_Helper_Functions::prepare_array_for_sql_in( $permalink_manager_options['screen-options']['post_statuses'] ) : "'no-post-status'";
23 $this->displayed_post_types = ( $permalink_manager_active_subsection == 'all' ) ? Permalink_Manager_Helper_Functions::prepare_array_for_sql_in( $permalink_manager_options['screen-options']['post_types'] ) : "'{$permalink_manager_active_subsection}'";
24 }
25
26 /**
27 * Get the HTML output with the whole WP_List_Table
28 *
29 * @return string
30 */
31 public function display_admin_section() {
32 $output = "<form id=\"permalinks-post-types-table\" class=\"slugs-table\" method=\"post\">";
33 $output .= wp_nonce_field( 'permalink-manager', 'uri_editor_nonce' );
34 $output .= Permalink_Manager_UI_Elements::generate_option_field( 'pm_session_id', array( 'value' => uniqid(), 'type' => 'hidden' ) );
35
36 // Bypass
37 ob_start();
38
39 $this->prepare_items();
40 $this->display();
41 $output .= ob_get_contents();
42
43 ob_end_clean();
44
45 $output .= "</form>";
46
47 return $output;
48 }
49
50 /**
51 * Return an array of classes to be used in the HTML table
52 *
53 * @return array
54 */
55 function get_table_classes() {
56 return array( 'widefat', 'striped', $this->_args['plural'] );
57 }
58
59 /**
60 * Add columns to the table
61 *
62 * @return array
63 */
64 public function get_columns() {
65 return apply_filters( 'permalink_manager_uri_editor_columns', array(
66 'item_title' => __( 'Post title', 'permalink-manager' ),
67 'item_uri' => __( 'Custom permalink', 'permalink-manager' )
68 ) );
69 }
70
71 /**
72 * Define sortable columns
73 *
74 * @return array
75 */
76 public function get_sortable_columns() {
77 return array(
78 'item_title' => array( 'post_title', false )
79 );
80 }
81
82 /**
83 * Data inside the columns
84 *
85 * @param array $item
86 * @param string $column_name
87 *
88 * @return string
89 */
90 public function column_default( $item, $column_name ) {
91 global $permalink_manager_options;
92
93 if ( Permalink_Manager_Helper_Functions::is_front_page( $item['ID'] ) ) {
94 $uri = '';
95 $permalink = Permalink_Manager_Permastructure_Functions::get_permalink_base( $item['ID'] );
96 $is_front_page = true;
97 } else {
98 $is_draft = ( $item["post_status"] == 'draft' ) ? true : false;
99 $uri = Permalink_Manager_URI_Functions_Post::get_post_uri( $item['ID'], true, $is_draft );
100 $uri = ( ! empty( $permalink_manager_options['general']['decode_uris'] ) ) ? urldecode( $uri ) : $uri;
101 $permalink = get_permalink( $item['ID'] );
102 $is_front_page = false;
103 }
104
105 $field_args_base = array( 'type' => 'text', 'value' => $uri, 'without_label' => true, 'input_class' => 'custom_uri', 'extra_atts' => "data-element-id=\"{$item['ID']}\"" );
106 $post_title = sanitize_text_field( $item['post_title'] );
107
108 $post_statuses_array = Permalink_Manager_Helper_Functions::get_post_statuses();
109 $post_statuses_array['inherit'] = __( 'Inherit (Attachment)', 'permalink-manager' );
110
111 $output = apply_filters( 'permalink_manager_uri_editor_column_content', '', $column_name, get_post( $item['ID'] ) );
112 if ( ! empty( $output ) ) {
113 return $output;
114 }
115
116 switch ( $column_name ) {
117 case 'item_uri':
118 // Get auto-update settings
119 $auto_update_val = get_post_meta( $item['ID'], "auto_update_uri", true );
120 $auto_update_uri = ( ! empty( $auto_update_val ) ) ? $auto_update_val : $permalink_manager_options["general"]["auto_update_uris"];
121
122 if ( $is_front_page ) {
123 $field_args_base['disabled'] = true;
124 $field_args_base['append_content'] = sprintf( '<p class="small uri_locked">%s %s</p>', '<span class="dashicons dashicons-lock"></span>', __( 'URI Editor is disabled because a custom permalink cannot be set for a front page.', 'permalink-manager' ) );
125 } else if ( Permalink_Manager_Helper_Functions::is_draft_excluded( (int) $item['ID'] ) ) {
126 $field_args_base['disabled'] = true;
127 $field_args_base['append_content'] = sprintf( '<p class="small uri_locked">%s %s</p>', '<span class="dashicons dashicons-lock"></span>', __( 'URI Editor disabled due to "Exclude drafts & pending posts" setting and the post status.', 'permalink-manager' ) );
128 } else if ( $auto_update_uri == 1 ) {
129 $field_args_base['readonly'] = true;
130 $field_args_base['append_content'] = sprintf( '<p class="small uri_locked">%s %s</p>', '<span class="dashicons dashicons-lock"></span>', __( 'The above permalink will be automatically updated and is locked for editing.', 'permalink-manager' ) );
131 } else if ( $auto_update_uri == 2 ) {
132 $field_args_base['disabled'] = true;
133 $field_args_base['append_content'] = sprintf( '<p class="small uri_locked">%s %s</p>', '<span class="dashicons dashicons-lock"></span>', __( 'URI Editor disabled due to "Permalink update" setting.', 'permalink-manager' ) );
134 }
135
136 $output = '<div class="custom_uri_container">';
137 $output .= Permalink_Manager_UI_Elements::generate_option_field( "uri[{$item['ID']}]", $field_args_base );
138 $output .= "<span class=\"duplicated_uri_alert\"></span>";
139 $output .= sprintf( "<a class=\"small post_permalink\" href=\"%s\" target=\"_blank\"><span class=\"dashicons dashicons-admin-links\"></span> %s</a>", $permalink, urldecode( $permalink ) );
140 $output .= '</div>';
141
142 return $output;
143
144 case 'item_title':
145 $output = esc_html( $post_title );
146 $output .= '<div class="extra-info small">';
147 $output .= sprintf( "<span><strong>%s:</strong> %s</span>", __( "Slug", "permalink-manager" ), urldecode( $item['post_name'] ) );
148 $output .= sprintf( " | <span><strong>%s:</strong> {$post_statuses_array[$item["post_status"]]}</span>", __( "Post status", "permalink-manager" ) );
149 $output .= apply_filters( 'permalink_manager_uri_editor_extra_info', '', $column_name, get_post( $item['ID'] ) );
150 $output .= '</div>';
151
152 $output .= '<div class="row-actions">';
153 $output .= sprintf( '<span class="edit"><a href="%1$s" title="%2$s">%2$s</a> | </span>', esc_url( get_edit_post_link( $item['ID'] ) ), __( 'Edit', 'permalink-manager' ) );
154 $output .= sprintf( '<span class="view"><a target="_blank" href="%1$s" title="%2$s %3$s" rel="permalink">%2$s</a> | </span>', esc_attr( $permalink ), __( 'View', 'permalink-manager' ), esc_html( $post_title ) );
155 $output .= sprintf( '<span class="id">#%s</span>', esc_html( $item['ID'] ) );
156 $output .= '</div>';
157
158 return $output;
159
160 default:
161 return $item[ $column_name ];
162 }
163 }
164
165 /**
166 * The button that allows to save updated slugs
167 */
168 function extra_tablenav( $which ) {
169 global $wpdb;
170
171 if ( $which == "top" ) {
172 $button_text = __( 'Save all the permalinks below', 'permalink-manager' );
173 $button_name = 'update_all_slugs[top]';
174 } else {
175 $button_text = __( 'Save all the permalinks above', 'permalink-manager' );
176 $button_name = 'update_all_slugs[bottom]';
177 }
178
179 $html = "<div class=\"alignleft actions\">";
180 $html .= get_submit_button( $button_text, 'primary alignleft', $button_name, false, array( 'id' => 'doaction', 'value' => 'update_all_slugs' ) );
181 $html .= "</div>";
182
183 if ( $which == "top" ) {
184 // Filter by date
185 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
186 $months = $wpdb->get_results( "SELECT DISTINCT month(post_date) AS m, year(post_date) AS y FROM {$wpdb->posts} WHERE post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types) ORDER BY post_date DESC", ARRAY_A );
187
188 if ( $months ) {
189 $choices = array( __( 'All dates', 'permalink-manager' ) );
190
191 foreach ( $months as $month ) {
192 $month_raw = sprintf( "%s-%s", $month['y'], $month['m'] );
193 $choices[ $month_raw ] = date_i18n( "F Y", strtotime( $month_raw ) );
194 }
195
196 $select_field = Permalink_Manager_UI_Elements::generate_option_field( 'month', array(
197 'type' => 'select',
198 'choices' => $choices,
199 'value' => ( isset( $_REQUEST['month'] ) ) ? sanitize_key( $_REQUEST['month'] ) : '' // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only WP_List_Table month filter
200 ) );
201
202 $html .= sprintf( '<div id="months-filter" class="alignleft actions">%s</div>', $select_field );
203 }
204
205 $extra_fields = apply_filters( 'permalink_manager_uri_editor_extra_fields', '', 'posts' );
206
207 if ( $months || $extra_fields ) {
208 $html .= $extra_fields;
209
210 $html .= '<div class="alignleft">';
211 $html .= get_submit_button( __( "Filter", "permalink-manager" ), 'button', false, false, array( 'id' => 'filter-button', 'name' => 'filter-button' ) );
212 $html .= "</div>";
213 }
214
215 $html .= '<div class="alignright">';
216 $html .= $this->search_box( __( 'Search', 'permalink-manager' ), 'search-input' );
217 $html .= '</div>';
218 }
219
220 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
221 echo $html;
222 }
223
224 /**
225 * Display the search input field
226 *
227 * @return string
228 */
229 public function search_box( $text = '', $input_id = '' ) {
230 $search_query = ( ! empty( $_REQUEST['s'] ) ) ? esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ) : ""; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only WP_List_Table search value; no state change.
231
232 $output = "<p class=\"search-box\">";
233 $output .= "<label class=\"screen-reader-text\" for=\"{$input_id}\">{$text}:</label>";
234 $output .= Permalink_Manager_UI_Elements::generate_option_field( 's', array( 'value' => $search_query, 'type' => 'search' ) );
235 $output .= get_submit_button( $text, 'button', false, false, array( 'id' => 'search-submit', 'name' => 'search-submit' ) );
236 $output .= "</p>";
237
238 return $output;
239 }
240
241 /**
242 * Prepare the items for the table to process
243 */
244 public function prepare_items() {
245 global $wpdb;
246
247 $columns = $this->get_columns();
248 $hidden = $this->get_hidden_columns();
249 $sortable = $this->get_sortable_columns();
250 $current_page = $this->get_pagenum();
251
252 // SQL query parameters
253 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only WP_List_Table search value; no state change.
254 $order = ( isset( $_REQUEST['order'] ) && in_array( $_REQUEST['order'], array( 'asc', 'desc' ) ) ) ? sanitize_sql_orderby( wp_unslash( $_REQUEST['order'] ) ) : 'desc';
255 $orderby = ( isset( $_REQUEST['orderby'] ) ) ? sanitize_sql_orderby( wp_unslash( $_REQUEST['orderby'] ) ) : 'ID';
256 $search_query = ( ! empty( $_REQUEST['s'] ) ) ? esc_sql( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ) : "";
257
258 // Extra filters
259 $extra_filters = $attachment_support = '';
260 if ( ! empty( $_GET['month'] ) ) {
261 $month = gmdate( "n", strtotime( sanitize_key( $_GET['month'] ) ) );
262 $year = gmdate( "Y", strtotime( sanitize_key( $_GET['month'] ) ) );
263
264 $extra_filters .= "AND month(post_date) = {$month} AND year(post_date) = {$year}";
265 }
266 // phpcs:enable
267
268 // Support for attachments
269 if ( strpos( $this->displayed_post_types, 'attachment' ) !== false ) {
270 $attachment_support = " OR (post_type = 'attachment')";
271 }
272
273 // Grab posts from database
274 $sql_parts['start'] = "SELECT * FROM {$wpdb->posts} AS p ";
275 if ( $search_query ) {
276 $sql_parts['where'] = "WHERE (LOWER(post_title) LIKE LOWER('%{$search_query}%') ";
277
278 // Search in array with custom URIs
279 $found = Permalink_Manager_URI_Functions::find_uri( $search_query, false, 'posts' );
280 if ( $found ) {
281 $sql_parts['where'] .= sprintf( "OR ID IN (%s)", implode( ',', $found ) );
282 }
283 $sql_parts['where'] .= " ) AND ((post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types)) {$attachment_support}) {$extra_filters} ";
284 } else {
285 $sql_parts['where'] = "WHERE ((post_status IN ($this->displayed_post_statuses) AND post_type IN ($this->displayed_post_types)) {$attachment_support}) {$extra_filters} ";
286 }
287
288 // Do not display excluded posts in Bulk URI Editor
289 $excluded_posts = Permalink_Manager_Helper_Functions::get_excluded_post_ids();
290 if ( ! empty( $excluded_posts ) && is_array( $excluded_posts ) ) {
291 $sql_parts['where'] .= sprintf( "AND ID NOT IN (%s) ", Permalink_Manager_Helper_Functions::prepare_array_for_sql_in( $excluded_posts ) );
292 }
293
294 $sql_parts['end'] = "ORDER BY {$orderby} {$order}";
295
296 list( $all_items, $total_items, $per_page ) = Permalink_Manager_URI_Editor::prepare_sql_query( $sql_parts, $current_page, false );
297
298 $this->set_pagination_args( array(
299 'total_items' => $total_items,
300 'per_page' => $per_page
301 ) );
302
303 $this->_column_headers = array( $columns, $hidden, $sortable );
304 $this->items = $all_items;
305 }
306
307 /**
308 * Define hidden columns
309 *
310 * @return array
311 */
312 public function get_hidden_columns() {
313 return array();
314 }
315
316 /**
317 * Sort the data
318 *
319 * @param mixed $a
320 * @param mixed $b
321 *
322 * @return int
323 */
324 private function sort_data( $a, $b ) {
325 // Set defaults
326 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only WP_List_Table sort column; no state change.
327 $orderby = ( ! empty( $_GET['orderby'] ) ) ? sanitize_sql_orderby( wp_unslash( $_GET['orderby'] ) ) : 'post_title';
328 $order = ( ! empty( $_GET['order'] ) ) ? sanitize_sql_orderby( wp_unslash( $_GET['order'] ) ) : 'asc';
329 $result = strnatcasecmp( $a[ $orderby ], $b[ $orderby ] );
330 // phpcs:enable
331
332 return ( $order === 'asc' ) ? $result : - $result;
333 }
334
335 }
336