PluginProbe
Image Source Control Lite – Show Image Credits and Captions / 1.10
Image Source Control Lite – Show Image Credits and Captions v1.10
3.12.0 3.11.0 trunk 1.1 1.1.1 1.1.2 1.1.2.1 1.1.3 1.10 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.2 1.2.0.1 1.2.0.2 1.2.0.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.4.1 1.3.5 All 110 releases
← All changes | public/public.php +653 -688 trunk1.10 View file →
@@ -1,796 +1,761 @@
1 1 <?php
2 +//avoid direct calls to this file
3 +if (!function_exists('add_action')) {
4 + header('Status: 403 Forbidden');
5 + header('HTTP/1.1 403 Forbidden');
6 + exit();
7 +}
8 +if (!class_exists('ISC_Public')) {
2 9
3 -use ISC\Standard_Source;
4 -use ISC\Helpers;
10 + /**
11 + * handles all admin functionalities
12 + *
13 + * @since 1.7
14 + * @todo move frontend-only functions from general class here
15 + */
16 + class ISC_Public extends ISC_Class {
5 17
6 -/**
7 - * Handles all frontend facing functionalities
8 - *
9 - * @todo move frontend-only functions from general class here
10 - */
11 -class ISC_Public extends \ISC\Image_Sources\Image_Sources {
18 + public function __construct() {
19 + parent::__construct();
12 20
13 - /**
14 - * Instance of ISC_Public
15 - *
16 - * @var $instance
17 - */
18 - protected static $instance = null;
21 + add_action('wp_enqueue_scripts', array($this, 'front_scripts'));
22 + add_action('wp_head', array($this, 'front_head'));
19 23
20 - /**
21 - * ISC_Public constructor.
22 - */
23 - public function __construct() {
24 - parent::__construct();
24 + /**
25 + * filters need to be above 10 in order to interpret also gallery shortcode
26 + */
27 + add_filter('the_content', array($this, 'content_filter'), 20);
28 + add_filter('the_excerpt', array($this, 'excerpt_filter'), 20);
29 + add_shortcode('isc_list', array($this, 'list_post_attachments_with_sources_shortcode'));
30 + add_shortcode('isc_list_all', array($this, 'list_all_post_attachments_sources_shortcode'));
31 + }
25 32
26 - add_action( 'wp', [ $this, 'register_hooks' ] );
27 - }
33 + /**
34 + * Enqueue scripts for the front-end.
35 + */
36 + public function front_scripts() {
37 + // inject in footer as we only do stuff after dom-ready
38 + wp_enqueue_script('isc_front_js', plugins_url('/assets/js/front-js.js', __FILE__), array('jquery'), ISCVERSION, true);
39 + }
28 40
29 - /**
30 - * Register hooks after the page is set up so that we have access to the post ID.
31 - */
32 - public function register_hooks() {
33 - // register the shortcode for the global list. Since this shortcode has to be placed manually and is normally only used once, checking if ISC is disabled on cetain pages doesn’t make sense
34 - add_shortcode( 'isc_list_all', [ '\ISC\Image_Sources\Renderer\Global_List', 'execute_shortcode' ] );
41 + /**
42 + * Front-end scripts in <head /> section.
43 + */
44 + public function front_head()
45 + {
46 + $options = $this->get_isc_options();
47 + ?>
48 + <script type="text/javascript">
49 + /* <![CDATA[ */
50 + var isc_front_data =
51 + {
52 + caption_position : '<?php echo $options['caption_position']; ?>',
53 + }
54 + /* ]]> */
55 + </script>
56 + <style>
57 + .isc-source { position: relative; }
58 + </style>
59 + <?php
60 + }
35 61
36 - if ( ! self::can_load_image_sources() ) {
37 - return;
38 - }
62 + /**
63 + * add captions to post content and include source into caption, if this setting is enabled
64 + *
65 + * @param string $content post content
66 + * @return string $content
67 + *
68 + * @update 1.4.3
69 + */
70 + public function content_filter($content)
71 + {
39 72
40 - // prepare the log
41 - $this->prepare_log();
73 + // display inline sources
74 + $options = $this->get_isc_options();
75 + if( isset($options['display_type']) && is_array($options['display_type']) && in_array('overlay', $options['display_type'] ) ) {
76 + /**
77 + * split content where `isc_stop_overlay` is found to not display overlays starting there
78 + */
79 + if( strpos( $content, 'isc_stop_overlay' ) ){
80 + list( $content, $content_after ) = explode( 'isc_stop_overlay', $content, 2 );
81 + } else {
82 + $content_after = '';
83 + }
42 84
43 - if ( ISC\Image_Sources\Renderer\Caption::has_caption_style() ) {
44 - add_action( 'wp_enqueue_scripts', [ $this, 'front_scripts' ] );
45 - add_action( 'wp_head', [ $this, 'front_head' ] );
46 - }
85 + /**
86 + * removed [caption], because this check runs after the hook that interprets shortcodes
87 + * img tag is checked individually since there is a different order of attributes when images are used in gallery or individually
88 + *
89 + * 0 – full match
90 + * 1 - <figure> if set
91 + * 2 – alignment
92 + * 3 – inner code starting with <a>
93 + * 4 – opening link attribute
94 + * 5 – "rel" attribute from link tag
95 + * 6 – image id from link wp-att- value in "rel" attribute
96 + * 7 – full img tag
97 + * 8 – image URL
98 + * 9 – (unused)
99 + * 10 - </figure>
100 + *
101 + * tested with:
102 + * * with and without [caption]
103 + * * with and without link attibute
104 + *
105 + * potential issues:
106 + * * line breaks in the code
107 + */
108 + $pattern = '#(<[^>]*class="[^"]*(alignleft|alignright|alignnone|aligncenter).*)?((<a [^>]*(rel="[^"]*[^"]*wp-att-(\d+)"[^>]*)>)? *(<img [^>]*[^>]*src="(.+)".*\/?>).*(</a>)??[^<]*).*(<\/figure.*>)?#isU';
109 + $count = preg_match_all($pattern, $content, $matches);
47 110
48 - // Content filters need to be above 10 in order to interpret also gallery shortcode
49 - self::register_the_content_filters();
50 - add_filter( 'the_excerpt', [ $this, 'excerpt_filter' ], 20 );
51 - add_filter( 'render_block', [ $this, 'add_featured_image_source_to_excerpt_block' ], 10, 2 );
111 + // error_log(print_r($content, true)); error_log(print_r($matches, true));
112 + if (false !== $count) {
113 + for ($i=0; $i < $count; $i++) {
52 114
53 - add_shortcode( 'isc_list', [ $this, 'list_post_attachments_with_sources_shortcode' ] );
54 - }
115 + /**
116 + * interpret the image tag
117 + *
118 + * we only need the ID if we don’t have it yet
119 + * it can be retrieved from "wp-image-" class (single) or "aria-describedby="gallery-1-34" in gallery
120 + */
121 + $id = $matches[6][$i];
122 + $img_tag = $matches[7][$i];
55 123
56 - /**
57 - * Check if the current frontend page can run ISC properly
58 - *
59 - * @return bool
60 - */
61 - public static function can_load_image_sources() {
124 + if( ! $id ){
125 + $success = preg_match('#wp-image-(\d+)|aria-describedby="gallery-1-(\d+)#is', $img_tag, $matches_id);
126 + if( $success ){
127 + $id = $matches_id[1] ? intval( $matches_id[1] ) : intval( $matches_id[2] );
128 + }
129 + }
62 130
63 - $post_id = get_the_ID();
131 + // if ID is still missing get image by URL
132 + if( ! $id ){
133 + $src = $matches[8][$i];
134 + $id = $this->get_image_by_url($src);
135 + }
64 136
65 - if ( $post_id
66 - && is_singular()
67 - /**
68 - * Filter posts that should not output ISC information by their ID
69 - *
70 - * @param int[] void WP_Post IDs.
71 - */
72 - && in_array( $post_id, apply_filters( 'isc_public_excluded_post_ids', [] ), true ) ) {
73 - return false;
74 - }
137 + // don’t show caption for own image if admin choose not to do so
138 + if($options['exclude_own_images']){
139 + if(get_post_meta($id, 'isc_image_source_own', true)) {
140 + continue;
141 + }
142 + }
75 143
76 - return apply_filters( 'isc_can_load', ISC\Plugin::is_module_enabled( 'image_sources' ) );
77 - }
144 + // don’t display empty sources
145 + if( !$source_string = $this->render_image_source_string( $id ) ) {
146 + continue;
147 + }
78 148
79 - /**
80 - * Prepare the log file
81 - */
82 - public function prepare_log() {
83 - if ( ISC_Log::clear_log() ) {
84 - ISC_Log::delete_log_file();
85 - }
149 + // get any alignment from the original code
150 + preg_match('#alignleft|alignright|alignnone|aligncenter#is', $matches[0][$i], $matches_align);
151 + $alignment = isset( $matches_align[0] ) ? $matches_align[0] : '';
86 152
87 - if ( ISC_Log::enabled() ) {
88 - ISC_Log::log( '---' );
89 - ISC_Log::maybe_log_settings();
90 - }
91 - }
153 + $source = '<span class="isc-source-text">' . $options['source_pretext'] . ' ' . $source_string . '</span>';
154 + $old_content = $matches[3][$i];
155 + $new_content = str_replace('wp-image-' . $id, 'wp-image-' . $id . ' with-source', $old_content);
92 156
93 - /**
94 - * Register our the_content filters
95 - */
96 - public static function register_the_content_filters() {
157 + $content = str_replace($old_content, '<div id="isc_attachment_' . $id . '" class="isc-source ' . $alignment . '"> ' . $new_content . $source . '</div>', $content);
97 158
98 - // Content filters need to be above 10 in order to interpret also gallery shortcode
99 - // needs to be added to remove_the_content_filters() as well to prevent infinite loops
100 - add_filter( 'the_content', [ self::get_instance(), 'add_sources_to_content' ], 20 );
101 - }
159 + }
160 + }
161 + /**
162 + * attach follow content back
163 + */
164 + $content = $content . $content_after;
165 + }
102 166
103 - /**
104 - * Unregister our the_content filters
105 - * used in places where we want to prevent infinite loops
106 - */
107 - public static function remove_the_content_filters() {
108 - remove_filter( 'the_content', [ self::get_instance(), 'add_sources_to_content' ], 20 );
109 - }
167 + // attach image source list to content, if option is enabled
168 + if ((isset($options['list_on_archives']) && $options['list_on_archives']) ||
169 + (is_singular() && isset($options['display_type']) && is_array($options['display_type']) && in_array('list', $options['display_type']))) {
170 + $content = $content . $this->list_post_attachments_with_sources();
171 + }
110 172
111 - /**
112 - * Get an instance of ISC_Public
113 - *
114 - * @return ISC_Public|null
115 - */
116 - public static function get_instance() {
117 - if ( null === self::$instance ) {
118 - self::$instance = new self();
119 - }
120 - return self::$instance;
121 - }
173 + return $content;
174 + }
122 175
123 - /**
124 - * Enqueue scripts for the front-end.
125 - */
126 - public function front_scripts() {
127 - // don’t add the script on AMP pages
128 - if ( self::is_amp() ) {
129 - return;
130 - }
131 - // inject in footer as we can only reliably position captions when the DOM is fully loaded
132 - Helpers::enqueue_script( 'isc_caption', 'public/assets/js/captions.js' );
176 + /**
177 + * add image source of featured image to post excerpts
178 + *
179 + * @param string $excerpt post excerpt
180 + * @return string $excerpt
181 + *
182 + * @update 1.4.3
183 + */
184 + public function excerpt_filter($excerpt)
185 + {
133 186
134 - $options = $this->get_options();
187 + // display inline sources
188 + $options = $this->get_isc_options();
189 + $post = get_post();
135 190
136 - $caption_style = [
137 - 'position' => 'absolute',
138 - 'font-size' => '0.9em',
139 - 'background-color' => '#333',
140 - 'color' => '#fff',
141 - 'opacity' => '0.70',
142 - 'padding' => '0 0.15em',
143 - 'text-shadow' => 'none',
144 - 'display' => 'block',
145 - ];
191 + if (empty($options['list_on_excerpts'])) return $excerpt;
146 192
147 - $front_data = [
148 - 'caption_position' => isset( $options['caption_position'] ) ? esc_html( $options['caption_position'] ) : '',
149 - /**
150 - * Filter: isc_public_caption_default_style
151 - * Allows to change the default caption style.
152 - *
153 - * @param array $caption_style The default caption style.
154 - * @param array $options The options array.
155 - */
156 - 'caption_style' => apply_filters( 'isc_public_caption_default_style', $caption_style, $options ),
157 - ];
193 + $source_string = $this->get_thumbnail_source_string($post->ID);
158 194
159 - /**
160 - * Filter: isc_public_caption_script_options
161 - *
162 - * @param array $front_data The data to be localized.
163 - * @param array $options The options array.
164 - */
165 - $filtered_front_data = apply_filters( 'isc_public_caption_script_options', $front_data, $options );
195 + $excerpt = $excerpt . $source_string;
166 196
167 - wp_localize_script(
168 - 'isc_caption',
169 - 'isc_front_data',
170 - $filtered_front_data
171 - );
172 - }
197 + return $excerpt;
198 + }
173 199
174 - /**
175 - * Front-end scripts in <head /> section.
176 - */
177 - public function front_head() {
178 - // don’t add the script on AMP pages
179 - if ( self::is_amp() ) {
180 - return;
181 - }
200 + /**
201 + * create image sources list for all images of this post
202 + *
203 + * @since 1.0
204 + * @updated 1.1, 1.3.5
205 + * @updated 1.5 use new render function to create basic image source string
206 + *
207 + * @param int $post_id id of the current post/page
208 + * @return echo output
209 + */
210 + public function list_post_attachments_with_sources($post_id = 0)
211 + {
212 + global $post;
213 + if (empty($post_id)) {
214 + if (!empty($post->ID)) {
215 + $post_id = $post->ID;
216 + } else {
217 + return;
218 + }
219 + }
182 220
183 - $options = $this->get_options();
184 - ?>
185 - <style>
186 - .isc-source { position: relative; display: inline-block; line-height: initial; }
187 - .isc-ai-label-icon { display: inline-block; width: auto; height: 1.25em; vertical-align: -0.25em; }
188 - /* Hides the caption initially until it is positioned via JavaScript */
189 - .isc-source > .isc-source-text { display: none; }
190 - .wp-block-cover .isc-source { position: static; }
191 - <?php
192 - // The 2022 theme adds display:block to the featured image block, which creates additional line breaks. `display: inline` fixes that.
193 - ?>
194 - span.isc-source-text a { display: inline; color: #fff; }
195 - <?php
196 - // force the overlay caption into the bottom left corner for lightboxes introduced in WP 6.4; only applied to the positions that are currently broken
197 - if ( in_array( $options['caption_position'], [ 'top-center', 'top-right', 'center' ], true ) ) {
198 - ?>
199 - .wp-lightbox-overlay.active .isc-source-text { top: initial !important; left: initial !important; bottom: 0! important; }
200 - <?php
201 - }
202 - ?>
203 - </style>
204 - <?php
205 - }
221 + $attachments = get_post_meta($post_id, 'isc_post_images', true);
206 222
207 - /**
208 - * Find images in the content, create the index, and maybe add sources to it
209 - *
210 - * @param string $content post content.
211 - * @return string $content
212 - */
213 - public function add_sources_to_content( $content ) {
214 - // return if content is empty or null (the latter being an actual issue on a user’s site likely caused by a third-party plugin using the the_content filter wrongly)
215 - if ( empty( $content ) ) {
216 - ISC_Log::log( 'skipped adding sources because the content was empty' );
217 - return $content;
218 - }
223 + // if attachments is an empty string, search for images in it
224 + if ($attachments == '') {
225 + // unregister our content filter in order to prevent infinite loops when calling the_content in the next steps
226 + remove_filter( 'the_content', array( $this, 'content_filter' ), 20 );
219 227
220 - if ( ISC\Indexer::is_global_list_page( $content ) ) {
221 - ISC_Log::log( 'skipped adding sources because the content contains the Global List' );
222 - return $content;
223 - }
228 + $this->save_image_information_on_load();
229 + $this->update_image_posts_meta($post_id, $post->post_content);
224 230
225 - // return if this is not the main query or within the loop
226 - if ( ! self::is_main_loop() ) {
227 - ISC_Log::log( 'skipped adding sources because the content was loaded outside the main loop' );
228 - return $content;
229 - }
231 + $attachments = get_post_meta($post_id, 'isc_post_images', true);
232 + }
230 233
231 - if ( ISC_Log::is_type( 'backtrace' ) ) {
232 - ISC_Log::log_stack_trace();
233 - }
234 + $return = '';
235 + if (!empty($attachments)) {
236 + $atts = array();
237 + foreach ($attachments as $attachment_id => $attachment_array) {
234 238
235 - // maybe add source captions
236 - if ( self::captions_enabled() && apply_filters( 'isc_public_add_source_captions_to_content', true ) ) {
237 - $content = self::add_source_captions_to_content( $content );
238 - } else {
239 - ISC_Log::log( 'not creating image overlays because the option is disabled for post content' );
240 - }
239 + $own = get_post_meta($attachment_id, 'isc_image_source_own', true);
240 + $source = get_post_meta($attachment_id, 'isc_image_source', true);
241 241
242 - /**
243 - * Indexing the content for images here after we added overlays, so that we could also count
244 - * non-images with overlays
245 - */
246 - if ( apply_filters( 'isc_update_indexes_in_the_content', true ) ) {
247 - \ISC\Indexer::update_indexes( $content );
248 - }
242 + // check if source of own images can be displayed
243 + if ( ($own == '' && $source == '' ) || ($own != '' && $this->_options['exclude_own_images'])) {
244 + unset($atts[$attachment_id]);
245 + continue;
246 + } else {
247 + $atts[$attachment_id]['title'] = get_the_title($attachment_id);
248 + $atts[$attachment_id]['source'] = $this->render_image_source_string($attachment_id);
249 + }
249 250
250 - /**
251 - * The sources list is rendered after indexing the content for images
252 - * since it is build on top of it
253 - */
254 - // maybe add source list
255 - return self::add_source_list_to_content( $content );
256 - }
251 + }
257 252
258 - /**
259 - * Check main loop
260 - *
261 - * @return bool true if we are currently on something that could be called the "main loop"
262 - */
263 - public static function is_main_loop() {
253 + $return = $this->render_attachments($atts);
254 + }
264 255
265 - // Exception: Oxygen builder, where `is_the_loop()` is false
266 - if ( defined( 'CT_VERSION' ) && defined( 'CT_FW_PATH' ) ) {
267 - return true;
268 - } elseif ( self::is_amp_reader_mode() && is_single() ) {
269 - // Exception: AMP reader mode and the AMPforWP plugin need this extra check
270 - return true;
271 - } elseif ( in_the_loop() && is_main_query() ) {
272 - return true;
273 - }
256 + return $return;
257 + }
274 258
275 - return false;
276 - }
259 + /**
260 + * render attachment list
261 + *
262 + * @param array $attachments
263 + * @updated 1.3.5
264 + * @updated 1.5 removed rendering the license to an earlier function
265 + */
266 + protected function render_attachments($attachments)
267 + {
268 + // don't display anything, if no image sources displayed
269 + if ($attachments == array()) {
270 + return ;
271 + }
277 272
278 - /**
279 - * Add captions to post content and include source into caption, if this setting is enabled
280 - *
281 - * @param string $content post content.
282 - * @return string $content
283 - */
284 - public function add_source_captions_to_content( $content ) {
285 - ISC_Log::log( 'start creating source overlays' );
286 273
287 - /**
288 - * Split content where `isc_stop_overlay` is found to not display overlays starting there
289 - */
290 - if ( strpos( $content, 'isc_stop_overlay' ) !== false ) {
291 - list( $content, $content_after ) = explode( 'isc_stop_overlay', $content, 2 );
292 - } else {
293 - $content_after = '';
294 - }
274 + $options = $this->get_isc_options();
295 275
296 - $content = apply_filters( 'isc_public_caption_regex_content', $content );
297 - $matches = $this->html_analyzer->extract_images_from_html( $content );
276 + ob_start();
277 + $headline = $this->_options['image_list_headline'];
278 + ?><div class="isc_image_list_box"><?php
279 + printf('<p class="isc_image_list_title">%1$s</p>', $headline); ?>
280 + <ul class="isc_image_list"><?php
298 281
299 - ISC_Log::log( 'embedded images found: ' . count( $matches ) );
282 + foreach ($attachments as $atts_id => $atts_array) {
283 + if (empty($atts_array['source'])) {
284 + continue;
285 + }
286 + printf('<li>%1$s: %2$s</li>', $atts_array['title'], $atts_array['source']);
287 + }
288 + ?></ul></div><?php
289 + return ob_get_clean();
290 + }
300 291
301 - if ( ! count( $matches ) ) {
302 - return $content . $content_after;
303 - }
292 + /**
293 + * shortcode function to list all image sources
294 + * @param arr $atts
295 + */
296 + public function list_post_attachments_with_sources_shortcode($atts = array())
297 + {
298 + global $post;
299 + extract(shortcode_atts(array('id' => 0), $atts));
304 300
305 - // gather elements already replaced to prevent duplicate sources, see GitHub #105
306 - $replaced = [];
301 + // if $id not set, use the current ID from the post
302 + if (empty($id)) {
303 + $id = $post->ID;
304 + }
307 305
308 - foreach ( $matches as $_match ) {
309 - if ( ! $_match['img_src'] ) {
310 - ISC_Log::log( 'skipped an image because src is empty' );
311 - continue;
312 - }
313 - $hash = md5( $_match['inner_code'] );
306 + if (empty($id)) {
307 + return;
308 + }
309 + return $this->list_post_attachments_with_sources($id);
310 + }
314 311
315 - if ( in_array( $hash, $replaced, true ) ) {
316 - ISC_Log::log( 'skipped an image because it appears multiple times' );
317 - continue;
318 - } else {
319 - $replaced[] = $hash;
320 - }
312 + /**
313 + * create shortcode to list all image sources in the frontend
314 + * @param array $atts
315 + * @since 1.1.3
316 + */
317 + public function list_all_post_attachments_sources_shortcode($atts = array())
318 + {
319 + extract(shortcode_atts(array(
320 + 'per_page' => 99999,
321 + 'before_links' => '',
322 + 'after_links' => '',
323 + 'prev_text' => '&#171; Previous',
324 + 'next_text' => 'Next &#187;',
325 + 'included' => 'displayed'
326 + ),
327 + $atts));
321 328
322 - $id = $this->html_analyzer->extract_image_id( $_match['inner_code'] );
329 + if ('&#171; Previous' == $prev_text)
330 + $prev_text = __('&#171; Previous', 'image-source-control-isc');
331 + if ('Next &#187;' == $next_text)
332 + $next_text = __('Next &#187;', 'image-source-control-isc');
323 333
324 - // if ID is still missing get the image by URL
325 - if ( ! $id ) {
326 - $id = ISC_Model::get_image_by_url( $_match['img_src'] );
327 - ISC_Log::log( sprintf( 'ID for source "%s": "%s"', $_match['img_src'], $id ) );
328 - }
334 + // retrieve all attachments
335 + $args = array(
336 + 'post_type' => 'attachment',
337 + 'numberposts' => -1,
338 + 'post_status' => null,
339 + 'post_parent' => null
340 + );
329 341
330 - $source = ISC\Image_Sources\Renderer\Caption::get( $id );
342 + // check mode
343 + if( $included === 'all' ){
344 + // load all images
331 345
332 - if ( ! $source ) {
333 - ISC_Log::log( sprintf( 'skipped empty sources string for ID "%s"', $id ) );
334 - continue;
335 - }
346 + } else { // load only images attached to posts
347 + $args['meta_query'] = array(
348 + array(
349 + 'key' => 'isc_image_posts',
350 + 'value' => 'a:0:{}',
351 + 'compare' => '!='
352 + )
353 + );
354 + }
336 355
337 - // get any alignment from the original code
338 - preg_match( '#alignleft|alignright|alignnone|aligncenter#is', $_match['full'], $matches_align );
339 - $alignment = $matches_align[0] ?? '';
340 - $old_content = $_match['inner_code'];
341 - $markup_before = '';
342 - $markup_after = '';
356 + $attachments = get_posts($args);
357 + if (empty($attachments)) {
358 + return;
359 + }
343 360
344 - // default style
345 - if ( ISC\Image_Sources\Renderer\Caption::has_caption_style() ) {
346 - $markup_before = '<span id="isc_attachment_' . $id . '" class="isc-source ' . $alignment . '">';
347 - $markup_after = '</span>';
348 - }
361 + $options = $this->get_isc_options();
349 362
350 - $content = str_replace(
351 - $old_content,
352 - sprintf(
353 - '%s%s%s%s',
354 - apply_filters( 'isc_overlay_html_markup_before', $markup_before, $id ),
355 - str_replace( 'wp-image-' . $id, 'wp-image-' . $id . ' with-source', $old_content ), // new content
356 - $source,
357 - apply_filters( 'isc_overlay_html_markup_after', $markup_after, $id )
358 - ),
359 - $content
360 - );
361 - }
362 - ISC_Log::log( 'number of unique images found: ' . count( $replaced ) );
363 + $connected_atts = array();
363 364
364 - /**
365 - * Attach follow content back
366 - */
367 - return $content . $content_after;
368 - }
365 + foreach ($attachments as $_attachment) {
366 + $connected_atts[$_attachment->ID]['source'] = get_post_meta($_attachment->ID, 'isc_image_source', true);
367 + $connected_atts[$_attachment->ID]['own'] = get_post_meta($_attachment->ID, 'isc_image_source_own', true);
368 + // jump to next element if author images are not to be included in the list
369 + if($options['exclude_own_images'] && '' != $connected_atts[$_attachment->ID]['own']) {
370 + unset($connected_atts[$_attachment->ID]);
371 + continue;
372 + }
369 373
370 - /**
371 - * Return true if captions are enabled
372 - *
373 - * @return bool
374 - */
375 - public static function captions_enabled(): bool {
376 - $options = self::get_instance()->get_options();
377 - return ! empty( $options['display_type'] ) && is_array( $options['display_type'] ) && in_array( 'overlay', $options['display_type'], true );
378 - }
374 + $connected_atts[$_attachment->ID]['title'] = $_attachment->post_title;
375 + $connected_atts[$_attachment->ID]['author_name'] = '';
376 + if ('' != $connected_atts[$_attachment->ID]['own']) {
377 + $connected_atts[$_attachment->ID]['author_name'] = get_the_author_meta('display_name', $_attachment->post_author);
378 + }
379 379
380 - /**
381 - * Add the Per-page list if the option is enabled
382 - *
383 - * @param string $content post content.
384 - * @return string $content
385 - */
386 - public function add_source_list_to_content( $content ) {
380 + $metadata = get_post_meta($_attachment->ID, 'isc_image_posts', true);
381 + $usage_data = '';
387 382
388 - /**
389 - * Display the Per-page list
390 - * on single pages if the following option is enabled: How to display source in Frontend > list below content
391 - * on archive pages and home pages with posts if the following option is enabled: Archive Pages > Display sources list below full posts
392 - */
393 - if ( $this->can_add_list_to_content() ) {
394 - ISC_Log::log( 'start creating source list below content' );
395 - $content = $content . $this->list_post_attachments_with_sources();
396 - }
383 + if (is_array($metadata) && array() != $metadata) {
384 + $usage_data .= "<ul style='margin: 0;'>";
385 + $usage_data_array = array();
386 + foreach($metadata as $data) {
387 + // only list published posts
388 + if(get_post_status($data) == 'publish') {
389 + $usage_data_array[] = sprintf(__('<li><a href="%1$s" title="View %2$s">%3$s</a></li>', 'image-source-control-isc'),
390 + esc_url(get_permalink($data)),
391 + esc_attr(get_the_title($data)),
392 + esc_html(get_the_title($data))
393 + );
394 + }
395 + }
396 + if ( 'all' !== $included && $usage_data_array === array() ) {
397 + unset($connected_atts[$_attachment->ID]);
398 + continue;
399 + }
400 + $usage_data .= implode( '', $usage_data_array );
401 + $usage_data .= "</ul>";
402 + }
397 403
398 - return $content;
399 - }
404 + $connected_atts[$_attachment->ID]['posts'] = $usage_data;
405 + }
400 406
401 - /**
402 - * Add image source of featured image to post excerpts
403 - *
404 - * @param string $excerpt post excerpt.
405 - * @return string $excerpt
406 - *
407 - * @update 1.4.3
408 - */
409 - public function excerpt_filter( $excerpt ) {
407 + $total = count($connected_atts);
410 408
411 - // display inline sources
412 - $options = $this->get_options();
413 - $post = get_post();
409 + if (0 == $total)
410 + return;
414 411
415 - if ( empty( $options['list_on_excerpts'] ) ) {
416 - return $excerpt;
417 - }
412 + $page = isset($_GET['isc-page']) ? intval($_GET['isc-page']) : 1;
413 + $down_limit = 1; // First page
418 414
419 - return $excerpt . $this->get_thumbnail_source_string( $post->ID );
420 - }
415 + $up_limit = 1;
421 416
422 - /**
423 - * Add image source of featured image to the post excerpt block in the frontend
424 - *
425 - * @param string $block_content rendered content of the block.
426 - * @param array $block full block details.
427 - * @return string $excerpt
428 - */
429 - public function add_featured_image_source_to_excerpt_block( $block_content, $block ) {
417 + if ($per_page < $total) {
418 + $rem = $total % $per_page; // The Remainder of $total/$per_page
419 + $up_limit = ($total - $rem) / $per_page;
420 + if (0 < $rem) {
421 + $up_limit++; //If rem is positive, add the last page that contains less than $per_page attachment;
422 + }
423 + }
430 424
431 - if ( isset( $block['blockName'] ) && $block['blockName'] !== 'core/post-excerpt' ) {
432 - return $block_content;
433 - }
425 + ob_start();
426 + if ( 2 > $up_limit ) {
427 + $this->display_all_attachment_list($connected_atts);
428 + } else {
429 + $starting_atts = $per_page * ($page - 1); // for page 2 and 3 $per_page start display on $connected_atts[3*(2-1) = 3]
430 + $paged_atts = array_slice($connected_atts, $starting_atts, $per_page, true);
431 + $this->display_all_attachment_list($paged_atts);
432 + $this->pagination_links($up_limit, $before_links, $after_links, $prev_text, $next_text);
433 + }
434 + if (isset($options['webgilde']) && true == $options['webgilde']) {
435 + ?>
436 + <p class="isc-backlink"><?php printf(__('Image list created by <a href="%s" title="Image Source Control">Image Source Control Plugin</a>', 'image-source-control-isc'), WEBGILDE); ?></p>
437 + <?php
438 + }
434 439
435 - $options = $this->get_options();
436 - if ( empty( $options['list_on_excerpts'] ) ) {
437 - return $block_content;
438 - }
440 + $output = ob_get_clean();
441 + return $output;
442 + }
439 443
440 - $post = get_post();
441 - if ( ! $post || empty( $post->ID ) ) {
442 - return $block_content;
443 - }
444 444
445 - return str_replace(
446 - '</p></div>',
447 - $this->get_thumbnail_source_string( $post->ID ) . '</p></div>',
448 - $block_content
449 - );
450 - }
445 + /**
446 + * performs rendering of all attachments list
447 + * @since 1.1.3
448 + * @update 1.5 added new method to get source
449 + */
450 + public function display_all_attachment_list($atts)
451 + {
452 + if (!is_array($atts) || $atts == array())
453 + return;
454 + $options = $this->get_isc_options();
451 455
452 - /**
453 - * Create image sources list for all images of this post
454 - *
455 - * @since 1.0
456 - * @updated 1.1, 1.3.5
457 - * @updated 1.5 use new render function to create basic image source string
458 - *
459 - * @param integer $post_id id of the current post/page.
460 - * @return string output
461 - */
462 - public function list_post_attachments_with_sources( $post_id = 0 ) {
463 - global $post;
456 + /**
457 + * added comment `isc_stop_overlay` as a class to the table to suppress overlays within it starting at that point
458 + * todo: allow overlays to start again after the table
459 + *
460 + */
461 + ?><div class="isc_all_image_list_box isc_stop_overlay">
462 + <table>
463 + <thead>
464 + <?php if ($options['thumbnail_in_list']) : ?>
465 + <th><?php _e('Thumbnail', 'image-source-control-isc'); ?></th>
466 + <?php endif; ?>
467 + <th><?php _e("Attachment's ID", 'image-source-control-isc'); ?></th>
468 + <th><?php _e('Title', 'image-source-control-isc'); ?></th>
469 + <th><?php _e('Attached to', 'image-source-control-isc'); ?></th>
470 + <th><?php _e('Source', 'image-source-control-isc'); ?></th>
471 + </thead>
472 + <tbody>
473 + <?php foreach ($atts as $id => $data) : ?>
474 + <?php
475 + $source = $this->render_image_source_string($id);
476 + ?>
477 + <tr>
478 + <?php
479 + $v_align = '';
480 + if ($options['thumbnail_in_list']) :
481 + $v_align = 'style="vertical-align: top;"';
482 + ?>
483 + <?php if ('custom' != $options['thumbnail_size']) : ?>
484 + <td><?php echo wp_get_attachment_image($id, $options['thumbnail_size']); ?></td>
485 + <?php else : ?>
486 + <td><?php echo wp_get_attachment_image($id, array($options['thumbnail_width'], $options['thumbnail_height'])); ?></td>
487 + <?php endif; ?>
488 + <?php endif; ?>
489 + <td <?php echo $v_align;?>><?php echo $id; ?></td>
490 + <td <?php echo $v_align;?>><?php echo $data['title']; ?></td>
491 + <td <?php echo $v_align;?>><?php echo $data['posts']; ?></td>
492 + <td <?php echo $v_align;?>><?php echo $source; ?></td>
493 + </tr>
494 + <?php endforeach; ?>
495 + </tbody>
496 + </table></div>
497 + <?php
498 + }
464 499
465 - if ( empty( $post_id ) && ! empty( $post->ID ) ) {
466 - $post_id = $post->ID;
467 - }
500 + /**
501 + * Render pagination links, use $before_links and after_links to wrap pagination links inside an additional block
502 + * @param int $max_page total page count
503 + * @param string $before_links optional html to display before pagination links
504 + * @param string $after_links optional html to display after pagination links
505 + * @param string $prev_text text for the previous page link
506 + * @param string $next_text text for the next page link
507 + * @since 1.1.3
508 + *
509 + */
510 + public function pagination_links($max_page, $before_links, $after_links, $prev_text, $next_text)
511 + {
512 + if ((!isset($max_page)) || (!isset($before_links)) || (!isset($after_links)) || (!isset($prev_text)) || (!isset($next_text)))
513 + return;
514 + if (!empty($before_links))
515 + echo $before_links;
516 + ?>
517 + <div class="isc-paginated-links">
518 + <?php
519 + $page = isset($_GET['isc-page']) ? intval($_GET['isc-page']) : 1;
520 + if ($max_page < $page) {
521 + $page = $max_page;
522 + }
523 + if ($page < 1) {
524 + $page = 1;
525 + }
526 + $min_page = 1;
527 + $backward_distance = $page - $min_page;
528 + $forward_distance = $max_page - $page;
468 529
469 - if ( isset( $_SERVER['REQUEST_URI'] ) ) {
470 - ISC_Log::log( 'enter list_post_attachments_with_sources() for ' . $_SERVER['REQUEST_URI'] . ' and post_id ' . $post_id );
471 - }
530 + $page_link = get_page_link();
472 531
473 - // don’t do anything on REST requests since that causes issues with the block editor rendering a "post" for each image
474 - // just in case, we also prevent output for "content" from attachments
475 - if ( defined( 'REST_REQUEST' ) || ! isset( $post->post_type ) || 'attachment' === $post->post_type ) {
476 - ISC_Log::log( 'exit because of invalid request' );
477 - return '';
478 - }
532 + /**
533 + * Remove the query_string of the page_link (?page_id=xyz for the standard permalink structure),
534 + * which is already captured in $_SERVER['QUERY_STRING'].
535 + * @todo replace regex with other value (does WP store the url path without attributes somewhere?
536 + * >get_page_link() returns the permalink but for the default WP permalink structure, the permalink looks like "http://domain.tld/?p=52", while $_GET
537 + * still has a field named 'page_id' with the same value of 52.
538 + */
479 539
480 - // do not render an empty source list on non-post pages unless explicitly stated.
481 - if ( empty( $post_id ) ) {
482 - /**
483 - * Filter: isc_source_list_empty_output
484 - * allow to return some output even if there is no post ID (e.g., on archive pages).
485 - */
486 - return apply_filters( 'isc_source_list_empty_output', '' );
487 - }
540 + $pos = strpos($page_link, '?');
541 + if (false !== $pos) {
542 + $page_link = substr($page_link, 0, $pos);
543 + }
488 544
489 - // allow developers to override the output of the sources list
490 - $override = apply_filters( 'isc_sources_list_override_output', false, $post_id );
491 - if ( $override ) {
492 - ISC_Log::log( 'exit because override was set' );
493 - return $override;
494 - }
545 + /**
546 + * Unset the actual "$_GET['isc-page']" variable (if is set). Pagination variable will be appended to the new query string with a different value for each
547 + * pagination link.
548 + */
495 549
496 - $attachments = get_post_meta( $post_id, 'isc_post_images', true );
497 - $exclude_standard = Standard_Source::standard_source_is( 'exclude' );
550 + if (isset($_GET['isc-page'])) {
551 + unset($_GET['isc-page']);
552 + }
498 553
499 - if ( ! empty( $attachments ) && is_array( $attachments ) ) {
500 - ISC_Log::log( sprintf( 'going through %d attachments', count( $attachments ) ) );
501 - $atts = [];
502 - foreach ( $attachments as $attachment_id => $attachment_array ) {
503 - $image_uses_standard_source = Standard_Source::use_standard_source( $attachment_id );
504 - $source = ISC\Image_Sources\Image_Sources::sanitize_source_html( self::get_image_source_text_raw( $attachment_id ) );
554 + $query_string = http_build_query($_GET);
505 555
506 - // check if source of own images can be displayed
507 - if ( ( ! $image_uses_standard_source && $source === '' ) || ( $image_uses_standard_source && $exclude_standard ) ) {
508 - if ( $image_uses_standard_source && $exclude_standard ) {
509 - ISC_Log::log( sprintf( 'image %d: "own" sources are excluded', $attachment_id ) );
510 - } else {
511 - ISC_Log::log( sprintf( 'image %d: skipped because of empty source', $attachment_id ) );
512 - }
513 - unset( $atts[ $attachment_id ] );
514 - } else {
515 - $atts[ $attachment_id ]['title'] = get_the_title( $attachment_id );
516 - ISC_Log::log( sprintf( 'image %d: getting title "%s"', $attachment_id, $atts[ $attachment_id ]['title'] ) );
517 - $atts[ $attachment_id ]['source'] = ISC\Image_Sources\Renderer\Image_Source_String::get( $attachment_id );
518 - if ( ! $atts[ $attachment_id ]['source'] ) {
519 - ISC_Log::log( sprintf( 'image %d: skipped because of empty source', $attachment_id ) );
520 - unset( $atts[ $attachment_id ] );
521 - }
522 - }
523 - }
556 + $isc_query_tag = '';
557 + if (empty($query_string)) {
558 + $isc_query_tag = '?isc-page=';
559 + } else {
560 + $query_string = '?' . $query_string;
561 + $isc_query_tag = '&isc-page=';
562 + }
524 563
525 - return $this->render_attachments( $atts );
526 - } else {
527 - // see description above.
528 - ISC_Log::log( 'exit without any images found ' );
529 - // allow to return result if the source list is empty.
530 - return apply_filters( 'isc_source_list_empty_output', '' );
531 - }
532 - }
564 + if ($min_page != $page) {
565 + ?>
566 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . ($page-1); ?>" class="prev page-numbers"><?php echo $prev_text; ?></a>
567 + <?php
568 + }
533 569
534 - /**
535 - * Render attachment list
536 - *
537 - * @updated 1.3.5
538 - * @updated 1.5 removed rendering the license to an earlier function
539 - * @param array $attachments array of attachments.
540 - * @return string
541 - */
542 - public function render_attachments( $attachments ) {
543 - ISC_Log::log( 'start to render attachments list' );
570 + if (5 < $max_page) {
544 571
545 - // don't display anything, if no image sources displayed
546 - if ( $attachments === [] ) {
547 - ISC_Log::log( 'exit due to missing attachments' );
548 - return '';
549 - }
572 + if (3 < $backward_distance) {
573 + ?>
574 + <a href="<?php echo $page_link . $query_string . $isc_query_tag; ?>1" class="page-numbers">1</a>
575 + <span class="page-numbers dots">...</span>
576 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . ($page-2);?>" class="page-numbers"><?php echo $page-2; ?></a>
577 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . ($page-1);?>" class="page-numbers"><?php echo $page-1; ?></a>
578 + <span class="page-numbers current"><?php echo $page; ?></span>
579 + <?php
580 + } else {
581 + for ($i = 1; $i <= $page; $i++) {
582 + if ($i == $page) {
583 + ?>
584 + <span class="page-numbers current"><?php echo $i; ?></span>
585 + <?php
586 + } else {
587 + ?>
588 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . $i;?>" class="page-numbers"><?php echo $i; ?></a>
589 + <?php
590 + }
591 + }
592 + }
550 593
551 - ob_start();
594 + if (3 < $forward_distance) {
595 + ?>
596 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . ($page+1);?>" class="page-numbers"><?php echo $page+1; ?></a>
597 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . ($page+2);?>" class="page-numbers"><?php echo $page+2; ?></a>
598 + <span class="page-numbers dots">...</span>
599 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . $max_page;?>" class="page-numbers"><?php echo $max_page; ?></a>
600 + <?php
601 + } else {
602 + for ($i = $page+1; $i <= $max_page; $i++) {
603 + ?>
604 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . $i;?>" class="page-numbers"><?php echo $i; ?></a>
605 + <?php
606 + }
607 + }
608 + } else {
609 + for ($i = 1; $i <= $max_page; $i++) {
610 + if ($i == $page) {
611 + ?>
612 + <span class="page-numbers current"><?php echo $i; ?></span>
613 + <?php
614 + } else {
615 + ?>
616 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . $i;?>" class="page-numbers"><?php echo $i; ?></a>
617 + <?php
618 + }
619 + }
620 + }
621 + if ($page != $max_page) {
622 + ?>
623 + <a href="<?php echo $page_link . $query_string . $isc_query_tag . ($page+1);?>" class="next page-numbers"><?php echo $next_text; ?></a>
624 + <?php
625 + }
626 + ?>
627 + </div>
628 + <?php
629 + echo $after_links;
630 + }
552 631
553 - ?>
554 - <ul class="isc_image_list">
555 - <?php
632 + /**
633 + * get source string of a feature image
634 + *
635 + * @since 1.8
636 + * @param $post_id
637 + * @return source string
638 + */
639 + function get_thumbnail_source_string($post_id = 0){
556 640
557 - ISC_Log::log( sprintf( 'start listing %d attachments', count( $attachments ) ) );
641 + if(empty($post_id)) return '';
558 642
559 - foreach ( $attachments as $atts_id => $atts_array ) {
560 - if ( empty( $atts_array['source'] ) ) {
561 - ISC_Log::log( sprintf( 'skip image %d because of empty source', $atts_id ) );
562 - continue;
563 - }
564 - echo apply_filters(
565 - 'isc_source_list_line',
566 - sprintf( '<li>%1$s: %2$s</li>', $atts_array['title'], $atts_array['source'] ),
567 - $atts_id,
568 - $atts_array,
569 - $attachments
570 - );
571 - }
572 - ?>
573 - </ul>
574 - <?php
575 - $output = apply_filters( 'isc_source_list', ob_get_clean() );
643 + $options = $this->get_isc_options();
576 644
577 - return $this->render_image_source_box( $output );
578 - }
645 + if(has_post_thumbnail($post_id)){
646 + $id = get_post_thumbnail_id($post_id);
647 + $thumb = get_post($post_id);
579 648
580 - /**
581 - * Shortcode function to list all image sources of a given page (per-page list)
582 - *
583 - * @param array $atts attributes.
584 - * @return string
585 - */
586 - public function list_post_attachments_with_sources_shortcode( $atts = [] ) {
587 - global $post;
649 + // don’t show caption for own image if admin choose not to do so
650 + if($options['exclude_own_images']){
651 + if(get_post_meta($id, 'isc_image_source_own', true)) return '';
652 + }
653 + // don’t display empty sources
654 + $src = $thumb->guid;
655 + if(!$source_string = $this->render_image_source_string($id)) return '';
588 656
589 - ISC_Log::log( 'enter for [isc_list] shortcode' );
657 + return '<p class="isc-source-text">' . $options['source_pretext'] . ' ' . $source_string . '</p>';
658 + }
590 659
591 - // hotfix for https://github.com/webgilde/image-source-control/issues/48 to prevent loops
592 - if ( defined( 'REST_REQUEST' ) ) {
593 - ISC_Log::log( 'exit due to calling through REST_REQUEST' );
594 - return '';
595 - }
660 + return '';
661 + }
596 662
597 - $a = shortcode_atts( [ 'id' => 0 ], $atts );
663 + /**
664 + * load an image source string by url
665 + *
666 + * @updated 1.5
667 + * @deprecated since 1.9
668 + * @param string $url url of the image
669 + * @return type
670 + */
671 + public function get_source_by_url($url)
672 + {
673 + // get the id by the image source
674 + $id = $this->get_image_by_url($url);
598 675
599 - // if $id not set, use the current ID from the post
600 - if ( ! $a['id'] && isset( $post->ID ) ) {
601 - $a['id'] = $post->ID;
602 - }
676 + return $this->render_image_source_string($id);
603 677
604 - return $this->list_post_attachments_with_sources( $a['id'] );
605 - }
678 + }
606 679
607 - /**
608 - * Get source string of a feature image
609 - *
610 - * @param integer $post_id post object ID.
611 - *
612 - * @return string source
613 - */
614 - public function get_thumbnail_source_string( int $post_id = 0 ): string {
615 - if ( empty( $post_id ) || ! has_post_thumbnail( $post_id ) ) {
616 - return '';
617 - }
680 + /**
681 + * render source string of single image by its id
682 + * this only returns the string with source and license (and urls),
683 + * but no wrapping, because the string is used in a lot of functions
684 + * (e.g. image source list where title is prepended)
685 + *
686 + * @updated 1.5 wrapped source into source url
687 + *
688 + * @param int $id id of the image
689 + * @return bool|string false if no source was given, else string with source
690 + */
691 + public function render_image_source_string($id){
692 + $id = absint($id);
618 693
619 - $id = get_post_thumbnail_id( $post_id );
620 - $source_string = ISC\Image_Sources\Renderer\Caption::get(
621 - $id,
622 - [],
623 - [
624 - 'prefix' => false,
625 - 'styled' => false,
626 - ]
627 - );
628 - if ( ! $source_string ) {
629 - return '';
630 - }
694 + $options = $this->get_isc_options();
631 695
632 - return '<p class="isc-source-text">' . apply_filters( 'isc_featured_image_source_pre_text', _x( 'Featured image: ', 'label of the featured image source, when displayed below post excerpts', 'image-source-control-isc' ) ) . ' ' . $source_string . '</p>';
633 - }
696 + $metadata['source'] = get_post_meta($id, 'isc_image_source', true);
697 + $metadata['source_url'] = get_post_meta($id, 'isc_image_source_url', true);
698 + $metadata['own'] = get_post_meta($id, 'isc_image_source_own', true);
699 + $metadata['licence'] = get_post_meta($id, 'isc_image_licence', true);
634 700
635 - /**
636 - * Load an image source string by url
637 - *
638 - * @updated 1.5
639 - * @deprecated since 1.9
640 - * @param string $url url of the image.
641 - * @return string
642 - */
643 - public function get_source_by_url( $url ) {
644 - // get the id by the image source
645 - $id = ISC_Model::get_image_by_url( $url );
701 + $source = '';
646 702
647 - _deprecated_function( __METHOD__, '1.9.0' );
703 + $att_post = get_post($id);
648 704
649 - return ISC\Image_Sources\Renderer\Image_Source_String::get( $id );
650 - }
705 + if ('' != $metadata['own']) {
706 + if ($this->_options['use_authorname']) {
707 + if (!empty($att_post)) {
708 + $source = get_the_author_meta('display_name', $att_post->post_author);
709 + }
710 + } else {
711 + $source = $this->_options['by_author_text'];
712 + }
713 + } else {
714 + if ('' != $metadata['source']) {
715 + $source = $metadata['source'];
716 + }
717 + }
651 718
652 - /**
653 - * Render the image source box
654 - * dedicated to displaying an empty box as well so don’t add more visible elements
655 - *
656 - * @param string $content content of the source box, i.e., list of sources.
657 - * @param bool $create_placeholder if true, create a placeholder box without content.
658 - */
659 - public function render_image_source_box( string $content = '', bool $create_placeholder = false ): string {
660 - $options = $this->get_options();
661 - $headline = $options['image_list_headline'];
719 + if($source == '') return false;
662 720
663 - ob_start();
664 - require ISCPATH . 'public/views/image-source-box.php';
721 + // wrap link around source, if given
722 + if('' != $metadata['source_url']){
723 + $source = sprintf('<a href="%2$s" target="_blank" rel="nofollow">%1$s</a>', $source, $metadata['source_url']);
724 + }
665 725
666 - ISC_Log::log( 'finished creating image source box' );
726 + // add license if enabled
727 + if($options['enable_licences'] && isset($metadata['licence']) && $metadata['licence']) {
728 + $licences = $this->licences_text_to_array($options['licences']);
729 + if(isset($licences[$metadata['licence']]['url'])) $licence_url = $licences[$metadata['licence']]['url'];
667 730
668 - /**
669 - * Filter: isc_render_image_source_box
670 - * allow to modify the output of the image source box
671 - *
672 - * @param string $content content of the source box.
673 - * @param string $headline headline of the source box.
674 - * @param bool $create_placeholder if true, create a placeholder box without content.
675 - */
676 - return apply_filters( 'isc_render_image_source_box', ob_get_clean(), $content, $headline, $create_placeholder );
677 - }
731 + if(isset($licence_url) && $licence_url != '') {
732 + $source = sprintf('%1$s | <a href="%3$s" target="_blank" rel="nofollow">%2$s</a>', $source, $metadata['licence'], $licence_url);
733 + } else {
734 + $source = sprintf('%1$s | %2$s', $source, $metadata['licence']);
735 + }
736 + }
678 737
679 - /**
680 - * Render source string of single image by its id
681 - * this only returns the string with source and license (and urls),
682 - * but no wrapping, because the string is used in a lot of functions
683 - * (e.g. image source list where title is prepended)
684 - *
685 - * @updated 1.5 wrapped source into source url
686 - * @updated 2.4 accept metadata as an argument
687 - * @deprecated since 3.0
688 - *
689 - * @param int|string $id id of the image.
690 - * @param string[] $data metadata.
691 - * @param array $args arguments
692 - * use "disable-links" = (any value), to disable any working links.
693 - *
694 - * @return bool|string false if no source was given, else string with source
695 - */
696 - public function render_image_source_string( $id, array $data = [], array $args = [] ) {
697 - _deprecated_function( __METHOD__, '3.0.0', 'ISC\Image_Sources\Renderer\Image_Source_String::get' );
738 + return $source;
739 + }
698 740
699 - return ISC\Image_Sources\Renderer\Image_Source_String::get( $id, $data, $args );
700 - }
741 + /**
742 + * save image information for a post when it is viewed – only called when using isc_list function
743 + * (to help indexing old posts)
744 + *
745 + * @since 1.1
746 + */
747 + public function save_image_information_on_load()
748 + {
749 + global $post;
750 + if (empty($post->ID)) {
751 + return;
752 + }
701 753
702 - /**
703 - * Check if the source list can be added to the content automatically
704 - *
705 - * @return bool true if the source list can be added to the content
706 - */
707 - public function can_add_list_to_content() {
708 - $options = $this->get_options();
754 + $post_id = $post->ID;
755 + $_content = $post->post_content;
709 756
710 - /**
711 - * Tests:
712 - * - is list allowed on archive pages?
713 - * - automatic injection of the list is enabled
714 - */
715 - if (
716 - (
717 - ( is_archive() || is_home() )
718 - && isset( $options['list_on_archives'] ) && $options['list_on_archives'] )
719 - || ( is_singular() && isset( $options['display_type'] ) && is_array( $options['display_type'] ) && in_array( 'list', $options['display_type'], true ) ) ) {
720 - return true;
721 - }
757 + $this->save_image_information($post_id, $_content);
758 + }
722 759
723 - return false;
724 - }
725 -
726 - /**
727 - * Get image source string for public output
728 - *
729 - * @depreacted since 3.0
730 - *
731 - * @param int $attachment_id attachment ID.
732 - * @return string
733 - */
734 - public static function get_image_source_text( $attachment_id ) {
735 - _deprecated_function( __METHOD__, '3.0.0', 'ISC\Image_Sources\Image_Source::get_image_source_text' );
736 -
737 - return ISC\Image_Sources\Image_Sources::get_image_source_text( $attachment_id );
738 - }
739 -
740 - /**
741 - * Are we currently on an AMP URL?
742 - *
743 - * @return bool true if AMP url, false otherwise
744 - */
745 - public static function is_amp() {
746 - global $pagenow;
747 - if ( is_admin()
748 - || is_embed()
749 - || is_feed()
750 - || ( isset( $pagenow ) && in_array( $pagenow, [ 'wp-login.php', 'wp-signup.php', 'wp-activate.php' ], true ) )
751 - || ( defined( 'REST_REQUEST' ) && REST_REQUEST )
752 - || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
753 - ) {
754 - return false;
755 - }
756 -
757 - if ( ! did_action( 'wp' ) ) {
758 - return false;
759 - }
760 -
761 - return ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() )
762 - || ( function_exists( 'is_wp_amp' ) && is_wp_amp() )
763 - || ( function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() )
764 - || ( function_exists( 'is_penci_amp' ) && is_penci_amp() )
765 - || isset( $_GET ['wpamp'] );
766 - }
767 -
768 - /**
769 - * Are we currently on a URL using AMP reader mode?
770 - * This mode is optional in the official AMP plugin and the only choice in the AMPforWP plugin
771 - * in reader mode, the classic WordPress filters are not working
772 - *
773 - * @return bool true if AMP url, false otherwise
774 - */
775 - public static function is_amp_reader_mode() {
776 - // stop if we are not even on an AMP page
777 - if ( ! self::is_amp() ) {
778 - return false;
779 - }
780 -
781 - // official AMP plugin in reader mode
782 - if (
783 - class_exists( 'AMP_Options_Manager', false )
784 - && AMP_Options_Manager::get_option( 'theme_support' ) === 'reader'
785 - ) {
786 - return true;
787 - }
788 -
789 - // the AMPforWP plugin only uses reader mode since they base on an old version of the AMP plugin where only that one was available
790 - if ( function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() ) {
791 - return true;
792 - }
793 -
794 - return false;
795 - }
760 + }
796 761 }