├── assets ├── littlebot-netlifly.css ├── littlebot-netlifly.js └── repo │ └── README.md ├── includes ├── README.md ├── class-lbn-assets.php ├── class-lbn-meta-fields.php ├── class-lbn-metaboxes.php ├── class-lbn-netlifly.php ├── class-lbn-post.php └── class-lbn-settings.php ├── readme.md ├── views ├── view-metabox-major-publishing.php └── view-metabox-publish.php └── wp-buildhook-deploy.php /assets/littlebot-netlifly.css: -------------------------------------------------------------------------------- 1 | #lb-publishing-action #major-publishing-actions { 2 | margin: 20px -12px -12px -12px; 3 | overflow: hidden; 4 | } 5 | -------------------------------------------------------------------------------- /assets/littlebot-netlifly.js: -------------------------------------------------------------------------------- 1 | ( function($) { 2 | 3 | 4 | })( jQuery ); 5 | -------------------------------------------------------------------------------- /assets/repo/README.md: -------------------------------------------------------------------------------- 1 | # littlebot-netlify Repo Assets # 2 | https://www.justinwhall.com 3 | Copyright (c) 2018 jwind 4 | Licensed under the GPLv2 license. 5 | 6 | Assets such as screenshots and banner for WordPress.org plugin repository listing. -------------------------------------------------------------------------------- /includes/README.md: -------------------------------------------------------------------------------- 1 | # littlebot-netlify Includes # 2 | https://www.justinwhall.com 3 | Copyright (c) 2018 jwind 4 | Licensed under the GPLv2 license. 5 | 6 | Additional PHP functionality goes here. -------------------------------------------------------------------------------- /includes/class-lbn-assets.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 35 | $this->hooks(); 36 | } 37 | 38 | /** 39 | * Attach hooks. 40 | * 41 | * @return void 42 | */ 43 | public function hooks() { 44 | add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) ); 45 | } 46 | 47 | /** 48 | * Enqueue assets 49 | * 50 | * @return void 51 | */ 52 | public function enqueue_scripts_styles() { 53 | wp_enqueue_style( 'lbn-styles', $this->plugin->url . '/assets/littlebot-netlifly.css', array(), $this->plugin->__get( 'version' ), false ); 54 | wp_enqueue_script( 'lbn-scripts', $this->plugin->url . '/assets/littlebot-netlifly.js', array(), $this->plugin->__get( 'version' ), true ); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /includes/class-lbn-meta-fields.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 29 | $this->hooks(); 30 | } 31 | 32 | /** 33 | * Attach hooks. 34 | * 35 | * @return void 36 | */ 37 | public function hooks() { 38 | add_action( 'init', array( $this, 'register_meta_fields' ) ); 39 | } 40 | 41 | /** 42 | * Register customer meta fields and show in REST. 43 | * 44 | * @return void 45 | */ 46 | public function register_meta_fields() { 47 | 48 | $args = array( 49 | 'type' => 'boolean', 50 | 'description' => 'Has this post been published to stage', 51 | 'single' => true, 52 | 'show_in_rest' => true, 53 | ); 54 | 55 | register_meta( 'post', 'lbn_published_stage', $args ); 56 | 57 | $args['description'] = 'Has this post been published to production'; 58 | register_meta( 'post', 'lbn_published_production', $args ); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /includes/class-lbn-metaboxes.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 37 | $this->hooks(); 38 | } 39 | 40 | /** 41 | * Attach hooks. 42 | * 43 | * @return void 44 | */ 45 | public function hooks() { 46 | // Remove default publish metabox. 47 | add_action( 'do_meta_boxes', array( $this, 'remove_publish_box' ) ); 48 | add_action( 'add_meta_boxes', array( $this, 'add_publish_box' ) ); 49 | } 50 | 51 | /** 52 | * Remove default publish metabox. We'll add our own. 53 | * 54 | * @return void 55 | */ 56 | public function remove_publish_box() { 57 | remove_meta_box( 'submitdiv', array( 'post', 'page' ), 'side' ); 58 | } 59 | 60 | /** 61 | * Add a custom publishing metabox. 62 | * 63 | * @return void 64 | */ 65 | public function add_publish_box() { 66 | add_meta_box( 67 | 'lb_netlifly', 68 | __( 'Netlify', 'littlebot-netlify' ), 69 | array( $this, 'render_meta_box_content' ), 70 | array( 'post', 'page' ), 71 | 'side', 72 | 'high' 73 | ); 74 | } 75 | 76 | /** 77 | * Render Meta Box content. 78 | * 79 | * @param WP_Post $post The post object. 80 | */ 81 | public function render_meta_box_content( $post ) { 82 | include_once $this->plugin->path . 'views/view-metabox-publish.php'; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /includes/class-lbn-netlifly.php: -------------------------------------------------------------------------------- 1 | settings = get_option( 'lb_netlifly' ); 43 | $this->build_hook_url = $this->get_build_hook( $env ); 44 | } 45 | 46 | /** 47 | * Detirmine which env build hook to call. 48 | * 49 | * @param string $env The environment we want to call the buildhook. 50 | * 51 | * @return string 52 | */ 53 | public function get_build_hook( $env ) { 54 | return $this->settings[ $env . '_buildhook' ]; 55 | } 56 | 57 | /** 58 | * Call Netlifly buildhook. 59 | * 60 | * @return void 61 | */ 62 | function call_build_hook() { 63 | 64 | $response = Requests::post( $this->build_hook_url ); 65 | 66 | // TODO: further processing .... 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /includes/class-lbn-post.php: -------------------------------------------------------------------------------- 1 | plugin = $plugin; 36 | $this->hooks(); 37 | } 38 | 39 | /** 40 | * Attach hooks. 41 | * 42 | * @return void 43 | */ 44 | public function hooks() { 45 | add_action( 'save_post', array( $this, 'save_post' ), 10, 3 ); 46 | add_action( 'trash_post', array( $this, 'trash_post' ), 10, 1 ); 47 | add_action( 'wp_insert_post_data', array( $this, 'insert_post' ), 10, 3 ); 48 | add_action( 'manage_posts_columns', array( $this, 'show_publish_status' ), 10, 3 ); 49 | add_action( 'manage_posts_custom_column', array( $this, 'build_column' ), 15, 3 ); 50 | } 51 | 52 | /** 53 | * Add publish column 54 | * 55 | * @param array $columns Post list columns. 56 | * 57 | * @return array 58 | */ 59 | public function show_publish_status( $columns ) { 60 | return array_merge( 61 | $columns, 62 | array( 63 | 'Published' => __( 'Published', 'lb-netlifly' ), 64 | ) 65 | ); 66 | } 67 | 68 | /** 69 | * Add columns to invoice and estimates 70 | * 71 | * @param array $columns post screen columns. 72 | * @param int $post_id the post id. 73 | * @return void 74 | */ 75 | public function build_column( $columns, $post_id ) { 76 | 77 | $stage_status = (bool) get_post_meta( $post_id, 'lbn_published_stage', true ); 78 | $prod_status = (bool) get_post_meta( $post_id, 'lbn_published_production', true ); 79 | 80 | if ( $prod_status ) { 81 | echo sprintf( '
%s
', esc_html( 'Production', 'lb-netlifly' ) ); 82 | } 83 | 84 | if ( $stage_status ) { 85 | echo sprintf( '
%s
', esc_html( 'Stage', 'lb-netlifly' ) ); 86 | } 87 | 88 | if ( ! $stage_status && ! $prod_status ) { 89 | echo '—'; 90 | } 91 | } 92 | 93 | /** 94 | * Updates "deploy" status on post update 95 | * 96 | * @param object $data the $_POST request. 97 | * @param object $post the post being updated. 98 | * 99 | * @return object 100 | */ 101 | public function insert_post( $data, $post ) { 102 | if ( 103 | isset( $post['post_status'] ) && 'auto-draft' === $post['post_status'] || 104 | defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || 105 | defined( 'DOING_AJAX' ) && DOING_AJAX 106 | ) { 107 | return $data; 108 | } 109 | 110 | // If it's a deploy, make sure it's set to publish. 111 | if ( isset( $post['deploy'] ) ) { 112 | $data['post_status'] = 'publish'; 113 | } 114 | 115 | return $data; 116 | } 117 | 118 | /** 119 | * Save post callback 120 | * 121 | * @param int $post_id The post ID. 122 | * @param object $post The post object. 123 | * @param boolean $update Is this an update. 124 | * @return void 125 | */ 126 | public function save_post( $post_id, $post, $update ) { 127 | LBN_POST::update( $post ); 128 | } 129 | 130 | /** 131 | * Trash post callback 132 | * 133 | * @param int $post_id The post id. 134 | * @return void 135 | */ 136 | public function trash_post( $post_id ) { 137 | $post = get_post( $post_id ); 138 | LBN_POST::update( $post ); 139 | } 140 | 141 | /** 142 | * Update post meta and call build hooks(s) 143 | * 144 | * @param object $post The post being updated. 145 | * @return void 146 | */ 147 | public function update( $post ) { 148 | if ( 149 | isset( $post->post_status ) && 'auto-draft' === $post->post_status || 150 | defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || 151 | defined( 'DOING_AJAX' ) && DOING_AJAX 152 | ) { 153 | return; 154 | } 155 | 156 | $lb_netlifly = get_option( 'lb_netlifly' ); 157 | $has_stage_hook = (bool) $lb_netlifly['stage_buildhook']; 158 | $has_prod_hook = (bool) $lb_netlifly['production_buildhook']; 159 | 160 | // Is this post published. 161 | $published_stage = isset( $_POST['lbn_published_stage'] ) ? true : false; 162 | $published_production = isset( $_POST['lbn_published_production'] ) ? true : false; 163 | 164 | // Stage. 165 | if ( $has_stage_hook ) { 166 | update_post_meta( $post->ID, 'lbn_published_stage', $published_stage ); 167 | $netlifly_stage = new LBN_Netlifly( 'stage' ); 168 | $netlifly_stage->call_build_hook(); 169 | } 170 | 171 | // Prod. 172 | if ( $has_prod_hook ) { 173 | update_post_meta( $post->ID, 'lbn_published_production', $published_production ); 174 | $netlifly_stage = new LBN_Netlifly( 'production' ); 175 | $netlifly_stage->call_build_hook(); 176 | } 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /includes/class-lbn-settings.php: -------------------------------------------------------------------------------- 1 | options = get_option( 'lb_netlifly' ); 57 | 58 | ?> 59 |
60 |

