├── .gitignore
├── assets
├── icon-128x128.png
├── screenshot-1.png
├── screenshot-2.png
├── screenshot-3.png
├── screenshot-4.png
└── banner-772x250.png
├── todo.txt
├── admin
└── partials
│ ├── image-meta-01.png
│ ├── admin-general-header.php
│ ├── admin-cache-header.php
│ ├── admin-api-header.php
│ └── admin-help-header.php
├── public
├── images
│ ├── cc-attribution.png
│ ├── cc-share-alike.png
│ └── cc-non-commercial.png
├── css
│ └── gga-dynamic-images.css
└── partials
│ └── image-attribution-item.php
├── uninstall.php
├── readme.txt
├── README.md
├── includes
├── class-gga-dynamic-placeholder-images-dashboard-widgets.php
├── class-gga-dynamic-placeholder-images-stats.php
├── class-gga-dynamic-placeholder-images-attachment-meta.php
├── class-gga-dynamic-placeholder-images-api.php
├── class-gga-dynamic-placeholder-images-attribution.php
├── class-gga-dynamic-placeholder-images-cache.php
├── class-gga-dynamic-placeholder-images-settings.php
└── class-gga-dynamic-placeholder-images-core.php
└── gga-dynamic-placeholder-images.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .phpintel
2 |
--------------------------------------------------------------------------------
/assets/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/assets/icon-128x128.png
--------------------------------------------------------------------------------
/assets/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/assets/screenshot-1.png
--------------------------------------------------------------------------------
/assets/screenshot-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/assets/screenshot-2.png
--------------------------------------------------------------------------------
/assets/screenshot-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/assets/screenshot-3.png
--------------------------------------------------------------------------------
/assets/screenshot-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/assets/screenshot-4.png
--------------------------------------------------------------------------------
/assets/banner-772x250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/assets/banner-772x250.png
--------------------------------------------------------------------------------
/todo.txt:
--------------------------------------------------------------------------------
1 | Auto-clean cache directory to prevent it from getting larger than a configured size
2 | Min and max resolution configurable
3 |
--------------------------------------------------------------------------------
/admin/partials/image-meta-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/admin/partials/image-meta-01.png
--------------------------------------------------------------------------------
/public/images/cc-attribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/public/images/cc-attribution.png
--------------------------------------------------------------------------------
/public/images/cc-share-alike.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/public/images/cc-share-alike.png
--------------------------------------------------------------------------------
/public/images/cc-non-commercial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/gga-dynamic-placeholder-images/HEAD/public/images/cc-non-commercial.png
--------------------------------------------------------------------------------
/admin/partials/admin-general-header.php:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/admin/partials/admin-cache-header.php:
--------------------------------------------------------------------------------
1 | dashboard_widget_cache();
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/uninstall.php:
--------------------------------------------------------------------------------
1 | prefix . 'gga_dynamic_images_stats';
15 | $sql = "DROP TABLE IF EXISTS $table_name";
16 | $wpdb->query($sql);
17 |
18 | $sql = "DELETE FROM $wpdb->options WHERE option_name like '_gga-placeholder-image-for%'";
19 | $wpdb->query($sql);
20 |
21 |
22 | flush_rewrite_rules();
23 |
--------------------------------------------------------------------------------
/admin/partials/admin-api-header.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-setting-is-enabled', 'images-api', $this->plugin_name . '-settings-api', 'api-enabled' );
5 | $base_endpoint = apply_filters( $this->plugin_name . '-setting-get', 'images-api', $this->plugin_name . '-settings-api', 'api-endpoint' );
6 |
7 | if ( ! empty( $enabled ) && ! empty( $base_endpoint ) ) {
8 | $url = site_url( trailingslashit( $base_endpoint ) );
9 | }
10 |
11 | ?>
12 |
13 |
14 |
15 |
16 |
:
17 |
18 |
19 |
--------------------------------------------------------------------------------
/public/css/gga-dynamic-images.css:
--------------------------------------------------------------------------------
1 | .gga-dynamic-images-attribution {
2 | margin: auto;
3 | }
4 |
5 | .gga-dynamic-images-attribution .attribImage {
6 | margin-top: 10px;
7 | display: inline-block;
8 | vertical-align: top;
9 | padding: 1%;
10 | width: 100%;
11 | text-align: center;
12 | box-sizing: border-box;
13 | }
14 |
15 | .gga-dynamic-images-attribution .attribImage-inner {
16 | display: inline-block;
17 | }
18 |
19 |
20 | .gga-dynamic-images-attribution .attribImage .image-meta {
21 | text-align: left;
22 | }
23 |
24 |
25 | .gga-dynamic-images-attribution .cc {
26 | display: inline-block;
27 | margin: 0.15em
28 | }
29 |
30 | .gga-dynamic-images-attribution .cc:first-of-type {
31 | margin-left: 0;
32 | }
33 |
34 | .gga-dynamic-images-attribution .cc:last-of-type {
35 | margin-right: 0.5em
36 | }
37 |
38 | .gga-dynamic-images-attribution .some-rights-reserved {
39 | font-size: 0.6em;
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === Dynamic Placeholder Images ===
2 | Contributors: gungeekatx
3 | Tags: images, media
4 | Donate link: http://baconmockup.com
5 | Requires at least: 4.0
6 | Tested up to: 4.9
7 | Stable tag: 2.0.3
8 | License: GPLv2 or later
9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html
10 |
11 | Serve dynamic placeholder images (like baconmockup or placekitten)
12 |
13 | == Description ==
14 |
15 | If you've ever wanted to make your own dynamic placeholder images web site (like [baconmockup](http://baconmockup.com/) or [placekitten](https://placekitten.com/)), this plugin is for you. Once it's installed and you've added some images, you can access them at a URL with the desired height and width. Example: http://baconmockup.com/400/300/
16 |
17 |
18 | Includes:
19 |
20 | * [dynamic-images-attribution] shortcode to display a complete list of images that can be used
21 | * JSON API
22 |
23 | Be sure to check Settings/Dynamic Placeholder images to fully customize your settings.
24 |
25 | View a demo page with my goofy dog: https://petenelson.com/dynamic-clyde-images/
26 |
27 | Thanks to [Kenzie Moss](https://twitter.com/kenziemoss) for the plugin banner and icon.
28 |
29 | == Installation ==
30 |
31 | 1. Upload the gga-dynamic-placeholder-images to the `/wp-content/plugins/` directory
32 | 2. Activate the plugin through the 'Plugins' menu in WordPress
33 | 3. Place the `[dynamic-images-attribution]` shortcode in a page or post
34 | 4. Check Settings/Dynamic Placeholder images to fully customize your settings.
35 |
36 |
37 | == Changelog ==
38 |
39 | = v2.0.3 October 9, 2016 =
40 | * Fixed bug in 404 handling for URLs using specific slugs
41 |
42 | = v2.0.2 March 10, 2015 =
43 | * Fixed bugs in activation hook
44 | * Added deactivation hook to delete image cache
45 | * Updated uninstall hook to remove plugin options
46 |
47 | = v2.0.1 March 8, 2015 =
48 | * Minor updates to the image attribution CSS
49 |
50 | = v2.0.0 March 7, 2015 =
51 | * Initial release to the WordPress repository
52 |
53 |
54 | == Upgrade Notice ==
55 |
56 | = v2.0.3 October 9, 2015 =
57 | * Fixed bug in 404 handling for URLs using specific slugs
58 |
59 |
60 | == Frequently Asked Questions ==
61 |
62 | = Do you have any questions? =
63 | We can answer them here!
64 |
65 |
66 | == Screenshots ==
67 |
68 | 1. Configure your dynamic placeholder image generator
69 | 2. Flag an image to be used as a placeholder image
70 | 3. Sample image
71 | 4. Sample image attributuon grid
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dynamic Placeholder Images
2 | [WordPress plugin](https://wordpress.org/plugins/any-ipsum/) to manage and serve up dynamic placeholder images used by the [baconmockup](http://baconmockup.com/) web site
3 |
4 | [](https://codeclimate.com/github/petenelson/gga-dynamic-placeholder-images)
5 |
6 | ## What's in here?
7 |
8 | - **gga-dynamic-placeholder-images.php** - WordPress plugin wrapper (loades classes, registers core hooks, etc)
9 | - **readme.txt** - Info for the WordPress repo
10 | - **uninstall.php** - WordPress uninstall code
11 | - **admin/partials** - Headers for the plugin settings
12 | - **assets/** - Assets for the WordPress plugin repository
13 | - **lang/** - For future translastions
14 | - **includes/**
15 | - **class-gga-dynamic-placeholder-images-core.php** - Exposes filters used by other classes
16 | - **class-gga-dynamic-placeholder-images-api.php** - API handler
17 | - **class-gga-dynamic-placeholder-images-attachment-meta.php** - Adds meta fields to Media library
18 | - **class-gga-dynamic-placeholder-images-attribution.php** - Handles the [dynamic-images-attribution] shortcode
19 | - **class-gga-dynamic-placeholder-images-cache.php** - Handles caching functions
20 | - **class-gga-dynamic-placeholder-images-dashboard-widgets.php** - Dashboard widget
21 | - **class-gga-dynamic-placeholder-images-settings.php** - Manages plugin settings
22 | - **class-gga-dynamic-placeholder-images-stats.php** - Manages stats logging
23 | - **public/** - CSS and images, and template for the attribution shortcode HTML
24 |
25 |
26 | ## Revision History
27 |
28 | ### v2.0.3 October 9, 2016 =
29 | - Fixed bug in 404 handling for URLs using specific slugs
30 |
31 | ### v2.0.2 March 10, 2015
32 | - Fixed bugs in activation hook
33 | - Added deactivation hook to delete image cache
34 | - Updated uninstall hook to remove plugin options
35 |
36 | ### v2.0.1 March 8, 2015
37 | - Minor updates to the image attribution CSS
38 |
39 | ### v2.0.0 March 7, 2015
40 | - Major rewrite, first release to the WordPress repository
41 |
42 | ### v1.2 March 6, 2013
43 | - Changed most options to autoload=no
44 | - Added textdomain support
45 | - Added admin option to clear associations created between dimensions and images
46 | - Added hook for delete_attachment to clear options assocation with a deleted image
47 |
48 | ### v1.1 March 6, 2013
49 | - Initial Release
50 |
--------------------------------------------------------------------------------
/public/partials/image-attribution-item.php:
--------------------------------------------------------------------------------
1 | ID, $this->meta_prefix . 'attribute_to', true );
6 | $attrib_url = get_post_meta( $gga_image_post->ID, $this->meta_prefix . 'attribute_url', true );
7 |
8 | $cc_url = '';
9 |
10 | if ( 'on' === get_post_meta( $gga_image_post->ID, $this->meta_prefix . 'cc_by', true ) );
11 | $cc_url = 'http://creativecommons.org/licenses/by/2.0/';
12 |
13 | if ( 'on' === get_post_meta( $gga_image_post->ID, $this->meta_prefix . 'cc_sa', true ) );
14 | $cc_url = 'http://creativecommons.org/licenses/by-sa/2.0/';
15 |
16 | $image_url = apply_filters( $this->plugin_name . '-image-url', '', $gga_attrib_args['width'], $gga_attrib_args['height'], $gga_image_post->post_name );
17 | ?>
18 |
19 |
20 |

21 |
39 |
40 |
41 | plugin_name . '-dashboard-widget',
20 | __('Dynamic Placeholder Images', 'gga-dynamic-placeholder-images' ),
21 | array( $this, 'dashboard_widget' )
22 | );
23 |
24 | }
25 |
26 | }
27 |
28 |
29 | public function dashboard_widget() {
30 |
31 | ?>
32 |
33 |
34 | dashboard_widget_cache( $show_help = true ); ?>
35 |
36 |
37 |
38 | plugin_name . '-get-cache-size', 0 ) ) );
44 | if ( empty ( $cache_size ) ) {
45 | $cache_size = __( 'Empty', 'gga-dynamic-placeholder-images' );
46 | }
47 |
48 | $image_associations = number_format( intval( apply_filters( $this->plugin_name . '-get-associations-count', 0 ) ) );
49 |
50 | ?>
51 |
52 |
56 |
57 |
60 |
61 |
62 |
63 |
64 |
67 |
68 | plugin_name . '-action' => $action,
72 | $this->plugin_name . '-nonce' => wp_create_nonce( $action ),
73 | ) );
74 | ?>
75 |
76 |
77 |
78 | plugin_name . '-action' => $action,
82 | $this->plugin_name . '-nonce' => wp_create_nonce( $action ),
83 | ) );
84 | ?>
85 |
86 |
87 |
88 | update_db_check();
15 |
16 | add_action( $this->plugin_name . '-image-view', array( $this, 'log_image_view' ) );
17 |
18 | }
19 |
20 |
21 | public function activation_hook() {
22 | $this->create_stats_table();
23 | }
24 |
25 |
26 | function update_db_check() {
27 |
28 | if ( get_site_option( $this->plugin_name . '-stats-version' ) != $this->version ) {
29 | $this->create_stats_table();
30 | }
31 |
32 | }
33 |
34 |
35 | function stats_table_name() {
36 | global $wpdb;
37 | return $wpdb->prefix . 'gga_dynamic_images_stats';
38 | }
39 |
40 |
41 | function create_stats_table() {
42 | // for reference
43 | // You must put each field on its own line in your SQL statement.
44 | // You must have two spaces between the words PRIMARY KEY and the definition of your primary key.
45 | // You must use the key word KEY rather than its synonym INDEX and you must include at least one KEY.
46 | // You must not use any apostrophes or backticks around field names.
47 | // Field types must be all lowercase.
48 | // SQL keywords, like CREATE TABLE and UPDATE, must be uppercase.
49 |
50 | global $wpdb;
51 | $table_name = $this->stats_table_name();
52 |
53 | $charset_collate = $wpdb->get_charset_collate();
54 |
55 | $sql = "CREATE TABLE $table_name (
56 | id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
57 | time datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
58 | post_id bigint(20) UNSIGNED NOT NULL,
59 | width int(11) UNSIGNED NOT NULL,
60 | height int(11) UNSIGNED NOT NULL,
61 | bytes int(11) UNSIGNED NOT NULL,
62 | PRIMARY KEY (id)
63 | ) $charset_collate;";
64 |
65 | require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
66 | dbDelta( $sql );
67 |
68 | update_site_option( $this->plugin_name . '-stats-version', $this->version );
69 |
70 | }
71 |
72 |
73 | function log_image_view( $args ) {
74 |
75 | $args = wp_parse_args( $args, array(
76 | 'post_id' => 0,
77 | 'width' => 0,
78 | 'height' => 0,
79 | 'bytes' => 0,
80 | ));
81 |
82 | global $wpdb;
83 | $table_name = $this->stats_table_name();
84 |
85 | $wpdb->insert(
86 | $table_name,
87 | array(
88 | 'time' => current_time( 'mysql' ),
89 | 'post_id' => intval( $args['post_id'] ),
90 | 'width' => intval( $args['width'] ),
91 | 'height' => intval( $args['height'] ),
92 | 'bytes' => intval( $args['bytes'] ),
93 | )
94 | );
95 |
96 | $error = $wpdb->last_error;
97 |
98 | if ( strlen( trim( $error ) ) > 0 ) {
99 | $this->create_stats_table();
100 | }
101 |
102 |
103 | }
104 |
105 | }
106 |
107 |
108 | }
--------------------------------------------------------------------------------
/gga-dynamic-placeholder-images.php:
--------------------------------------------------------------------------------
1 | http://baconmockup.com/200/200)
6 | Version: 2.0.3
7 | Author: Pete Nelson (@GunGeekATX)
8 | Author URI: https://twitter.com/GunGeekATX
9 | Text Domain: gga-dynamic-placeholder-images
10 | Domain Path: /lang
11 | */
12 |
13 | if ( ! defined( 'ABSPATH' ) ) die( 'restricted access' );
14 |
15 | $includes = array( 'core', 'cache', 'api', 'attachment-meta', 'settings', 'dashboard-widgets', 'stats', 'attribution' );
16 | foreach ($includes as $include) {
17 | require_once plugin_dir_path( __FILE__ ) . 'includes/class-gga-dynamic-placeholder-images-' . $include . '.php';
18 | }
19 |
20 |
21 | // handles URL rewrites, generating placeholder images, flushing cache, etc
22 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Core' ) ) {
23 | $gga_images_core = new GGA_Dynamic_Placeholder_Images_Core();
24 | $gga_images_core->plugin_base_url = plugin_dir_url( __FILE__ );
25 | add_action( 'plugins_loaded', array( $gga_images_core, 'plugins_loaded' ) );
26 | }
27 |
28 |
29 | // Cache management
30 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Cache' ) ) {
31 | $gga_images_cache = new GGA_Dynamic_Placeholder_Images_Cache();
32 | add_action( 'plugins_loaded', array( $gga_images_cache, 'plugins_loaded' ) );
33 | }
34 |
35 |
36 | // exposes an API endpoint and handles API actions
37 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_API' ) ) {
38 | $gga_images_api = new GGA_Dynamic_Placeholder_Images_API();
39 | add_action( 'plugins_loaded', array( $gga_images_api, 'plugins_loaded' ) );
40 | }
41 |
42 |
43 | // adds meta fields to attachments
44 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Attachment_Meta' ) ) {
45 | $gga_images_meta = new GGA_Dynamic_Placeholder_Images_Attachment_Meta();
46 | $gga_images_meta->plugin_base_url = plugin_dir_url( __FILE__ );
47 | add_action( 'plugins_loaded', array( $gga_images_meta, 'plugins_loaded' ) );
48 | }
49 |
50 |
51 | // handles Admin Settings pages and filters to get plugin settings
52 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Settings' ) ) {
53 | $gga_images_settings = new GGA_Dynamic_Placeholder_Images_Settings();
54 | $gga_images_settings->plugin_base_dir = plugin_dir_path( __FILE__ );
55 | add_action( 'plugins_loaded', array( $gga_images_settings, 'plugins_loaded' ) );
56 | register_activation_hook( __FILE__, array( $gga_images_settings, 'activation_hook' ) );
57 | register_deactivation_hook( __FILE__, array( $gga_images_settings, 'deactivation_hook' ) );
58 | }
59 |
60 |
61 | // Dashboard widgets
62 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Dashboard_Widgets' ) ) {
63 | $gga_images_widgets = new GGA_Dynamic_Placeholder_Images_Dashboard_Widgets();
64 | add_action( 'plugins_loaded', array( $gga_images_widgets, 'plugins_loaded' ) );
65 | }
66 |
67 |
68 | // Stats logging
69 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Stats' ) ) {
70 | $gga_images_stats = new GGA_Dynamic_Placeholder_Images_Stats();
71 | add_action( 'plugins_loaded', array( $gga_images_stats, 'plugins_loaded' ) );
72 | register_activation_hook( __FILE__, array( $gga_images_stats, 'activation_hook' ) );
73 | }
74 |
75 |
76 | // Attribution shortcode
77 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Attribution' ) ) {
78 | $gga_images_attrib = new GGA_Dynamic_Placeholder_Images_Attribution();
79 | $gga_images_attrib->plugin_base_url = plugin_dir_url( __FILE__ );
80 | $gga_images_attrib->plugin_base_dir = plugin_dir_path( __FILE__ );
81 | add_action( 'plugins_loaded', array( $gga_images_attrib, 'plugins_loaded' ) );
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/includes/class-gga-dynamic-placeholder-images-attachment-meta.php:
--------------------------------------------------------------------------------
1 | __( 'Is Dynamic Placeholder Image?', 'gga-dynamic-placeholder-images' ),
20 | 'input' => 'html',
21 | 'html' => $this->checkbox( $post, 'gga_image_is_mockup_image' ),
22 | 'value' => 'on',
23 | );
24 |
25 | $form_fields['gga_image_attribute_to'] =array(
26 | 'label' => __( 'Attribute To', 'gga-dynamic-placeholder-images' ) . ':',
27 | 'value' => get_post_meta( $post->ID, '_gga_image_attribute_to', true ),
28 | );
29 |
30 | $form_fields['gga_image_attribute_url'] =array(
31 | 'label' => __( 'Attribute Url', 'gga-dynamic-placeholder-images' ) . ':',
32 | 'value' => get_post_meta( $post->ID, '_gga_image_attribute_url', true ),
33 | );
34 |
35 | $form_fields['gga_image_cc_by'] =array(
36 | 'label' => __( 'Creative Commons Attribution', 'gga-dynamic-placeholder-images' ) . ':',
37 | 'input' => 'html',
38 | 'html' => $this->checkbox( $post, 'gga_image_cc_by', array( 'append_html' => apply_filters( 'gga-dynamic-images-cc-img-html', '', 'cc_by' ) ) ),
39 | 'value' => 'on',
40 | );
41 |
42 | $form_fields['gga_image_cc_sa'] =array(
43 | 'label' => __( 'Creative Commons Share Alike', 'gga-dynamic-placeholder-images' ) . ':',
44 | 'input' => 'html',
45 | 'html' => $this->checkbox( $post, 'gga_image_cc_sa', array( 'append_html' => apply_filters( 'gga-dynamic-images-cc-img-html', '', 'cc_sa' ) ) ),
46 | 'value' => 'on',
47 | );
48 |
49 | $form_fields['gga_image_cc_nc'] =array(
50 | 'label' => __( 'Creative Commons Non-Commercial', 'gga-dynamic-placeholder-images' ) . ':',
51 | 'input' => 'html',
52 | 'html' => $this->checkbox( $post, 'gga_image_cc_nc', array( 'append_html' => apply_filters( 'gga-dynamic-images-cc-img-html', '', 'cc_nc' ) ) ),
53 | 'value' => 'on',
54 | );
55 |
56 |
57 | return $form_fields;
58 | }
59 |
60 |
61 | function attachment_fields_to_save( $post, $attachment ) {
62 |
63 | $textfields = array( 'gga_image_attribute_to', 'gga_image_attribute_url' );
64 | foreach ( $textfields as $field ) {
65 | if ( isset( $attachment[ $field ] ) ) {
66 | update_post_meta( $post['ID'], '_' . $field, sanitize_text_field( $attachment[ $field ] ) );
67 | }
68 | }
69 |
70 | $checkboxes = array( 'gga_image_is_mockup_image', 'gga_image_cc_by', 'gga_image_cc_sa', 'gga_image_cc_nc' );
71 | foreach ( $checkboxes as $field ) {
72 | if ( !empty ( $attachment[ $field ] ) && $attachment[ $field ] === 'on' ) {
73 | update_post_meta( $post['ID'], '_' . $field, 'on' );
74 | } else {
75 | update_post_meta( $post['ID'], '_' . $field, '' );
76 | }
77 | }
78 |
79 | return $post;
80 |
81 | }
82 |
83 |
84 | private function checkbox( $post, $id, $args = null ) {
85 | $meta_on = get_post_meta( $post->ID, '_' . $id, true ) === 'on';
86 | $checked = $meta_on ? 'checked="checked"' : '';
87 | $args = wp_parse_args( $args, array( 'append_html' => '' ) );
88 | return "" . $args['append_html'];
89 | }
90 |
91 |
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/includes/class-gga-dynamic-placeholder-images-api.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-setting-is-enabled', 'images-api', $this->plugin_name . '-settings-api', 'api-enabled' );
19 | if ( $enabled ) {
20 |
21 | $endpoint = apply_filters( $this->plugin_name . '-setting-get', 'images-api', $this->plugin_name . '-settings-api', 'api-endpoint' );
22 | if ( ! empty ( $endpoint ) ) {
23 | $endpoint .= '/';
24 | }
25 |
26 | add_rewrite_tag( '%gga-image-api-action%', '([A-Za-z0-9\-\_]+)' );
27 | add_rewrite_tag( '%gga-image-api-request%', '1' );
28 |
29 | add_rewrite_rule( $endpoint . '([A-Za-z0-9\-\_]+)/?', 'index.php?gga-image-api-request=1&gga-image-api-action=$matches[1]', 'top' );
30 | add_rewrite_rule( $endpoint . '?', 'index.php?gga-image-api-request=1', 'top' );
31 | }
32 | }
33 |
34 |
35 | function template_redirect() {
36 |
37 | $enabled = apply_filters( $this->plugin_name . '-setting-is-enabled', 'images-api', $this->plugin_name . '-settings-api', 'api-enabled' );
38 | if ( $enabled ) {
39 | global $wp_query;
40 |
41 | if ( $wp_query->get( 'gga-image-api-request' ) === '1' ) {
42 |
43 | $action = $wp_query->get( 'gga-image-api-action' );
44 | $data = null;
45 |
46 | switch ( $action ) {
47 |
48 | case 'image-tags':
49 | $data = $this->image_tags_get();
50 | break;
51 |
52 | default:
53 | $data = $this->endpoint_list_get();
54 | break;
55 | }
56 |
57 |
58 | if ( empty ( $data) ) {
59 | wp_send_json_error();
60 | } else {
61 | wp_send_json_success( $data );
62 | }
63 |
64 | }
65 |
66 |
67 | }
68 |
69 | }
70 |
71 |
72 | private function endpoint_list_get() {
73 |
74 | $results = array();
75 | $base_endpoint = apply_filters( $this->plugin_name . '-setting-get', 'images-api', $this->plugin_name . '-settings-api', 'api-endpoint' );
76 |
77 | $endpoints = array(
78 | 'image-tags' => array(
79 | 'description' => __( 'Returns an array of available image tags', 'gga-dynamic-placeholder-images' ),
80 | ),
81 | );
82 |
83 |
84 | foreach ( $endpoints as $endpoint => $details ) {
85 | $o = new stdClass();
86 | $o->endpoint = $endpoint;
87 | $o->url = trim( site_url( trailingslashit( path_join( $base_endpoint, $endpoint ) ) ) );
88 | $o->details = $details;
89 | $results[] = $o;
90 | }
91 |
92 | return $results;
93 |
94 | }
95 |
96 |
97 | private function image_tags_get() {
98 |
99 | $tags = array();
100 |
101 | $args = array(
102 | 'posts_per_page' => -1,
103 | 'post_type' => 'attachment',
104 | 'post_status' => 'inherit',
105 | 'post_mime_type' => 'image',
106 | 'meta_key' => '_gga_image_is_mockup_image',
107 | 'meta_value' => 'on',
108 | 'orderby' => 'name',
109 | 'order' => 'asc',
110 | 'nopaging' => true,
111 | 'no_found_rows' => true,
112 | 'update_post_meta_cache' => false,
113 | 'update_post_term_cache' => false,
114 | );
115 |
116 |
117 | global $post;
118 | $query = new WP_Query( $args );
119 | while ( $query->have_posts() ) {
120 | $query->the_post();
121 | $tags[] = $post->post_name;
122 | }
123 |
124 | wp_reset_postdata();
125 |
126 | return $tags;
127 |
128 | }
129 |
130 | }
131 |
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/includes/class-gga-dynamic-placeholder-images-attribution.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-cc-img-html', array( $this, 'cc_img_html' ), 10, 2 );
22 |
23 | }
24 |
25 |
26 | public function image_attribution_shortcode( $args ) {
27 |
28 | global $gga_attrib_args;
29 |
30 | wp_enqueue_style( $this->plugin_name . '-attribution', $this->plugin_base_url . 'public/css/gga-dynamic-images.css', array(), $this->version );
31 | $gga_attrib_args = $this->sanitize_args( wp_parse_args( $args, $this->default_shortcode_args() ) );
32 |
33 | ob_start();
34 | ?>
35 |
36 | query_posts( );
38 | $this->echo_attribution_items_html( $posts );
39 | ?>
40 |
41 |
42 | plugin_name . '-attribution-shortcode-html', $html, $posts );
48 | }
49 |
50 |
51 | private function default_shortcode_args() {
52 | return array(
53 | 'width' => 300,
54 | 'height' => 300,
55 | 'columns' => 3,
56 | 'class' => 'gga-dynamic-images-attribution',
57 | );
58 | }
59 |
60 |
61 | private function echo_attribution_items_html( $posts ) {
62 | global $gga_image_post;
63 | foreach( $posts as $gga_image_post ) {
64 | include $this->plugin_base_dir . 'public/partials/image-attribution-item.php';
65 | }
66 | }
67 |
68 |
69 | public function cc_img_html( $html, $cc_type ) {
70 |
71 | $cc_data = array(
72 | 'cc_nc' => array(
73 | 'filename' => 'cc-non-commercial.png',
74 | 'alt' => __( 'Creative Commons Non-Commercial', 'gga-dynamic-placeholder-images' ),
75 | ),
76 | 'cc_by' => array(
77 | 'filename' => 'cc-attribution.png',
78 | 'alt' => __( 'Creative Commons Attribution', 'gga-dynamic-placeholder-images' ),
79 | ),
80 | 'cc_sa' => array(
81 | 'filename' => 'cc-share-alike.png',
82 | 'alt' => __( 'Creative Commons Share Alike', 'gga-dynamic-placeholder-images' ),
83 | ),
84 | );
85 |
86 | if ( ! empty( $cc_data[ $cc_type ] ) ) {
87 | $html = '
';
88 | }
89 |
90 | return $html;
91 | }
92 |
93 |
94 | private function query_posts( ) {
95 | $core = new GGA_Dynamic_Placeholder_Images_Core();
96 |
97 | $query_args = $core->image_query_args();
98 | $query_args['posts_per_page'] = -1;
99 | $query_args['orderby'] = 'name';
100 | $query_args['order'] = 'asc';
101 |
102 | return $core->query_images( $query_args );
103 | }
104 |
105 |
106 | private function sanitize_args( $args ) {
107 |
108 | $int_args = array( 'width', 'height', 'columns' );
109 | foreach ( $int_args as $key ) {
110 | $args[ $key ] = intval( $args[ $key ] );
111 | }
112 |
113 | if ( $args['columns'] < 1 )
114 | $args['columns'] = 1;
115 |
116 | if ( $args['width'] < 1 )
117 | $args['width'] = 1;
118 |
119 | if ( $args['height'] < 1 )
120 | $args['height'] = 1;
121 |
122 | $args['class'] = esc_attr( $args['class'] );
123 |
124 | return $args;
125 |
126 | }
127 |
128 |
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/includes/class-gga-dynamic-placeholder-images-cache.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-get-cache-directory', array( $this, 'get_cache_directory' ) );
14 | add_filter( $this->plugin_name . '-get-cache-directory-contents', array( $this, 'get_cache_directory_contents' ) );
15 | add_filter( $this->plugin_name . '-get-cache-size', array( $this, 'get_cache_directory_size' ) );
16 |
17 | add_action( $this->plugin_name . '-purge-cache', array( $this, 'purge_cache_directory' ) );
18 |
19 | }
20 |
21 |
22 | private function init_filesystem() {
23 | require_once( ABSPATH . 'wp-admin/includes/file.php' );
24 | $access_type = get_filesystem_method();
25 | if( $access_type === 'direct' ) {
26 | $upload_dir = wp_upload_dir();
27 | $creds = request_filesystem_credentials( $upload_dir['url'] );
28 | /* initialize the API */
29 | return WP_Filesystem( $creds );
30 | } else {
31 | return false;
32 | }
33 | }
34 |
35 |
36 | public function get_cache_directory( $cache_directory = '' ) {
37 | $cache_directory = apply_filters( $this->plugin_name . '-setting-get', 'gga-dynamic-placeholder-images', $this->plugin_name . '-settings-cache', 'cache-directory' );
38 | $upload_dir = wp_upload_dir();
39 | $cache_directory = path_join( $upload_dir['basedir'], $cache_directory );
40 | return $cache_directory;
41 | }
42 |
43 |
44 | public function get_cache_directory_contents( $contents = false ) {
45 | if ( $this->init_filesystem() ) {
46 | $cache_directory = $this->get_cache_directory();
47 | global $wp_filesystem;
48 | $contents = $wp_filesystem->dirlist( $cache_directory, false, true );
49 | }
50 | return $contents;
51 | }
52 |
53 |
54 | public function get_cache_directory_size( $size ) {
55 | $transient = $this->plugin_name . '-cache-size';
56 | $size = get_site_transient( $transient );
57 | if ( ! empty( $size ) ) {
58 | return $size;
59 | }
60 |
61 | $list = $this->get_cache_directory_contents();
62 | if ( ! empty( $list ) ) {
63 | $size = $this->get_directory_size( $list );
64 | set_site_transient( $transient, $size, MINUTE_IN_SECONDS * 15 );
65 | return $size;
66 | } else {
67 | return $size;
68 | }
69 |
70 | }
71 |
72 |
73 | public function purge_cache_directory() {
74 | if ( $this->delete_cache_directory() ) {
75 | return $this->create_cache_directory();
76 | }
77 | else {
78 | return false;
79 | }
80 | }
81 |
82 |
83 | private function create_cache_directory() {
84 | $cache_directory = $this->get_cache_directory();
85 | if ( wp_mkdir_p( $cache_directory ) ) {
86 | foreach( $this->cache_width_directories() as $width ) {
87 | $this->create_cache_width_directory( $cache_directory, $width );
88 | }
89 | }
90 |
91 | }
92 |
93 |
94 | private function create_cache_width_directory( $base_cache_directory, $width ) {
95 | wp_mkdir_p( path_join( $base_cache_directory, $width ) );
96 | }
97 |
98 |
99 | public function delete_cache_directory() {
100 |
101 | if ( $this->init_filesystem() ) {
102 | global $wp_filesystem;
103 | $cache_directory = $this->get_cache_directory();
104 | delete_site_transient( $this->plugin_name . '-cache-size' );
105 | return $wp_filesystem->rmdir( $cache_directory, true );
106 | } else {
107 | return false;
108 | }
109 |
110 | }
111 |
112 |
113 | private function get_directory_size( $list ) {
114 | $size = 0;
115 |
116 | if ( ! empty( $list ) ) {
117 |
118 | foreach ($list as $key => $item) {
119 | if ( $item['type'] == 'f' ) {
120 | $size += $item['size'];
121 | } else if ( $item['type'] == 'd' && ! empty( $item['files'] ) ) {
122 | $size += $this->get_directory_size( $item['files'] );
123 | }
124 | }
125 |
126 | }
127 |
128 | return $size;
129 | }
130 |
131 |
132 | private function cache_width_directories() {
133 | $widths = array();
134 | for ( $width = 0; $width <= 2000; $width += 100 ) {
135 | $widths[] = $width;
136 | }
137 | return $widths;
138 | }
139 |
140 |
141 |
142 | }
143 |
144 | }
--------------------------------------------------------------------------------
/admin/partials/admin-help-header.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-setting-is-enabled', 'images-api', $this->plugin_name . '-settings-api', 'api-enabled' );
5 | $base_endpoint = apply_filters( $this->plugin_name . '-setting-get', 'images-api', $this->plugin_name . '-settings-api', 'api-endpoint' );
6 |
7 | if ( ! empty( $enabled ) && ! empty( $base_endpoint ) ) {
8 | $url = site_url( trailingslashit( $base_endpoint ) );
9 | }
10 |
11 |
12 | ?>
13 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | : [dynamic-images-attribution]
43 |
44 |
45 |
46 | columns -
47 | width -
48 | height -
49 | class -
50 |
51 | : [dynamic-images-attribution columns=4 width=200 height=200 class='my-image-attributions']
52 |
53 |
54 |
55 |
56 |
57 | gga-dynamic-placeholder-images folder in the uploads folder.', 'gga-dynamic-placeholder-images' ) ?>
58 |
59 | Cache tab to clear up disk space.', 'gga-dynamic-placeholder-images' ), admin_url( 'options-general.php?page=gga-dynamic-images-settings&tab=gga-dynamic-images-settings-cache' ) ) ?>
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | -
72 | gga-dynamic-images-image-url:
73 |
74 | :
75 |
76 | - $url -
77 | - $width -
78 | - $height -
79 | - $tag -
80 |
81 | $url = apply_filters( 'gga-dynamic-images-image-url', '', 300, 400 );
82 |
83 |
84 | -
85 | gga-dynamic-images-attribution-shortcode-html:
86 |
87 | :
88 |
89 | - $html -
90 | - $posts -
91 |
92 |
93 | add_filter( 'gga-dynamic-images-attribution-shortcode-html', 'my_attribution_html', 10, 2 );
94 | function my_attribution_html( $html, $posts ) {
95 | // generate your own custom HTML here
96 | return $html;
97 | }
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | : pete@petenelson.com
108 | : @GunGeekATX
109 | : https://github.com/petenelson/gga-dynamic-placeholder-images
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/includes/class-gga-dynamic-placeholder-images-settings.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-setting-is-enabled', array( $this, 'setting_is_enabled' ), 10, 3 );
24 | add_filter( $this->plugin_name . '-setting-get', array( $this, 'setting_get' ), 10, 3 );
25 |
26 | // admin menus
27 | if ( is_admin() ) {
28 | $this->handle_admin_actions();
29 | add_action( 'admin_init', array( $this, 'admin_init' ) );
30 | add_action( 'admin_menu', array( $this, 'admin_menu' ) );
31 | add_action( 'admin_notices', array( $this, 'activation_admin_notice' ) );
32 | }
33 |
34 | }
35 |
36 |
37 | private function get_request( $key, $default = '', $filter = FILTER_SANITIZE_STRING ) {
38 | return GGA_Dynamic_Placeholder_Images_Core::get_request( $key, $default, $filter );
39 | }
40 |
41 |
42 | public function activation_hook() {
43 |
44 | // create default settings
45 | add_option( $this->settings_key_general, array(
46 | 'name' => 'Dynamic Images',
47 | 'base-url' => 'dynamic-images',
48 | ), '', $autoload = 'no' );
49 |
50 | add_option( $this->settings_key_api, array(
51 | 'api-enabled' => '0',
52 | 'api-endpoint' => 'images-api',
53 | ), '', $autoload = 'no' );
54 |
55 |
56 | // add an option so we can show the activated admin notice
57 | add_option( $this->plugin_name . '-plugin-activated', '1' );
58 |
59 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Core' ) ) {
60 | $core = new GGA_Dynamic_Placeholder_Images_Core();
61 | $core->register_rewrites( 'dynamic-images/' );
62 | }
63 |
64 | flush_rewrite_rules( );
65 |
66 | }
67 |
68 |
69 | public function deactivation_hook() {
70 | if ( class_exists( 'GGA_Dynamic_Placeholder_Images_Cache' ) ) {
71 | $cache = new GGA_Dynamic_Placeholder_Images_Cache();
72 | $cache->delete_cache_directory();
73 | }
74 | }
75 |
76 |
77 | function activation_admin_notice() {
78 | if ( '1' === get_option( $this->plugin_name . '-plugin-activated' ) ) {
79 | ?>
80 |
81 |
Dynamic Placeholder Images activated! Please visit the Settings page to customize your image generator.', 'gga-dynamic-placeholder-images' ), admin_url( 'options-general.php?page=' . $this->plugin_name . '-settings' ) );
83 | ?>
84 |
85 | plugin_name . '-plugin-activated' );
87 | }
88 | }
89 |
90 |
91 | function handle_admin_action_notices() {
92 | global $gga_dynamic_images_admin_notice;
93 | if ( ! empty( $gga_dynamic_images_admin_notice ) ) {
94 | ?>
95 |
98 | get_request( $this->plugin_name . '-action' );
106 | $nonce = $this->get_request( $this->plugin_name . '-nonce' );
107 | if ( ! empty( $action ) && current_user_can( 'manage_options' ) && wp_verify_nonce( $nonce, $action ) ) {
108 |
109 | global $gga_dynamic_images_admin_notice;
110 |
111 | switch ( $action ) {
112 | case 'purge-cache':
113 | do_action( $this->plugin_name . '-purge-cache' );
114 | $gga_dynamic_images_admin_notice = __( 'Cache Purged', 'gga-dynamic-placeholder-images' );
115 | break;
116 | case 'delete-associations':
117 | do_action( $this->plugin_name . '-delete-associations' );
118 | $gga_dynamic_images_admin_notice = __( 'Image Associations Deleted', 'gga-dynamic-placeholder-images' );
119 | break;
120 | }
121 |
122 | add_action( 'admin_notices', array( $this, 'handle_admin_action_notices' ) );
123 |
124 | }
125 |
126 | }
127 |
128 |
129 | function admin_init() {
130 | $this->register_general_settings();
131 | $this->register_api_settings();
132 | $this->register_cache_settings();
133 | $this->register_help_tab();
134 | }
135 |
136 |
137 | function register_general_settings() {
138 | $key = $this->settings_key_general;
139 | $this->plugin_settings_tabs[$key] = __( 'General', 'gga-dynamic-placeholder-images' );
140 |
141 | register_setting( $key, $key, array( $this, 'general_settings_sanitize' ) );
142 |
143 | $section = 'general';
144 |
145 | add_settings_section( $section, '', array( $this, 'section_header' ), $key );
146 |
147 | $permalink_structure = get_option( 'permalink_structure' );
148 | $permalink_warning = empty($permalink_structure) ? ' (please anable any non-default Permalink structure)' : '';
149 |
150 | /*
151 | add_settings_field( 'name', __( 'Your Dynamic Placholder Name', 'gga-dynamic-placeholder-images'), array( $this, 'settings_input' ), $key, $section,
152 | array('key' => $key, 'name' => 'name', 'size' => 20, 'maxlength' => 50, 'after' => 'Example: Bacon Mockup, Place Kitten'));
153 | */
154 |
155 |
156 | $after = __( 'Example: dynamic-images (ex: /dynamic-images/300/300/) or leave blank to operate at the root of your site.
NOTE: A blank URL may prevent other numeric-based URLs from working. Use with caution.', 'gga-dynamic-placeholder-images' ) . $permalink_warning;
157 |
158 | add_settings_field( 'base-url', __( 'Base URL', 'gga-dynamic-placeholder-images' ), array( $this, 'settings_input' ), $key, $section,
159 | array('key' => $key, 'name' => 'base-url', 'size' => 20, 'maxlength' => 50, 'after' => $after));
160 |
161 | }
162 |
163 |
164 | function general_settings_sanitize( $settings ) {
165 |
166 | if ( isset( $settings['base-url'] ) ) {
167 | $settings['base-url'] = sanitize_key( $settings['base-url'] );
168 | }
169 |
170 | return $settings;
171 | }
172 |
173 |
174 | function register_api_settings() {
175 | $key = $this->settings_key_api;
176 | $this->plugin_settings_tabs[$key] = __('API', 'gga-dynamic-placeholder-images');
177 |
178 | register_setting( $key, $key, array( $this, 'api_settings_sanitize') );
179 |
180 | $section = 'api';
181 |
182 | add_settings_section( $section, '', array( $this, 'section_header' ), $key );
183 |
184 | add_settings_field( 'api-enabled', __('Enabled', 'gga-dynamic-placeholder-images'), array( $this, 'settings_yes_no' ), $key, $section,
185 | array('key' => $key, 'name' => 'api-enabled'));
186 |
187 | $permalink_structure = get_option( 'permalink_structure' );
188 | $permalink_warning = empty($permalink_structure) ? ' (please anable any non-default Permalink structure)' : '';
189 |
190 | add_settings_field( 'api-endpoint', __('Endpoint Page Name', 'gga-dynamic-placeholder-images'), array( $this, 'settings_input' ), $key, $section,
191 | array('key' => $key, 'name' => 'api-endpoint', 'size' => 20, 'maxlength' => 50, 'after' => 'Example: images-api, bacon-images-api, etc' . $permalink_warning));
192 |
193 | }
194 |
195 |
196 | function api_settings_sanitize( $settings ) {
197 |
198 | if ( isset( $settings['api-endpoint'] ) ) {
199 | $settings['api-endpoint'] = sanitize_key( $settings['api-endpoint'] );
200 | }
201 |
202 | return $settings;
203 | }
204 |
205 |
206 | function register_cache_settings() {
207 | $key = $this->settings_key_cache;
208 | $this->plugin_settings_tabs[$key] = __( 'Cache', 'gga-dynamic-placeholder-images' );
209 |
210 | register_setting( $key, $key );
211 |
212 | $section = 'cache';
213 |
214 | add_settings_section( $section, '', array( $this, 'section_header' ), $key );
215 |
216 | }
217 |
218 |
219 | function register_help_tab() {
220 | $key = $this->settings_key_help;
221 | $this->plugin_settings_tabs[$key] = __('Help', 'gga-dynamic-placeholder-images');
222 |
223 | register_setting( $key, $key );
224 |
225 | $section = 'help';
226 |
227 | add_settings_section( $section, '', array( $this, 'section_header' ), $key );
228 |
229 | }
230 |
231 |
232 | function setting_is_enabled( $enabled, $key, $setting ) {
233 | return '1' === $this->setting_get('0', $key, $setting);
234 | }
235 |
236 |
237 | function setting_get( $value, $key, $setting ) {
238 |
239 | $args = wp_parse_args( get_option($key),
240 | array(
241 | $setting => $value,
242 | )
243 | );
244 |
245 | return $args[ $setting ];
246 | }
247 |
248 |
249 | function settings_input($args) {
250 |
251 | $args = wp_parse_args( $args,
252 | array(
253 | 'name' => '',
254 | 'key' => '',
255 | 'maxlength' => 50,
256 | 'size' => 30,
257 | 'after' => '',
258 | )
259 | );
260 |
261 |
262 | $name = $args['name'];
263 | $key = $args['key'];
264 | $size = $args['size'];
265 | $maxlength = $args['maxlength'];
266 |
267 | $option = get_option($key);
268 | $value = isset($option[$name]) ? esc_attr($option[$name]) : '';
269 |
270 | echo "";
271 | if (!empty($args['after']))
272 | echo '' . __($args['after'], 'gga-dynamic-placeholder-images') . '
';
273 |
274 | }
275 |
276 |
277 | function settings_textarea($args) {
278 |
279 | $args = wp_parse_args( $args,
280 | array(
281 | 'name' => '',
282 | 'key' => '',
283 | 'rows' => 10,
284 | 'cols' => 40,
285 | 'after' => '',
286 | )
287 | );
288 |
289 |
290 | $name = $args['name'];
291 | $key = $args['key'];
292 | $rows = $args['rows'];
293 | $cols = $args['cols'];
294 |
295 | $option = get_option($key);
296 | $value = isset($option[$name]) ? esc_attr($option[$name]) : '';
297 |
298 | echo "";
299 | if (!empty($args['after']))
300 | echo '' . $args['after'] . '
';
301 |
302 | }
303 |
304 |
305 | function settings_yes_no($args) {
306 |
307 | $args = wp_parse_args( $args,
308 | array(
309 | 'name' => '',
310 | 'key' => '',
311 | 'after' => '',
312 | )
313 | );
314 |
315 | $name = $args['name'];
316 | $key = $args['key'];
317 |
318 | $option = get_option($key);
319 | $value = isset($option[$name]) ? esc_attr($option[$name]) : '';
320 |
321 | if (empty($value))
322 | $value = '0';
323 |
324 | echo '';
325 | echo " ";
326 | echo " ";
327 | echo '
';
328 |
329 | if (!empty($args['after']))
330 | echo '' . __($args['after'], 'gga-dynamic-placeholder-images') . '
';
331 | }
332 |
333 |
334 | function admin_menu() {
335 | add_options_page( __('Dynamic Placeholder Images', 'gga-dynamic-placeholder-images' ), __('Dynamic Placeholder Images', 'gga-dynamic-placeholder-images'), 'manage_options', $this->settings_page, array($this, 'options_page' ), 30);
336 | }
337 |
338 |
339 | function options_page() {
340 |
341 | $tab = filter_input(INPUT_GET, 'tab', FILTER_SANITIZE_STRING);
342 | if ( empty ( $tab ) ) {
343 | $tab = $this->settings_key_general;
344 | }
345 |
346 | ?>
347 |
348 | plugin_options_tabs(); ?>
349 |
358 |
359 | get_request( 'settings-updated' );
362 | if ( ! empty( $settings_updated ) ) {
363 | flush_rewrite_rules( );
364 | }
365 |
366 | }
367 |
368 |
369 | function plugin_options_tabs() {
370 | $current_tab = $this->get_request( 'tab' );
371 | if ( empty( $current_tab ) ) {
372 | $current_tab = $this->settings_key_general;
373 | }
374 | echo '' . __('Dynamic Placeholder Images Settings', 'gga-dynamic-placeholder-images') . '
';
375 | foreach ( $this->plugin_settings_tabs as $tab_key => $tab_caption ) {
376 | $active = $current_tab == $tab_key ? 'nav-tab-active' : '';
377 | echo '' . $tab_caption . '';
378 | }
379 | echo '
';
380 | }
381 |
382 |
383 | function section_header( $args ) {
384 |
385 | switch ( $args['id'] ) {
386 | case 'general';
387 | include_once $this->plugin_base_dir . 'admin/partials/admin-general-header.php';
388 | break;
389 | case 'cache';
390 | include_once $this->plugin_base_dir . 'admin/partials/admin-cache-header.php';
391 | break;
392 | case 'api';
393 | include_once $this->plugin_base_dir . 'admin/partials/admin-api-header.php';
394 | break;
395 | case 'help';
396 | include_once $this->plugin_base_dir . 'admin/partials/admin-help-header.php';
397 | break;
398 | }
399 |
400 | }
401 |
402 |
403 | }
404 |
405 | }
406 |
--------------------------------------------------------------------------------
/includes/class-gga-dynamic-placeholder-images-core.php:
--------------------------------------------------------------------------------
1 | plugin_name . '-image-url', array( $this, 'generate_image_url' ), 10, 4 );
38 |
39 | add_action( $this->plugin_name . '-delete-associations', array( $this, 'delete_all_dimension_associations' ) );
40 | add_filter( $this->plugin_name . '-get-associations-count', array( $this, 'get_dimension_associations_count' ) );
41 |
42 | }
43 |
44 |
45 | public function register_rewrites( $base_url = '' ) {
46 |
47 | if ( empty( $base_url ) ) {
48 | $base_url = $this->get_base_url();
49 | }
50 |
51 | add_rewrite_tag( '%gga-dynamic-image%', '1' );
52 | add_rewrite_tag( '%gga-dynamic-image-width%', '([0-9]+)' );
53 | add_rewrite_tag( '%gga-dynamic-image-height%', '([0-9]+)' );
54 | add_rewrite_tag( '%gga-dynamic-image-slug%', '([A-Za-z0-9\-\_]+)' );
55 |
56 | add_rewrite_rule( $base_url . '([0-9]+)/([0-9]+)/([A-Za-z0-9\-\_]+)/?', 'index.php?gga-dynamic-image=1&gga-dynamic-image-width=$matches[1]&gga-dynamic-image-height=$matches[2]&gga-dynamic-image-slug=$matches[3]', 'top' );
57 | add_rewrite_rule( $base_url . '([0-9]+)/([0-9]+)/?', 'index.php?gga-dynamic-image=1&gga-dynamic-image-width=$matches[1]&gga-dynamic-image-height=$matches[2]&gga-dynamic-image-slug=', 'top' );
58 | }
59 |
60 |
61 | public function template_redirect() {
62 |
63 | global $wp_query;
64 |
65 | $action = $wp_query->get( 'gga-dynamic-image' );
66 |
67 | if ( ! empty( $action ) ) {
68 | $width = intval( $wp_query->get( 'gga-dynamic-image-width' ) );
69 | $height = intval( $wp_query->get( 'gga-dynamic-image-height' ) );
70 | $slug = sanitize_key( $wp_query->get( 'gga-dynamic-image-slug' ) );
71 |
72 | // bounds checking, defaults to a max of 2000x2000
73 | $max_width = $this->get_max_width();
74 | $max_height = $this->get_max_height();
75 | $width = $width > $max_width ? $max_width : $width;
76 | $height = $height > $max_height ? $max_height : $height;
77 |
78 | $this->handle_dynamic_image( $width, $height, $slug );
79 | }
80 |
81 | }
82 |
83 | public function generate_image_url( $url, $width, $height, $tag = '' ) {
84 | $url = site_url( $this->get_base_url() . intval( $width ) . '/' . intval( $height ) . '/' . sanitize_key( $tag ) . '/' );
85 | return $url;
86 | }
87 |
88 |
89 | private function get_base_url( $base_url = '' ) {
90 | $base_url = apply_filters( $this->plugin_name . '-setting-get', 'dynamic-image', 'gga-dynamic-images-settings-general', 'base-url' );
91 | return ! empty( $base_url ) ? $base_url . '/' : '';
92 | }
93 |
94 |
95 | private function handle_dynamic_image( $width, $height, $slug ) {
96 |
97 | if ( $width !== 0 && $height !== 0 ) {
98 |
99 | $id = $this->get_image_id_for_slug( $slug, $width, $height );
100 |
101 | // Set the 404 status if the slug isn't valid.
102 | if ( ! empty( $slug ) && 'random' !== $slug && empty( $id ) ) {
103 | $this->set_404();
104 | return;
105 | }
106 |
107 | if ( empty( $id ) ) {
108 | $id = $this->get_random_image_id();
109 | }
110 |
111 | if ( empty( $id ) ) {
112 | $this->set_404();
113 | }
114 | else {
115 | $this->generate_image( $id, $width, $height );
116 | $this->stream_image( $id, $width, $height );
117 | }
118 | }
119 |
120 | }
121 |
122 |
123 | private function get_image_id_for_slug( $slug, $width, $height ) {
124 | $id = 0;
125 |
126 | if ( empty( $slug ) ) {
127 | $id = $this->get_existing_image_id_by_dimensions( $width, $height );
128 | } else if ( $slug === 'random' ) {
129 | $id = $this->get_random_image_id();
130 | $this->add_expires = false;
131 | } else if ( ! empty( $slug ) ) {
132 | $id = $this->get_image_id_by_slug( $slug );
133 | if ( empty( $id ) ) {
134 | $this->set_404();
135 | }
136 | }
137 |
138 | return $id;
139 | }
140 |
141 |
142 | public function delete_attachment( $postid ) {
143 | $this->delete_options_from_query( " WHERE option_name like '_gga-placeholder-image-for%' and option_value = '" . intval( $postid ) . "'" );
144 | }
145 |
146 |
147 | public function delete_all_dimension_associations() {
148 | if ( current_user_can( 'manage_options' ) ) {
149 | $this->delete_options_from_query( " WHERE option_name like '_gga-placeholder-image-for%'" );
150 | }
151 | }
152 |
153 |
154 | public function get_dimension_associations_count( $count ) {
155 | global $wpdb;
156 | $count = $wpdb->get_var( "SELECT count(*) FROM $wpdb->options WHERE option_name like '_gga-placeholder-image-for%'" );
157 | return $count;
158 | }
159 |
160 |
161 | private function delete_options_from_query( $query ) {
162 | if ( ! empty( $query) ) {
163 | global $wpdb;
164 | $results = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options " . $query );
165 |
166 | foreach ( $results as $r ) {
167 | delete_option( $r->option_name );
168 | }
169 | }
170 | }
171 |
172 | private function set_404() {
173 | global $wp_query;
174 | $wp_query->is_404 = true;
175 | }
176 |
177 | public function query_images( $args ) {
178 | global $post;
179 | $posts = array();
180 | $query = new WP_Query( $args );
181 |
182 | while ( $query->have_posts() ) {
183 | $query->the_post();
184 | $posts[] = $post;
185 | }
186 |
187 | wp_reset_postdata();
188 | return $posts;
189 | }
190 |
191 |
192 | public function image_query_args() {
193 |
194 | return array(
195 | 'posts_per_page' => 1,
196 | 'post_type' => 'attachment',
197 | 'post_status' => 'inherit',
198 | 'post_mime_type' => 'image',
199 | 'meta_key' => '_gga_image_is_mockup_image',
200 | 'meta_value' => 'on',
201 | );
202 |
203 | }
204 |
205 |
206 | private function get_random_image_id() {
207 | $args = $this->image_query_args();
208 | $args['orderby'] = 'rand';
209 | return $this->get_image_id_from_query( $args );
210 | }
211 |
212 |
213 | private function get_image_id_by_slug( $slug ) {
214 | $args = $this->image_query_args();
215 | $args['name'] = $slug;
216 | return $this->get_image_id_from_query( $args );
217 | }
218 |
219 |
220 | private function get_image_id_from_query( $args ) {
221 | $id = 0;
222 | $query = new WP_Query( $args );
223 |
224 | if ( $query->have_posts() ) {
225 | $id = $query->post->ID;
226 | }
227 |
228 | return $id;
229 | }
230 |
231 |
232 | private function stream_image( $id, $width, $height ) {
233 |
234 | $image_size_name = $this->image_size_name( $width, $height );
235 | $image = get_post( $id );
236 |
237 | $meta = wp_get_attachment_metadata( $id );
238 | if ( ! empty( $meta[ $this->meta_sizes ] ) ) {
239 | $sizes = $meta[ $this->meta_sizes ];
240 | }
241 |
242 | if ( !empty( $sizes ) && ! empty( $sizes[ $image_size_name ] ) ) {
243 |
244 | $filename = $this->get_cached_file_path( $sizes[ $image_size_name ]['file'], $width );
245 | if ( ! file_exists( $filename ) ) {
246 | // regenrate a missing image
247 | $this->generate_image( $id, $width, $height );
248 | }
249 |
250 | $filesize = filesize( $filename );
251 | $this->send_image_stream_headers( $sizes[$image_size_name]['mime-type'], $filesize, $image->post_name . '-' . $width . '-' . $height . '.jpg' );
252 | $this->send_common_stream_headers();
253 |
254 | ob_clean();
255 | flush();
256 | readfile( $filename );
257 |
258 | // fire action to allow stats logging
259 | do_action( $this->plugin_name . '-image-view', array( 'post_id' => $id, 'width' => $width, 'height' => $height, 'bytes' => $filesize ) );
260 | die();
261 |
262 | }
263 | else {
264 | $this->set_404();
265 | }
266 |
267 | }
268 |
269 |
270 | private function send_image_stream_headers( $mime_type, $filesize, $filename ) {
271 | header( 'Content-Type: ' . sanitize_mime_type( $mime_type ) );
272 | header( 'Content-Length: ' . intval( $filesize ) );
273 | header( 'Content-Disposition: inline; filename=' . sanitize_file_name( $filename ) );
274 | }
275 |
276 |
277 | private function send_common_stream_headers() {
278 | if ( $this->add_expires ) {
279 | $expires = DAY_IN_SECONDS * 15;
280 | header( 'Pragma: public' );
281 | header( 'Cache-Control: public' );
282 | header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time()+$expires ) . ' GMT' );
283 | header( 'Last-Modified:Mon, 20 Aug 2012 19:20:21 GMT' );
284 | }
285 | }
286 |
287 |
288 | private function add_image_size_meta( $width, $height ) {
289 | $image_size_name = $this->image_size_name( $width, $height );
290 |
291 | if ( ! is_array( $this->sizes ) ) {
292 | $this->sizes = array();
293 | }
294 |
295 | foreach ( $this->sizes as $s ) {
296 | if ( $s->name === $image_size_name )
297 | return;
298 | }
299 |
300 |
301 | // size does not exist, add it
302 | $size = new stdClass();
303 | $size->name = $image_size_name;
304 | $size->width = $width;
305 | $size->height = $height;
306 |
307 | $this->sizes[] = $size;
308 |
309 | add_image_size( $image_size_name, $width, $height, true );
310 |
311 | }
312 |
313 |
314 | private function cached_file_exists( $metadata, $image_size_name, $width ) {
315 | if ( ! empty( $metadata ) && ! empty( $metadata[ $this->meta_sizes ] ) && ! empty( $metadata[ $this->meta_sizes ][ $image_size_name ] ) && ! empty( $metadata[ $this->meta_sizes ][ $image_size_name ]['file'] ) ) {
316 | return file_exists( $this->get_cached_file_path( $metadata[ $this->meta_sizes ][ $image_size_name ]['file'], $width ) );
317 | }
318 | else {
319 | return false;
320 | }
321 | }
322 |
323 |
324 | /*
325 | if ( false ) {
326 | // this will force the resizer to conform to the dimensions of the original image
327 | // we may need to add code here to scale up the original image before resizing/cropping
328 | if ( ! empty( $metadata['width'] ) && $width > $metadata['width'] ) {
329 | $width = $metadata['width'];
330 | }
331 |
332 | if ( ! empty( $metadata['height'] ) && $width > $metadata['height'] ) {
333 | $height = $metadata['height'];
334 | }
335 | }
336 | */
337 |
338 |
339 | private function generate_image( $id, $width, $height ) {
340 | $image_size_name = $this->image_size_name( $width, $height );
341 | $this->add_image_size_meta( $width, $height );
342 | $image = get_post( $id );
343 | $image_size_exists = $this->image_size_exists( $id, $width, $height );
344 | $metadata = wp_get_attachment_metadata( $id );
345 | $cached_file_exists = $this->cached_file_exists( $metadata, $image_size_name, $width );
346 |
347 | if ( ! empty( $image) && ( ! $image_size_exists || ! $cached_file_exists ) ) {
348 | $fullsizepath = get_attached_file( $image->ID );
349 | include_once ABSPATH . 'wp-admin/includes/image.php';
350 |
351 | if ( ! $cached_file_exists ) {
352 | $resized = $this->generate_resized_image( $fullsizepath, $width, $height );
353 | }
354 |
355 | $this->update_image_metadata( $id, $resized, $metadata, $image_size_name );
356 | }
357 |
358 | $this->add_image_size_association( $id, $width, $height );
359 |
360 | return true;
361 |
362 | }
363 |
364 |
365 | private function update_image_metadata( $id, $resized, $metadata, $image_size_name ) {
366 | if ( ! empty( $resized ) && ! empty( $resized['file'] ) ) {
367 | $metadata[ $this->meta_sizes ][ $image_size_name ] = $resized;
368 | wp_update_attachment_metadata( $id, $metadata );
369 | }
370 | }
371 |
372 |
373 | private function add_image_size_association( $id, $width, $height ) {
374 | // save option so we know which image to use for the size
375 | $exists = $this->get_existing_image_id_by_dimensions( $width, $height );
376 | if ( empty( $exists ) ) {
377 | add_option( "_gga-placeholder-image-for-{$width}-{$height}", $id, '', 'no' );
378 | }
379 | }
380 |
381 |
382 | private function generate_resized_image( $fullsizepath, $width, $height ) {
383 | // don't call wp_generate_attachment_metadata because it regenerates existing images
384 | $resized = image_make_intermediate_size( $fullsizepath, $width, $height, $crop=true );
385 | if ( ! empty( $resized ) ) {
386 | $this->move_resized_to_cache( $resized['file'], $fullsizepath, $width );
387 | return $resized;
388 | } else {
389 | return false;
390 | }
391 |
392 | }
393 |
394 |
395 | private function move_resized_to_cache( $resized_filename, $fullsizepath, $width ) {
396 | delete_site_transient( $this->plugin_name . '-cache-size' );
397 | rename( path_join( dirname($fullsizepath), $resized_filename ), path_join( $this->get_cache_directory_for_width( $width ), $resized_filename ) );
398 | }
399 |
400 |
401 | private function get_existing_image_id_by_dimensions( $width, $height ) {
402 | $id = get_option( "_gga-placeholder-image-for-{$width}-{$height}", false );
403 | return $id;
404 | }
405 |
406 |
407 | private function image_size_exists( $id, $width, $height ) {
408 | $meta = wp_get_attachment_metadata( $id );
409 | return ! empty( $meta[ $this->meta_sizes ] ) && ! empty( $meta[ $this->meta_sizes ][$this->image_size_name( $width, $height )] );
410 | }
411 |
412 |
413 | private function image_size_name( $width, $height ) {
414 | return 'gga-image-' . $width . '-' . $height;
415 | }
416 |
417 |
418 | private function get_cache_directory() {
419 | return apply_filters( $this->plugin_name . '-get-cache-directory', 'gga-dynamic-placeholder-images' );
420 | }
421 |
422 |
423 | private function get_cache_directory_for_width( $width ) {
424 | $max_width = $this->get_max_width();
425 | if ( $width > $max_width ) {
426 | $width = $max_width;
427 | }
428 |
429 | $width_directory = strval( floor( $width / 100 ) * 100 );
430 | if ( $width_directory === '0' )
431 | $width_directory = '1';
432 |
433 | $width_directory = path_join( $this->get_cache_directory(), $width_directory );
434 | if ( ! is_dir( $width_directory ) ) {
435 | wp_mkdir_p( $width_directory );
436 | }
437 |
438 | return $width_directory;
439 | }
440 |
441 |
442 | private function get_cached_file_path( $filename, $width ) {
443 | return path_join( $this->get_cache_directory_for_width( $width ), $filename );
444 | }
445 |
446 |
447 | private function get_max_width() {
448 | return intval( apply_filters( $this->plugin_name . '-setting-get', 2000, $this->plugin_name . '-settings-general', 'max-width' ) );
449 | }
450 |
451 |
452 | private function get_max_height() {
453 | return intval( apply_filters( $this->plugin_name . '-setting-get', 2000, $this->plugin_name . '-settings-general', 'max-height' ) );
454 | }
455 |
456 |
457 | // because Sneek read the code
458 |
459 | }
460 |
461 |
462 | }
463 |
--------------------------------------------------------------------------------