PluginProbe
Image Source Control Lite – Show Image Credits and Captions / 3.11.0
Image Source Control Lite – Show Image Credits and Captions v3.11.0
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 3.11.0, at public/public.php

795 lines 24.0 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 }
90 }
91
92 /**
93 * Register our the_content filters
94 */
95 public static function register_the_content_filters() {
96
97 // Content filters need to be above 10 in order to interpret also gallery shortcode
98 // needs to be added to remove_the_content_filters() as well to prevent infinite loops
99 add_filter( 'the_content', [ self::get_instance(), 'add_sources_to_content' ], 20 );
100 }
101
102 /**
103 * Unregister our the_content filters
104 * used in places where we want to prevent infinite loops
105 */
106 public static function remove_the_content_filters() {
107 remove_filter( 'the_content', [ self::get_instance(), 'add_sources_to_content' ], 20 );
108 }
109
110 /**
111 * Get an instance of ISC_Public
112 *
113 * @return ISC_Public|null
114 */
115 public static function get_instance() {
116 if ( null === self::$instance ) {
117 self::$instance = new self();
118 }
119 return self::$instance;
120 }
121
122 /**
123 * Enqueue scripts for the front-end.
124 */
125 public function front_scripts() {
126 // don’t add the script on AMP pages
127 if ( self::is_amp() ) {
128 return;
129 }
130 // inject in footer as we can only reliably position captions when the DOM is fully loaded
131 Helpers::enqueue_script( 'isc_caption', 'public/assets/js/captions.js' );
132
133 $options = $this->get_options();
134
135 $caption_style = [
136 'position' => 'absolute',
137 'font-size' => '0.9em',
138 'background-color' => '#333',
139 'color' => '#fff',
140 'opacity' => '0.70',
141 'padding' => '0 0.15em',
142 'text-shadow' => 'none',
143 'display' => 'block',
144 ];
145
146 $front_data = [
147 'caption_position' => isset( $options['caption_position'] ) ? esc_html( $options['caption_position'] ) : '',
148 /**
149 * Filter: isc_public_caption_default_style
150 * Allows to change the default caption style.
151 *
152 * @param array $caption_style The default caption style.
153 * @param array $options The options array.
154 */
155 'caption_style' => apply_filters( 'isc_public_caption_default_style', $caption_style, $options ),
156 ];
157
158 /**
159 * Filter: isc_public_caption_script_options
160 *
161 * @param array $front_data The data to be localized.
162 * @param array $options The options array.
163 */
164 $filtered_front_data = apply_filters( 'isc_public_caption_script_options', $front_data, $options );
165
166 wp_localize_script(
167 'isc_caption',
168 'isc_front_data',
169 $filtered_front_data
170 );
171 }
172
173 /**
174 * Front-end scripts in <head /> section.
175 */
176 public function front_head() {
177 // don’t add the script on AMP pages
178 if ( self::is_amp() ) {
179 return;
180 }
181
182 $options = $this->get_options();
183 ?>
184 <style>
185 .isc-source { position: relative; display: inline-block; line-height: initial; }
186 /* Hides the caption initially until it is positioned via JavaScript */
187 .isc-source > .isc-source-text { display: none; }
188 .wp-block-cover .isc-source { position: static; }
189 <?php
190 // The 2022 theme adds display:block to the featured image block, which creates additional line breaks. `display: inline` fixes that.
191 ?>
192 span.isc-source-text a { display: inline; color: #fff; }
193 <?php
194 // 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
195 if ( in_array( $options['caption_position'], [ 'top-center', 'top-right', 'center' ], true ) ) {
196 ?>
197 .wp-lightbox-overlay.active .isc-source-text { top: initial !important; left: initial !important; bottom: 0! important; }
198 <?php
199 }
200 ?>
201 </style>
202 <?php
203 }
204
205 /**
206 * Find images in the content, create the index, and maybe add sources to it
207 *
208 * @param string $content post content.
209 * @return string $content
210 */
211 public function add_sources_to_content( $content ) {
212 // 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)
213 if ( empty( $content ) ) {
214 ISC_Log::log( 'skipped adding sources because the content was empty' );
215 return $content;
216 }
217
218 if ( ISC\Indexer::is_global_list_page( $content ) ) {
219 ISC_Log::log( 'skipped adding sources because the content contains the Global List' );
220 return $content;
221 }
222
223 // return if this is not the main query or within the loop
224 if ( ! self::is_main_loop() ) {
225 ISC_Log::log( 'skipped adding sources because the content was loaded outside the main loop' );
226 return $content;
227 }
228
229 if ( ISC_Log::is_type( 'backtrace' ) ) {
230 ISC_Log::log_stack_trace();
231 }
232
233 // maybe add source captions
234 if ( self::captions_enabled() && apply_filters( 'isc_public_add_source_captions_to_content', true ) ) {
235 $content = self::add_source_captions_to_content( $content );
236 } else {
237 ISC_Log::log( 'not creating image overlays because the option is disabled for post content' );
238 }
239
240 /**
241 * Indexing the content for images here after we added overlays, so that we could also count
242 * non-images with overlays
243 */
244 if ( apply_filters( 'isc_update_indexes_in_the_content', true ) ) {
245 \ISC\Indexer::update_indexes( $content );
246 }
247
248 /**
249 * The sources list is rendered after indexing the content for images
250 * since it is build on top of it
251 */
252 // maybe add source list
253 return self::add_source_list_to_content( $content );
254 }
255
256 /**
257 * Check main loop
258 *
259 * @return bool true if we are currently on something that could be called the "main loop"
260 */
261 public static function is_main_loop() {
262
263 // Exception: Oxygen builder, where `is_the_loop()` is false
264 if ( defined( 'CT_VERSION' ) && defined( 'CT_FW_PATH' ) ) {
265 return true;
266 } elseif ( self::is_amp_reader_mode() && is_single() ) {
267 // Exception: AMP reader mode and the AMPforWP plugin need this extra check
268 return true;
269 } elseif ( in_the_loop() && is_main_query() ) {
270 return true;
271 }
272
273 return false;
274 }
275
276 /**
277 * Add captions to post content and include source into caption, if this setting is enabled
278 *
279 * @param string $content post content.
280 * @return string $content
281 */
282 public function add_source_captions_to_content( $content ) {
283 ISC_Log::log( 'start creating source overlays' );
284
285 /**
286 * Split content where `isc_stop_overlay` is found to not display overlays starting there
287 */
288 if ( strpos( $content, 'isc_stop_overlay' ) !== false ) {
289 list( $content, $content_after ) = explode( 'isc_stop_overlay', $content, 2 );
290 } else {
291 $content_after = '';
292 }
293
294 $content = apply_filters( 'isc_public_caption_regex_content', $content );
295 $matches = $this->html_analyzer->extract_images_from_html( $content );
296
297 ISC_Log::log( 'embedded images found: ' . count( $matches ) );
298
299 if ( ! count( $matches ) ) {
300 return $content . $content_after;
301 }
302
303 // gather elements already replaced to prevent duplicate sources, see GitHub #105
304 $replaced = [];
305
306 foreach ( $matches as $_match ) {
307 if ( ! $_match['img_src'] ) {
308 ISC_Log::log( 'skipped an image because src is empty' );
309 continue;
310 }
311 $hash = md5( $_match['inner_code'] );
312
313 if ( in_array( $hash, $replaced, true ) ) {
314 ISC_Log::log( 'skipped an image because it appears multiple times' );
315 continue;
316 } else {
317 $replaced[] = $hash;
318 }
319
320 $id = $this->html_analyzer->extract_image_id( $_match['inner_code'] );
321
322 // if ID is still missing get the image by URL
323 if ( ! $id ) {
324 $id = ISC_Model::get_image_by_url( $_match['img_src'] );
325 ISC_Log::log( sprintf( 'ID for source "%s": "%s"', $_match['img_src'], $id ) );
326 }
327
328 $source = ISC\Image_Sources\Renderer\Caption::get( $id );
329
330 if ( ! $source ) {
331 ISC_Log::log( sprintf( 'skipped empty sources string for ID "%s"', $id ) );
332 continue;
333 }
334
335 // get any alignment from the original code
336 preg_match( '#alignleft|alignright|alignnone|aligncenter#is', $_match['full'], $matches_align );
337 $alignment = $matches_align[0] ?? '';
338 $old_content = $_match['inner_code'];
339 $markup_before = '';
340 $markup_after = '';
341
342 // default style
343 if ( ISC\Image_Sources\Renderer\Caption::has_caption_style() ) {
344 $markup_before = '<span id="isc_attachment_' . $id . '" class="isc-source ' . $alignment . '">';
345 $markup_after = '</span>';
346 }
347
348 $content = str_replace(
349 $old_content,
350 sprintf(
351 '%s%s%s%s',
352 apply_filters( 'isc_overlay_html_markup_before', $markup_before, $id ),
353 str_replace( 'wp-image-' . $id, 'wp-image-' . $id . ' with-source', $old_content ), // new content
354 $source,
355 apply_filters( 'isc_overlay_html_markup_after', $markup_after, $id )
356 ),
357 $content
358 );
359 }
360 ISC_Log::log( 'number of unique images found: ' . count( $replaced ) );
361
362 /**
363 * Attach follow content back
364 */
365 return $content . $content_after;
366 }
367
368 /**
369 * Return true if captions are enabled
370 *
371 * @return bool
372 */
373 public static function captions_enabled(): bool {
374 $options = self::get_instance()->get_options();
375 return ! empty( $options['display_type'] ) && is_array( $options['display_type'] ) && in_array( 'overlay', $options['display_type'], true );
376 }
377
378 /**
379 * Add the Per-page list if the option is enabled
380 *
381 * @param string $content post content.
382 * @return string $content
383 */
384 public function add_source_list_to_content( $content ) {
385
386 /**
387 * Display the Per-page list
388 * on single pages if the following option is enabled: How to display source in Frontend > list below content
389 * on archive pages and home pages with posts if the following option is enabled: Archive Pages > Display sources list below full posts
390 */
391 if ( $this->can_add_list_to_content() ) {
392 ISC_Log::log( 'start creating source list below content' );
393 $content = $content . $this->list_post_attachments_with_sources();
394 }
395
396 return $content;
397 }
398
399 /**
400 * Add image source of featured image to post excerpts
401 *
402 * @param string $excerpt post excerpt.
403 * @return string $excerpt
404 *
405 * @update 1.4.3
406 */
407 public function excerpt_filter( $excerpt ) {
408
409 // display inline sources
410 $options = $this->get_options();
411 $post = get_post();
412
413 if ( empty( $options['list_on_excerpts'] ) ) {
414 return $excerpt;
415 }
416
417 return $excerpt . $this->get_thumbnail_source_string( $post->ID );
418 }
419
420 /**
421 * Add image source of featured image to the post excerpt block in the frontend
422 *
423 * @param string $block_content rendered content of the block.
424 * @param array $block full block details.
425 * @return string $excerpt
426 */
427 public function add_featured_image_source_to_excerpt_block( $block_content, $block ) {
428
429 if ( isset( $block['blockName'] ) && $block['blockName'] !== 'core/post-excerpt' ) {
430 return $block_content;
431 }
432
433 $options = $this->get_options();
434 if ( empty( $options['list_on_excerpts'] ) ) {
435 return $block_content;
436 }
437
438 $post = get_post();
439 if ( ! $post || empty( $post->ID ) ) {
440 return $block_content;
441 }
442
443 return str_replace(
444 '</p></div>',
445 $this->get_thumbnail_source_string( $post->ID ) . '</p></div>',
446 $block_content
447 );
448 }
449
450 /**
451 * Create image sources list for all images of this post
452 *
453 * @since 1.0
454 * @updated 1.1, 1.3.5
455 * @updated 1.5 use new render function to create basic image source string
456 *
457 * @param integer $post_id id of the current post/page.
458 * @return string output
459 */
460 public function list_post_attachments_with_sources( $post_id = 0 ) {
461 global $post;
462
463 if ( empty( $post_id ) && ! empty( $post->ID ) ) {
464 $post_id = $post->ID;
465 }
466
467 if ( isset( $_SERVER['REQUEST_URI'] ) ) {
468 ISC_Log::log( 'enter list_post_attachments_with_sources() for ' . $_SERVER['REQUEST_URI'] . ' and post_id ' . $post_id );
469 }
470
471 // don’t do anything on REST requests since that causes issues with the block editor rendering a "post" for each image
472 // just in case, we also prevent output for "content" from attachments
473 if ( defined( 'REST_REQUEST' ) || ! isset( $post->post_type ) || 'attachment' === $post->post_type ) {
474 ISC_Log::log( 'exit because of invalid request' );
475 return '';
476 }
477
478 // do not render an empty source list on non-post pages unless explicitly stated.
479 if ( empty( $post_id ) ) {
480 /**
481 * Filter: isc_source_list_empty_output
482 * allow to return some output even if there is no post ID (e.g., on archive pages).
483 */
484 return apply_filters( 'isc_source_list_empty_output', '' );
485 }
486
487 // allow developers to override the output of the sources list
488 $override = apply_filters( 'isc_sources_list_override_output', false, $post_id );
489 if ( $override ) {
490 ISC_Log::log( 'exit because override was set' );
491 return $override;
492 }
493
494 $attachments = get_post_meta( $post_id, 'isc_post_images', true );
495 $exclude_standard = Standard_Source::standard_source_is( 'exclude' );
496
497 if ( ! empty( $attachments ) && is_array( $attachments ) ) {
498 ISC_Log::log( sprintf( 'going through %d attachments', count( $attachments ) ) );
499 $atts = [];
500 foreach ( $attachments as $attachment_id => $attachment_array ) {
501 $image_uses_standard_source = Standard_Source::use_standard_source( $attachment_id );
502 $source = ISC\Image_Sources\Image_Sources::sanitize_source_html( self::get_image_source_text_raw( $attachment_id ) );
503
504 // check if source of own images can be displayed
505 if ( ( ! $image_uses_standard_source && $source === '' ) || ( $image_uses_standard_source && $exclude_standard ) ) {
506 if ( $image_uses_standard_source && $exclude_standard ) {
507 ISC_Log::log( sprintf( 'image %d: "own" sources are excluded', $attachment_id ) );
508 } else {
509 ISC_Log::log( sprintf( 'image %d: skipped because of empty source', $attachment_id ) );
510 }
511 unset( $atts[ $attachment_id ] );
512 } else {
513 $atts[ $attachment_id ]['title'] = get_the_title( $attachment_id );
514 ISC_Log::log( sprintf( 'image %d: getting title "%s"', $attachment_id, $atts[ $attachment_id ]['title'] ) );
515 $atts[ $attachment_id ]['source'] = ISC\Image_Sources\Renderer\Image_Source_String::get( $attachment_id );
516 if ( ! $atts[ $attachment_id ]['source'] ) {
517 ISC_Log::log( sprintf( 'image %d: skipped because of empty standard source', $attachment_id ) );
518 unset( $atts[ $attachment_id ] );
519 }
520 }
521 }
522
523 return $this->render_attachments( $atts );
524 } else {
525 // see description above.
526 ISC_Log::log( 'exit without any images found ' );
527 // allow to return result if the source list is empty.
528 return apply_filters( 'isc_source_list_empty_output', '' );
529 }
530 }
531
532 /**
533 * Render attachment list
534 *
535 * @updated 1.3.5
536 * @updated 1.5 removed rendering the license to an earlier function
537 * @param array $attachments array of attachments.
538 * @return string
539 */
540 public function render_attachments( $attachments ) {
541 ISC_Log::log( 'start to render attachments list' );
542
543 // don't display anything, if no image sources displayed
544 if ( $attachments === [] ) {
545 ISC_Log::log( 'exit due to missing attachments' );
546 return '';
547 }
548
549 ob_start();
550
551 ?>
552 <ul class="isc_image_list">
553 <?php
554
555 ISC_Log::log( sprintf( 'start listing %d attachments', count( $attachments ) ) );
556
557 foreach ( $attachments as $atts_id => $atts_array ) {
558 if ( empty( $atts_array['source'] ) ) {
559 ISC_Log::log( sprintf( 'skip image %d because of empty source', $atts_id ) );
560 continue;
561 }
562 echo apply_filters(
563 'isc_source_list_line',
564 sprintf( '<li>%1$s: %2$s</li>', $atts_array['title'], $atts_array['source'] ),
565 $atts_id,
566 $atts_array,
567 $attachments
568 );
569 }
570 ?>
571 </ul>
572 <?php
573 $output = apply_filters( 'isc_source_list', ob_get_clean() );
574
575 return $this->render_image_source_box( $output );
576 }
577
578 /**
579 * Shortcode function to list all image sources of a given page (per-page list)
580 *
581 * @param array $atts attributes.
582 * @return string
583 */
584 public function list_post_attachments_with_sources_shortcode( $atts = [] ) {
585 global $post;
586
587 ISC_Log::log( 'enter for [isc_list] shortcode' );
588
589 // hotfix for https://github.com/webgilde/image-source-control/issues/48 to prevent loops
590 if ( defined( 'REST_REQUEST' ) ) {
591 ISC_Log::log( 'exit due to calling through REST_REQUEST' );
592 return '';
593 }
594
595 $a = shortcode_atts( [ 'id' => 0 ], $atts );
596
597 // if $id not set, use the current ID from the post
598 if ( ! $a['id'] && isset( $post->ID ) ) {
599 $a['id'] = $post->ID;
600 }
601
602 return $this->list_post_attachments_with_sources( $a['id'] );
603 }
604
605 /**
606 * Get source string of a feature image
607 *
608 * @param integer $post_id post object ID.
609 *
610 * @return string source
611 */
612 public function get_thumbnail_source_string( int $post_id = 0 ): string {
613 if ( empty( $post_id ) || ! has_post_thumbnail( $post_id ) ) {
614 return '';
615 }
616
617 $id = get_post_thumbnail_id( $post_id );
618 $source_string = ISC\Image_Sources\Renderer\Caption::get(
619 $id,
620 [],
621 [
622 'prefix' => false,
623 'styled' => false,
624 ]
625 );
626 if ( ! $source_string ) {
627 return '';
628 }
629
630 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>';
631 }
632
633 /**
634 * Load an image source string by url
635 *
636 * @updated 1.5
637 * @deprecated since 1.9
638 * @param string $url url of the image.
639 * @return string
640 */
641 public function get_source_by_url( $url ) {
642 // get the id by the image source
643 $id = ISC_Model::get_image_by_url( $url );
644
645 _deprecated_function( __METHOD__, '1.9.0' );
646
647 return ISC\Image_Sources\Renderer\Image_Source_String::get( $id );
648 }
649
650 /**
651 * Render the image source box
652 * dedicated to displaying an empty box as well so don’t add more visible elements
653 *
654 * @param string $content content of the source box, i.e., list of sources.
655 * @param bool $create_placeholder if true, create a placeholder box without content.
656 */
657 public function render_image_source_box( string $content = '', bool $create_placeholder = false ): string {
658 $options = $this->get_options();
659 $headline = $options['image_list_headline'];
660
661 ob_start();
662 require ISCPATH . 'public/views/image-source-box.php';
663
664 ISC_Log::log( 'finished creating image source box' );
665
666 /**
667 * Filter: isc_render_image_source_box
668 * allow to modify the output of the image source box
669 *
670 * @param string $content content of the source box.
671 * @param string $headline headline of the source box.
672 * @param bool $create_placeholder if true, create a placeholder box without content.
673 */
674 return apply_filters( 'isc_render_image_source_box', ob_get_clean(), $content, $headline, $create_placeholder );
675 }
676
677 /**
678 * Render source string of single image by its id
679 * this only returns the string with source and license (and urls),
680 * but no wrapping, because the string is used in a lot of functions
681 * (e.g. image source list where title is prepended)
682 *
683 * @updated 1.5 wrapped source into source url
684 * @updated 2.4 accept metadata as an argument
685 * @deprecated since 3.0
686 *
687 * @param int|string $id id of the image.
688 * @param string[] $data metadata.
689 * @param array $args arguments
690 * use "disable-links" = (any value), to disable any working links.
691 *
692 * @return bool|string false if no source was given, else string with source
693 */
694 public function render_image_source_string( $id, array $data = [], array $args = [] ) {
695 _deprecated_function( __METHOD__, '3.0.0', 'ISC\Image_Sources\Renderer\Image_Source_String::get' );
696
697 return ISC\Image_Sources\Renderer\Image_Source_String::get( $id, $data, $args );
698 }
699
700 /**
701 * Check if the source list can be added to the content automatically
702 *
703 * @return bool true if the source list can be added to the content
704 */
705 public function can_add_list_to_content() {
706 $options = $this->get_options();
707
708 /**
709 * Tests:
710 * - is list allowed on archive pages?
711 * - automatic injection of the list is enabled
712 */
713 if (
714 (
715 ( is_archive() || is_home() )
716 && isset( $options['list_on_archives'] ) && $options['list_on_archives'] )
717 || ( is_singular() && isset( $options['display_type'] ) && is_array( $options['display_type'] ) && in_array( 'list', $options['display_type'], true ) ) ) {
718 return true;
719 }
720
721 return false;
722 }
723
724 /**
725 * Get image source string for public output
726 *
727 * @depreacted since 3.0
728 *
729 * @param int $attachment_id attachment ID.
730 * @return string
731 */
732 public static function get_image_source_text( $attachment_id ) {
733 _deprecated_function( __METHOD__, '3.0.0', 'ISC\Image_Sources\Image_Source::get_image_source_text' );
734
735 return ISC\Image_Sources\Image_Sources::get_image_source_text( $attachment_id );
736 }
737
738 /**
739 * Are we currently on an AMP URL?
740 *
741 * @return bool true if AMP url, false otherwise
742 */
743 public static function is_amp() {
744 global $pagenow;
745 if ( is_admin()
746 || is_embed()
747 || is_feed()
748 || ( isset( $pagenow ) && in_array( $pagenow, [ 'wp-login.php', 'wp-signup.php', 'wp-activate.php' ], true ) )
749 || ( defined( 'REST_REQUEST' ) && REST_REQUEST )
750 || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
751 ) {
752 return false;
753 }
754
755 if ( ! did_action( 'wp' ) ) {
756 return false;
757 }
758
759 return ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() )
760 || ( function_exists( 'is_wp_amp' ) && is_wp_amp() )
761 || ( function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() )
762 || ( function_exists( 'is_penci_amp' ) && is_penci_amp() )
763 || isset( $_GET ['wpamp'] );
764 }
765
766 /**
767 * Are we currently on a URL using AMP reader mode?
768 * This mode is optional in the official AMP plugin and the only choice in the AMPforWP plugin
769 * in reader mode, the classic WordPress filters are not working
770 *
771 * @return bool true if AMP url, false otherwise
772 */
773 public static function is_amp_reader_mode() {
774 // stop if we are not even on an AMP page
775 if ( ! self::is_amp() ) {
776 return false;
777 }
778
779 // official AMP plugin in reader mode
780 if (
781 class_exists( 'AMP_Options_Manager', false )
782 && AMP_Options_Manager::get_option( 'theme_support' ) === 'reader'
783 ) {
784 return true;
785 }
786
787 // the AMPforWP plugin only uses reader mode since they base on an old version of the AMP plugin where only that one was available
788 if ( function_exists( 'ampforwp_is_amp_endpoint' ) && ampforwp_is_amp_endpoint() ) {
789 return true;
790 }
791
792 return false;
793 }
794 }
795