WP Buildhook Deploy Settings

61 |
62 | 68 |
69 |
70 | ', 135 | isset( $this->options['production_buildhook'] ) ? esc_attr( $this->options['production_buildhook'] ) : '' 136 | ); 137 | } 138 | 139 | /** 140 | * Renders stage input option. 141 | * 142 | * @return void 143 | */ 144 | public function stage_callback() { 145 | printf( 146 | '', 147 | isset( $this->options['stage_buildhook'] ) ? esc_attr( $this->options['stage_buildhook'] ) : '' 148 | ); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | **👋 This plugin [has been forked](https://github.com/staticfuse/gatsby-toolkit) and is now maintained by [Static Fuse](https://staticfuse.com).** 2 | 3 | ====================================================================================== 4 | 5 | Look for improvments and more great WordPress + Gatsby workflow support. Questions? Submit an issue at the new repo or find me on twitter --> [@justinwhall](https://twitter.com/justinwhall) 6 | 7 | 8 | # WP Buildhook Deploy ("LittleBot Netlify") 9 | 10 | **This plugin was formerly know as "LittleBot Netlify". It was renamed to avoid confusion as it can be used to trigger build hooks at, say, AWS Amplify, GitHub or any service that provides a WebHook – _not_ just Netlify.** 11 | 12 | Connect your WordPress website to [Netlify](https://www.netlify.com/) (or any service that provides a buildhook) by triggering stage and or production build hooks on post save and or update. This plugin is not tied to Netlify, you can connect other CI systems with webhooks enabled like CircleCI, Travis, AWS Amplify, etc. 13 | 14 | ## Installation 15 | 16 | - Download or clone repository 17 | - Move `wp-buildhook-deploy` to your plugins directory or zip and upload 18 | - Activate plugin 19 | - Add at least one buildhook URL to the setings page `Settings > WP BuildHook Deploy` 20 | 21 | ### Using Netlify? (It's awesome BTW) 22 | 23 | - Create at least one site at Netlify 24 | - [Create a build hook](https://www.netlify.com/docs/webhooks/) for each site (or just one if you're just using one site) 25 | - Add build hook to the `Settings > WP BuildHook Deploy` 26 | - Your WordPress site will call your build hook(s) when publishing, updating or deleting a post 27 | 28 | ## Gatsby + WordPress + Netlify Starter 29 | 30 | [Gatsby + WordPress + Netlify Starter](https://github.com/justinwhall/gatsby-wordpress-netlify-starter) is a plug and play starter to get up and running with continuous deployment from your WordPress site to Netlify with Gatsby. 31 | 32 | ## Gatsby + WordPress + Live Previews 33 | 34 | Checkout [this Gatsby theme](https://github.com/justinwhall/wordpress-gatsby-preview-starter). This could also be used with this plugin to publish to Netlify, AWS Amplify etc when publishing/updating/deleting/etc WordPress Posts/pages. 35 | 36 | ## Q & A 37 | 38 | `Q` **Do you need two sites at Netlify?** 39 | 40 | `A` No. This plugin will call your build hook and build your Gatsby (or whatever) site no matter what. The starter mentioned above facilitates a _two_ environment Gatsby set up but other than that, this plugin is totally _front end agnostic_ and you could just as easy trigger one build hook by only adding one build hook URL. 41 | 42 | `Q` **Does this plugin support Gutenberg?** 43 | 44 | `A` This plugin supports both GutenLOVERS and GutenHATERS. How? It supports Gutenberg as that is what the WordPress editing experience is now. Don't like Gutenberg? This plugin also supports the Classic Editor. 45 | 46 | `Q` **Can I use this plugin with other similar system to Netlify like for example AWS Amplify?** 47 | 48 | `A` YES. You can use a CI like Amplify, Circle, Travis etc. Depending on what you are trying to do, the plugin may still work as it just calls a webhook URL with some logic around various publishing hooks. 49 | -------------------------------------------------------------------------------- /views/view-metabox-major-publishing.php: -------------------------------------------------------------------------------- 1 | 9 |

:

10 | 11 |
12 | 13 | 14 |
15 | 16 | 17 |
18 | open tag %2 close tag : */ 22 | esc_html__( 'Oops, you need to %1$sset a production or stage build hook%2$s for this plugin to work.', 'lb-netlifly' ), 23 | '', 24 | '' 25 | ); 26 | ?> 27 |
28 | 29 | -------------------------------------------------------------------------------- /views/view-metabox-publish.php: -------------------------------------------------------------------------------- 1 | post_type; 14 | $post_type_obj = get_post_type_object( $current_post_type ); 15 | $can_publish = current_user_can( $post_type_obj->cap->publish_posts ); 16 | // Prev deploy states. 17 | $published_stage = (bool) get_post_meta( $post->ID, 'lbn_published_stage', true ); 18 | $published_production = (bool) get_post_meta( $post->ID, 'lbn_published_production', true ); 19 | $is_classic_editor = is_plugin_active( 'classic-editor/classic-editor.php' ); 20 | ?> 21 | 22 |
23 |
24 | 25 | post_status, array( 'publish', 'future', 'private', 'lbn-update' ) ) || 0 === $post->ID ) : ?> 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
57 | ID ) ) { 59 | if ( ! EMPTY_TRASH_DAYS ) { 60 | $delete_text = __( 'Delete Permanently' ); 61 | } else { 62 | $delete_text = __( 'Move to Trash' ); 63 | } 64 | ?> 65 |
66 | 67 |
68 | 71 | 72 |
73 | 74 | 75 |
76 | 77 |
78 | 79 | 80 | 81 |
82 |
83 |
84 | 85 | -------------------------------------------------------------------------------- /wp-buildhook-deploy.php: -------------------------------------------------------------------------------- 1 | basename = plugin_basename( __FILE__ ); 136 | $this->url = plugin_dir_url( __FILE__ ); 137 | $this->path = plugin_dir_path( __FILE__ ); 138 | $this->ver = self::VERSION; 139 | } 140 | 141 | /** 142 | * Attach other plugin classes to the base plugin class. 143 | * 144 | * @since 0.9.0 145 | */ 146 | public function includes() { 147 | new LBN_Assets( $this ); 148 | new LBN_Settings( $this ); 149 | new LBN_Meta_Fields( $this ); 150 | new LBN_Metaboxes( $this ); 151 | new LBN_Post( $this ); 152 | } // END OF PLUGIN CLASSES FUNCTION 153 | 154 | /** 155 | * Add hooks and filters. 156 | * Priority needs to be 157 | * < 10 for CPT_Core, 158 | * < 5 for Taxonomy_Core, 159 | * and 0 for Widgets because widgets_init runs at init priority 1. 160 | * 161 | * @since 0.9.0 162 | */ 163 | public function hooks() { 164 | add_action( 'init', array( $this, 'init' ), 0 ); 165 | } 166 | 167 | /** 168 | * Activate the plugin. 169 | * 170 | * @since 0.9.0 171 | */ 172 | public function _activate() { 173 | // Bail early if requirements aren't met. 174 | if ( ! $this->check_requirements() ) { 175 | return; 176 | } 177 | 178 | // If we already have options, don't create defaults. 179 | if ( get_option( 'lb_netlifly' ) ) { 180 | return; 181 | } 182 | 183 | $options = array( 184 | 'production_buildhook' => '', 185 | 'stage_buildhook' => '', 186 | ); 187 | 188 | update_option( 'lb_netlifly', $options ); 189 | 190 | // Make sure any rewrite functionality has been loaded. 191 | flush_rewrite_rules(); 192 | } 193 | 194 | /** 195 | * Deactivate the plugin. 196 | * Uninstall routines should be in uninstall.php. 197 | * 198 | * @since 0.9.0 199 | */ 200 | public function _deactivate() { 201 | // Add deactivation cleanup functionality here. 202 | } 203 | 204 | /** 205 | * Init hooks 206 | * 207 | * @since 0.9.0 208 | */ 209 | public function init() { 210 | 211 | // Bail early if requirements aren't met. 212 | if ( ! $this->check_requirements() ) { 213 | return; 214 | } 215 | 216 | // Load translated strings for plugin. 217 | load_plugin_textdomain( 'littlebot-netlify', false, dirname( $this->basename ) . '/languages/' ); 218 | 219 | // Initialize plugin classes. 220 | $this->includes(); 221 | } 222 | 223 | /** 224 | * Check if the plugin meets requirements and 225 | * disable it if they are not present. 226 | * 227 | * @since 0.9.0 228 | * 229 | * @return boolean True if requirements met, false if not. 230 | */ 231 | public function check_requirements() { 232 | 233 | // Bail early if plugin meets requirements. 234 | if ( $this->meets_requirements() ) { 235 | return true; 236 | } 237 | 238 | // Add a dashboard notice. 239 | add_action( 'all_admin_notices', array( $this, 'requirements_not_met_notice' ) ); 240 | 241 | // Deactivate our plugin. 242 | add_action( 'admin_init', array( $this, 'deactivate_me' ) ); 243 | 244 | // Didn't meet the requirements. 245 | return false; 246 | } 247 | 248 | /** 249 | * Deactivates this plugin, hook this function on admin_init. 250 | * 251 | * @since 0.9.0 252 | */ 253 | public function deactivate_me() { 254 | 255 | // We do a check for deactivate_plugins before calling it, to protect 256 | // any developers from accidentally calling it too early and breaking things. 257 | if ( function_exists( 'deactivate_plugins' ) ) { 258 | deactivate_plugins( $this->basename ); 259 | } 260 | } 261 | 262 | /** 263 | * Check that all plugin requirements are met. 264 | * 265 | * @since 0.9.0 266 | * 267 | * @return boolean True if requirements are met. 268 | */ 269 | public function meets_requirements() { 270 | 271 | // Do checks for required classes / functions or similar. 272 | // Add detailed messages to $this->activation_errors array. 273 | return true; 274 | } 275 | 276 | /** 277 | * Adds a notice to the dashboard if the plugin requirements are not met. 278 | * 279 | * @since 0.9.0 280 | */ 281 | public function requirements_not_met_notice() { 282 | 283 | // Compile default message. 284 | /* translators: %s: Admin URL */ 285 | $default_message = sprintf( __( 'littlebot-netlify is missing requirements and has been deactivated. Please make sure all requirements are available.', 'littlebot-netlify' ), admin_url( 'plugins.php' ) ); 286 | 287 | // Default details to null. 288 | $details = null; 289 | 290 | // Add details if any exist. 291 | if ( $this->activation_errors && is_array( $this->activation_errors ) ) { 292 | $details = '' . implode( '
', $this->activation_errors ) . ''; 293 | } 294 | 295 | // Output errors. 296 | ?> 297 |
298 |

