Permalink
Browse files

Finally added the PHP portion to the repo.

  • Loading branch information...
1 parent e9eef8e commit e1490d832d0eceda720ecd4081edfe371bc75261 @scottgonzalez committed Oct 12, 2012
Showing with 206 additions and 0 deletions.
  1. +3 −0 README.md
  2. +203 −0 grunt-wordpress.php
View
@@ -3,6 +3,7 @@
Grunt plugin for publishing content to WordPress
## Getting Started
+
Install this grunt plugin next to your project's
[grunt.js gruntfile](https://github.com/cowboy/grunt/blob/master/docs/getting_started.md)
with: `npm install grunt-wordpress`
@@ -13,6 +14,8 @@ Then add this line to your project's `grunt.js` gruntfile:
grunt.loadNpmTasks( "grunt-wordpress" );
```
+Finally, copy `grunt-wordpress.js` in to your WordPress install as a plugin.
+
## API
For most projects, you should only need to specify the `wordpress` config
View
@@ -0,0 +1,203 @@
+<?php
+/**
+ * Plugin Name: Grunt WordPress XML-RPC extensions
+ * Description: Adds custom XML-RPC methods for use with grunt-wordpress.
+ */
+
+if ( ! defined( 'GW_RESOURCE_DIR' ) )
+ define( 'GW_RESOURCE_DIR', dirname( WP_CONTENT_DIR ) . '/gw-resources/' .
+ preg_replace( '/^\w+:\/\//', '', home_url() ) );
+
+function gw_get_version( $args ) {
+ global $wp_xmlrpc_server;
+ $wp_xmlrpc_server->escape( $args );
+
+ // Authenticate
+ $blog_id = $args[0];
+ $username = $args[1];
+ $password = $args[2];
+
+ // We require authentication so that we can ensure that the username
+ // and password provided will work for other methods.
+ if ( ! $user = $wp_xmlrpc_server->login( $username, $password ) ) {
+ return $wp_xmlrpc_server->error;
+ }
+
+ return "1.0.3";
+}
+
+function gw_get_post_paths( $post_type = "" ) {
+ $results = array();
+ $query = new WP_Query( array(
+ 'post_type' => $post_type,
+ 'post_status' => 'publish',
+ 'posts_per_page' => -1,
+ 'update_post_term_cache' => false,
+ ) );
+ foreach ( $query->posts as $post ) {
+ $results[ $post->post_type . '/' . get_page_uri( $post->ID ) ] = array(
+ 'id' => $post->ID,
+ 'checksum' => get_post_meta( $post->ID, 'gwcs', true ),
+ );
+ }
+
+ return $results;
+}
+
+
+function gw_get_resources() {
+ $filename = GW_RESOURCE_DIR . "/__gw.json";
+ if ( !file_exists( $filename ) ) {
+ return array();
+ }
+ return json_decode( file_get_contents( $filename ), true );
+}
+
+function gw_set_resources( $resources ) {
+ file_put_contents( GW_RESOURCE_DIR . "/__gw.json", json_encode( $resources ) );
+}
+
+function gw_add_resource( $args ) {
+ global $wp_xmlrpc_server;
+ $wp_xmlrpc_server->escape( $args );
+
+ // Authenticate
+ $blog_id = $args[0];
+ $username = $args[1];
+ $password = $args[2];
+
+ if ( ! $user = $wp_xmlrpc_server->login( $username, $password ) ) {
+ return $wp_xmlrpc_server->error;
+ }
+
+ // Verify path and decode file contents
+ $path = $args[3];
+ if ( false !== strpos( $path, ".." ) ) {
+ return new IXR_ERROR( 500, "Invalid path." );
+ }
+ $bits = $args[4];
+ $checksum = md5( $bits );
+ $bits = base64_decode( $bits );
+
+ // Create a temp file using built-in upload functionality
+ $info = pathinfo( $path );
+ $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
+ $upload = wp_upload_bits( "gw-resource" . $ext, null, $bits );
+ if ( !empty( $upload['error'] ) ) {
+ return new IXR_Error( 500, $upload['error'] );
+ }
+
+ // Move the file to the gw-resources directory
+ $new_file = GW_RESOURCE_DIR . "/$path";
+ if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
+ $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), dirname( $new_file ) );
+ return new IXR_Error( 500, $message );
+ }
+ rename( $upload['file'], $new_file );
+ clearstatcache();
+
+ // Update resource list
+ $resources = gw_get_resources();
+ $resources[ $path ] = $checksum;
+ gw_set_resources( $resources );
+
+ return $checksum;
+}
+
+function gw_delete_resource( $args ) {
+ global $wp_xmlrpc_server;
+ $wp_xmlrpc_server->escape( $args );
+
+ // Authenticate
+ $blog_id = $args[0];
+ $username = $args[1];
+ $password = $args[2];
+
+ if ( ! $user = $wp_xmlrpc_server->login( $username, $password ) ) {
+ return $wp_xmlrpc_server->error;
+ }
+
+ // Verify path
+ $path = $args[3];
+ if ( false !== strpos( $path, ".." ) ) {
+ return new IXR_ERROR( 500, "Invalid path." );
+ }
+
+ // Delete resource
+ $old_file = GW_RESOURCE_DIR . "/$path";
+ if ( file_exists( $old_file ) ) {
+ unlink( $old_file );
+ }
+
+ // Update resource list
+ $resources = gw_get_resources();
+ $checksum = empty( $resources[ $path ] ) ? null : $resources[ $path ];
+ unset( $resources[ $path ] );
+ gw_set_resources( $resources );
+
+ return $checksum;
+}
+
+function gw_register_xmlrpc_methods( $methods ) {
+ $methods['gw.getVersion'] = 'gw_get_version';
+ $methods['gw.getPostPaths'] = 'gw_get_post_paths';
+ $methods['gw.getResources'] = 'gw_get_resources';
+ $methods['gw.addResource'] = 'gw_add_resource';
+ $methods['gw.deleteResource'] = 'gw_delete_resource';
+ return $methods;
+}
+
+add_filter( 'xmlrpc_methods', 'gw_register_xmlrpc_methods' );
+
+
+
+function gw_sanitize_title_with_dashes( $title, $raw_title = '', $context = 'display' ) {
+ // Special case during the install process.
+ if ( 'Uncategorized' == $raw_title )
+ return 'uncategorized';
+
+ $title = strip_tags($title);
+ // Preserve escaped octets.
+ $title = preg_replace( '|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title );
+ // Remove percent signs that are not part of an octet.
+ $title = str_replace( '%', '', $title );
+ // Restore octets.
+ $title = preg_replace( '|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title );
+
+ // CHANGE: Don't lowercase
+ if ( seems_utf8( $title ) ) {
+ $title = utf8_uri_encode( $title, 200 );
+ }
+
+ // CHANGE: Don't lowercase and don't remove dots
+ $title = preg_replace( '/&.+?;/', '', $title ); // kill entities
+
+ if ( 'save' == $context ) {
+ // Convert nbsp, ndash and mdash to hyphens
+ $title = str_replace( array( '%c2%a0', '%e2%80%93', '%e2%80%94' ), '-', $title );
+
+ // Strip these characters entirely
+ $title = str_replace( array(
+ // iexcl and iquest
+ '%c2%a1', '%c2%bf',
+ // angle quotes
+ '%c2%ab', '%c2%bb', '%e2%80%b9', '%e2%80%ba',
+ // curly quotes
+ '%e2%80%98', '%e2%80%99', '%e2%80%9c', '%e2%80%9d',
+ '%e2%80%9a', '%e2%80%9b', '%e2%80%9e', '%e2%80%9f',
+ // copy, reg, deg, hellip and trade
+ '%c2%a9', '%c2%ae', '%c2%b0', '%e2%80%a6', '%e2%84%a2',
+ ), '', $title );
+ }
+
+ // CHANGE: Allow dots and case-insensitive
+ $title = preg_replace( '/[^%a-z0-9 _.-]/i', '', $title );
+ $title = preg_replace( '/\s+/', '-', $title );
+ $title = preg_replace( '|-+|', '-', $title );
+ $title = trim( $title, '-' );
+
+ return $title;
+}
+
+remove_filter( 'sanitize_title', 'sanitize_title_with_dashes', 10, 3 );
+add_filter( 'sanitize_title', 'gw_sanitize_title_with_dashes', 10, 3 );

0 comments on commit e1490d8

Please sign in to comment.