PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.26
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.26
3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 2.44 All 141 releases
photonic / admin / Photonic_Shortcode_Usage.php

Photonic_Shortcode_Usage.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 2.26, at admin/Photonic_Shortcode_Usage.php

270 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Generates a table showing the usage of the <code>gallery</code> shortcode for Photonic.
4 * This is used as an interim conversion step for switching shortcodes to a different, non-<code>gallery</code> shortcode.
5 * This is crucial for Gutenberg support, as the "Convert to Blocks" capability of Gutenberg is broken (https://github.com/WordPress/gutenberg/issues/10674).
6 *
7 * @package Photonic
8 * @subpackage Gutenberg
9 * @since 2.10
10 */
11
12 if(!class_exists('WP_List_Table')){
13 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
14 }
15
16 class Photonic_Shortcode_Usage extends WP_List_Table {
17 public $items = array();
18 public $tag;
19 var $per_page = 100;
20
21 public function __construct($args = array()) {
22 parent::__construct(array(
23 'singular' => 'post',
24 'plural' => 'posts',
25 'ajax' => false,
26 ));
27 $this->tag = 'gallery';
28 add_filter('removable_query_args', array(&$this, 'remove_args'));
29 }
30
31 /**
32 * List of columns displayed in the table
33 *
34 * @return array
35 */
36 public function get_columns() {
37 return array(
38 'cb' => '<input type="checkbox" />',
39 'title' => esc_html__('Post Title', 'photonic'),
40 'type' => esc_html__('Post Type', 'photonic'),
41 'status' => esc_html__('Post Status', 'photonic'),
42 'shortcodes' => esc_html__('Gallery Shortcodes used by Photonic', 'photonic'),
43 );
44 }
45
46 /**
47 * List of columns sortable by the user
48 *
49 * @return array
50 */
51 public function get_sortable_columns() {
52 return array(
53 'type' => array('type', true),
54 'title' => array('title', true),
55 'status' => array('status', false),
56 );
57 }
58
59 /**
60 * Main method to build out the list items
61 */
62 public function prepare_items() {
63 $this->_column_headers = array(
64 $this->get_columns(),
65 array(),
66 $this->get_sortable_columns(),
67 'title'
68 );
69
70 $this->process_bulk_action();
71
72 global $wpdb;
73 $results = $wpdb->get_results(
74 "SELECT ID, post_type, post_status, post_title, post_content FROM {$wpdb->posts} where post_type not in ('revision', 'attachment', 'nav_menu_item', 'oembed_cache') and post_status not in ('trash', 'inherit')",
75 ARRAY_A
76 );
77
78 $pattern = get_shortcode_regex(array($this->tag));
79 $types = array('default', 'wp', 'flickr', 'smugmug', 'picasa', 'google', 'zenfolio', 'instagram');
80 $layouts = array('square', 'circle', 'random', 'masonry', 'mosaic', 'strip-above', 'strip-below', 'strip-right', 'no-strip');
81 $data = array();
82
83 foreach ($results as $post) {
84 preg_match_all('/' . $pattern . '/s', $post['post_content'], $matches, PREG_OFFSET_CAPTURE);
85 if (!empty($matches) && !empty($matches[0]) && !empty($matches[1]) && !empty($matches[2]) && !empty($matches[3])) {
86 $to_change = array();
87 foreach ($matches[1] as $instance => $start) {
88 if ($start[0] === '') {
89 if (!empty($matches[3][$instance])) {
90 $attributes = shortcode_parse_atts($matches[3][$instance][0]);
91 if ((!empty($attributes['type']) && in_array($attributes['type'], $types)) ||
92 (empty($attributes['type']) && !empty($attributes['style']) && in_array($attributes['style'], $layouts))) {
93 $to_change[] = "<code>" . esc_html($matches[0][$instance][0]) . "</code>";
94 }
95 }
96 }
97 }
98 if (!empty($to_change)) {
99 $data[] = array(
100 'id' => $post['ID'],
101 'type' => $post['post_type'],
102 'status' => $post['post_status'],
103 'title' => $post['post_title'],
104 'shortcodes' => $to_change,
105 );
106 }
107 }
108 }
109 $current_page = $this->get_pagenum();
110 $total_items = count($data);
111 $data = array_slice($data, (($current_page-1) * $this->per_page), $this->per_page);
112 $this->items = $data;
113 $this->set_pagination_args(array(
114 'total_items' => $total_items,
115 'per_page' => $this->per_page,
116 'total_pages' => ceil($total_items/$this->per_page),
117 ));
118 }
119
120 /**
121 * Default output for a column, if a column-specific output is not defined
122 *
123 * @param object $item
124 * @param string $column_name
125 * @return null|string
126 */
127 protected function column_default($item, $column_name) {
128 return isset($item[$column_name]) ? esc_html($item[$column_name]) : null;
129 }
130
131 /**
132 * Adds the "Checkbox" column for bulk actions
133 *
134 * @param object $item
135 * @return string
136 */
137 protected function column_cb($item) {
138 return sprintf('<input type="checkbox" name="photonic_post[]" value="%s" />', $item['id']);
139 }
140
141 protected function column_title($item) {
142 $actions = array(
143 'edit' => '<a href="' . get_edit_post_link($item['id']) . '">' . esc_html__('Edit', 'photonic') . '</a>',
144 'view' => '<a href="' . get_permalink($item['id']) . '">' . esc_html__('View', 'photonic') . '</a>',
145 'replace_shortcode_individual' => '<a href="'.admin_url('admin.php?page=photonic-gutenberg&action=replace_shortcode_individual&photonic_post_id='.$item['id']).'" class="photonic-shortcode-replace">' . esc_html__('Replace Shortcodes', 'photonic') . '</a>',
146 );
147 return $item['title'] . $this->row_actions($actions);
148 }
149
150 protected function column_shortcodes($item) {
151 return implode("<br/>\n", $item['shortcodes']);
152 }
153
154 public function no_items() {
155 echo sprintf(esc_html__('No instances of Photonic found with the %s shortcode', 'photonic'), "<code>{$this->tag}</code>");
156 }
157
158 function get_bulk_actions() {
159 $actions = array(
160 'replace_shortcode' => esc_html__('Replace Shortcode', 'photonic')
161 );
162 return $actions;
163 }
164
165 function process_bulk_action() {
166 if ('replace_shortcode' === $this->current_action()) {
167 if (!empty($_POST['photonic_post'])) {
168 $post_ids = $_POST['photonic_post'];
169 $post_ids = array_map(function ($v) {
170 return "'" . esc_sql($v) . "'";
171 }, $post_ids);
172 $post_ids = implode(',', $post_ids);
173 }
174 }
175 else if ('replace_shortcode_individual' === $this->current_action()) {
176 if (!empty($_REQUEST['photonic_post_id'])) {
177 $post_ids = esc_sql($_REQUEST['photonic_post_id']);
178 }
179 }
180
181 if (!empty($post_ids)) {
182 global $wpdb, $photonic_alternative_shortcode;
183 if (empty($photonic_alternative_shortcode) || strtolower($photonic_alternative_shortcode) === 'gallery') {
184 echo "<div class='notice notice-error is-dismissible'>\n<p>\n";
185 echo sprintf(esc_html__('Cannot update the posts because a custom shortcode has not been set up under %s.', 'photonic'),
186 '<strong><em>Photonic &rarr; Settings &rarr; Generic Options &rarr; Generic Settings &rarr; Custom Shortcode</em></strong>');
187 echo "\n</p>\n</div>\n";
188 return;
189 }
190
191 $r_tag = $photonic_alternative_shortcode;
192 $o_len = strlen($this->tag);
193 $r_len = strlen($r_tag);
194
195 $results = $wpdb->get_results(
196 "SELECT ID, post_type, post_status, post_title, post_content FROM {$wpdb->posts} where post_type not in ('revision', 'attachment', 'nav_menu_item', 'oembed_cache') and post_status not in ('trash', 'inherit') and ID in (" . $post_ids . ")",
197 ARRAY_A
198 );
199 $pattern = get_shortcode_regex(array($this->tag));
200 $types = array('default', 'wp', 'flickr', 'smugmug', 'picasa', 'google', 'zenfolio', 'instagram');
201 $layouts = array('square', 'circle', 'random', 'masonry', 'mosaic', 'strip-above', 'strip-below', 'strip-right', 'no-strip');
202
203 $count = 0;
204 $got_error = false;
205 foreach ($results as $id => $post) {
206 preg_match_all('/' . $pattern . '/s', $post['post_content'], $matches, PREG_OFFSET_CAPTURE);
207 $changed = false;
208 if (!empty($matches) && !empty($matches[0]) && !empty($matches[1]) && !empty($matches[2]) && !empty($matches[3])) {
209 $instances = array();
210 $init = $post['post_content'];
211 foreach ($matches[1] as $instance => $start) {
212 if ($start[0] === '') {
213 if (!empty($matches[3][$instance])) {
214 $attributes = shortcode_parse_atts($matches[3][$instance][0]);
215 if ((!empty($attributes['type']) && in_array($attributes['type'], $types)) ||
216 (empty($attributes['type']) && !empty($attributes['style']) && in_array($attributes['style'], $layouts))) {
217 $offset = count($instances) * ($r_len - $o_len);
218 $upto = substr($init, 0, $matches[0][$instance][1] + $offset);
219 $instances[] = $instance;
220 $replacement = str_replace('[' . $this->tag, '[' . $r_tag, $matches[0][$instance][0]);
221 $after = substr($init, $matches[0][$instance][1] + $offset + strlen($matches[0][$instance][0]));
222 $init = $upto . $replacement . $after;
223 $changed = true;
224 }
225 }
226 }
227 }
228 if ($changed) {
229 $update = $wpdb->update($wpdb->posts, array('post_content' => $init), array('ID' => $post['ID']));
230 if ($update === false) {
231 $got_error = true;
232 }
233 else if ($update === 0) {
234 }
235 else {
236 $count++;
237 }
238 }
239 }
240 }
241 if ($got_error) {
242 $type = 'error';
243 $message = esc_html__('Failed to replace shortcodes due to an error. Please open a support ticket.', 'photonic');
244 }
245 else if ($count === 0) {
246 $type = 'warning';
247 $message = esc_html__('0 replacements made. If this is not what you were expecting please open a support ticket.', 'photonic');
248 }
249 else {
250 $type = 'success';
251 $message = esc_html(sprintf(_n(
252 '%d post updated with the shortcode replacement.',
253 '%d posts updated with the shortcode replacement.',
254 $count, 'photonic'),
255 $count)
256 );
257 }
258
259 echo "<div class='notice notice-$type is-dismissible'>\n<p>\n";
260 echo $message;
261 echo "\n</p>\n</div>\n";
262 }
263 }
264
265 function remove_args($args) {
266 $args[] = 'action';
267 $args[] = 'photonic_post_id';
268 return $args;
269 }
270 }