PluginProbe
Image Source Control Lite – Show Image Credits and Captions / trunk
Image Source Control Lite – Show Image Credits and Captions vtrunk
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
image-source-control-isc / public / public.php

public.php in Image Source Control Lite – Show Image Credits and Captions trunk, at public/public.php

797 lines 24.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use ISC\Standard_Source;
4 use ISC\Helpers;
5
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 {
12
13 /**
14 * Instance of ISC_Public
15 *
16 * @var $instance
17 */
18 protected static $instance = null;
19
20 /**
21 * ISC_Public constructor.
22 */
23 public function __construct() {
24 parent::__construct();
25
26 add_action( 'wp', [ $this, 'register_hooks' ] );
27 }
28
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' ] );
35
36 if ( ! self::can_load_image_sources() ) {
37 return;
38 }
39
40 // prepare the log
41 $this->prepare_log();
42
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 }
47
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 );
52
53 add_shortcode( 'isc_list', [ $this, 'list_post_attachments_with_sources_shortcode' ] );
54 }
55
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() {
62
63 $post_id = get_the_ID();
64
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 }
75
76 return apply_filters( 'isc_can_load', ISC\Plugin::is_module_enabled( 'image_sources' ) );
77 }
78
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 }
86
87 if ( ISC_Log::enabled() ) {
88 ISC_Log::log( '---' );
89 ISC_Log::maybe_log_settings();
90 }
91 }
92
93 /**
94 * Register our the_content filters
95 */
96 public static function register_the_content_filters() {
97
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 }
102
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 }
110
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 }
122
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' );
133
134 $options = $this->get_options();
135
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 ];
146
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 ];
158
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 );
166
167 wp_localize_script(
168 'isc_caption',
169 'isc_front_data',
170 $filtered_front_data
171 );
172 }
173
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 }
182
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 }
206
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 }
219
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 }
224
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 }
230
231 if ( ISC_Log::is_type( 'backtrace' ) ) {
232 ISC_Log::log_stack_trace();
233 }
234
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 }
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 }
249
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 }
257
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() {
264
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 }
274
275 return false;
276 }
277
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
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 }
295
296 $content = apply_filters( 'isc_public_caption_regex_content', $content );
297 $matches = $this->html_analyzer->extract_images_from_html( $content );
298
299 ISC_Log::log( 'embedded images found: ' . count( $matches ) );
300
301 if ( ! count( $matches ) ) {
302 return $content . $content_after;
303 }
304
305 // gather elements already replaced to prevent duplicate sources, see GitHub #105
306 $replaced = [];
307
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'] );
314
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 }
321
322 $id = $this->html_analyzer->extract_image_id( $_match['inner_code'] );
323
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 }
329
330 $source = ISC\Image_Sources\Renderer\Caption::get( $id );
331
332 if ( ! $source ) {
333 ISC_Log::log( sprintf( 'skipped empty sources string for ID "%s"', $id ) );
334 continue;
335 }
336
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 = '';
343
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 }
349
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
364 /**
365 * Attach follow content back
366 */
367 return $content . $content_after;
368 }
369
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 }
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 ) {
387
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 }
397
398 return $content;
399 }
400
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 ) {
410
411 // display inline sources
412 $options = $this->get_options();
413 $post = get_post();
414
415 if ( empty( $options['list_on_excerpts'] ) ) {
416 return $excerpt;
417 }
418
419 return $excerpt . $this->get_thumbnail_source_string( $post->ID );
420 }
421
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 ) {
430
431 if ( isset( $block['blockName'] ) && $block['blockName'] !== 'core/post-excerpt' ) {
432 return $block_content;
433 }
434
435 $options = $this->get_options();
436 if ( empty( $options['list_on_excerpts'] ) ) {
437 return $block_content;
438 }
439
440 $post = get_post();
441 if ( ! $post || empty( $post->ID ) ) {
442 return $block_content;
443 }
444
445 return str_replace(
446 '</p></div>',
447 $this->get_thumbnail_source_string( $post->ID ) . '</p></div>',
448 $block_content
449 );
450 }
451
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;
464
465 if ( empty( $post_id ) && ! empty( $post->ID ) ) {
466 $post_id = $post->ID;
467 }
468
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 }
472
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 }
479
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 }
488
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 }
495
496 $attachments = get_post_meta( $post_id, 'isc_post_images', true );
497 $exclude_standard = Standard_Source::standard_source_is( 'exclude' );
498
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 ) );
505
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 }
524
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 }
533
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' );
544
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 }
550
551 ob_start();
552
553 ?>
554 <ul class="isc_image_list">
555 <?php
556
557 ISC_Log::log( sprintf( 'start listing %d attachments', count( $attachments ) ) );
558
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() );
576
577 return $this->render_image_source_box( $output );
578 }
579
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;
588
589 ISC_Log::log( 'enter for [isc_list] shortcode' );
590
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 }
596
597 $a = shortcode_atts( [ 'id' => 0 ], $atts );
598
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 }
603
604 return $this->list_post_attachments_with_sources( $a['id'] );
605 }
606
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 }
618
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 }
631
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 }
634
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 );
646
647 _deprecated_function( __METHOD__, '1.9.0' );
648
649 return ISC\Image_Sources\Renderer\Image_Source_String::get( $id );
650 }
651
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'];
662
663 ob_start();
664 require ISCPATH . 'public/views/image-source-box.php';
665
666 ISC_Log::log( 'finished creating image source box' );
667
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 }
678
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' );
698
699 return ISC\Image_Sources\Renderer\Image_Source_String::get( $id, $data, $args );
700 }
701
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();
709
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 }
722
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 }
796 }
797