299 | 300 |
301 | $field; 321 | default: 322 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field ); 323 | } 324 | } 325 | 326 | /** 327 | * Include a file from the includes directory. 328 | * 329 | * @since 0.9.0 330 | * 331 | * @param string $filename Name of the file to be included. 332 | * @return boolean Result of include call. 333 | */ 334 | public static function include_file( $filename ) { 335 | $file = self::dir( $filename . '.php' ); 336 | if ( file_exists( $file ) ) { 337 | return include_once $file; 338 | } 339 | return false; 340 | } 341 | 342 | /** 343 | * This plugin's directory. 344 | * 345 | * @since 0.9.0 346 | * 347 | * @param string $path (optional) appended path. 348 | * @return string Directory and path. 349 | */ 350 | public static function dir( $path = '' ) { 351 | static $dir; 352 | $dir = $dir ? $dir : trailingslashit( dirname( __FILE__ ) ); 353 | return $dir . $path; 354 | } 355 | 356 | /** 357 | * This plugin's url. 358 | * 359 | * @since 0.9.0 360 | * 361 | * @param string $path (optional) appended path. 362 | * @return string URL and path. 363 | */ 364 | public static function url( $path = '' ) { 365 | static $url; 366 | $url = $url ? $url : trailingslashit( plugin_dir_url( __FILE__ ) ); 367 | return $url . $path; 368 | } 369 | } 370 | 371 | /** 372 | * Grab the Littlebot_netlify object and return it. 373 | * Wrapper for Littlebot_netlify::get_instance(). 374 | * 375 | * @since 0.9.0 376 | * @return Littlebot_netlify Singleton instance of plugin class. 377 | */ 378 | function littlebot_netlify() { 379 | return Littlebot_Netlify::get_instance(); 380 | } 381 | 382 | // Kick it off. 383 | add_action( 'plugins_loaded', array( littlebot_netlify(), 'hooks' ) ); 384 | 385 | // Activation and deactivation. 386 | register_activation_hook( __FILE__, array( littlebot_netlify(), '_activate' ) ); 387 | register_deactivation_hook( __FILE__, array( littlebot_netlify(), '_deactivate' ) ); 388 | --------------------------------------------------------------------------------