Category: Plugin

  • Translations Abstraction Proposal for WordPress

    plugins.svn.wordpress.org:

    • There is a new special folder in Plugin Repositories, at /assets/i18n/
    • A /assets/trunk.pot file should probably be maintained for support of repositories where trunk is their public release version.
    • Whenever a new tag is created, for example /tag/3.2-beta1 (a script automatically|the plugin author) generates the po/mo source files, and stores it as /assets/i18n/3.2-beta1.pot or the like.
    • I’m torn as to who generates this, and I have no desire for this to generate additional changesets on our already burdened plugins.svn.wordpress.org — perhaps they could live elsewhere, and wouldn’t necessarily need to be under version control.
    • A /assets/i18n/master.pot and the like file may be maintained which is a merger of all the strings in all the versions in all the tags.
      • This is to simplify things so that if a string is dropped from one version to the next, it is still included in a master index, potentially simplifying things from a storage perspective, so that if requesting translations for a plugin, a version number does not need to be specified, and GlotPress wouldn’t need to store fifty copies of the same string for the same plugin, if there are fifty different tagged versions.

    plugins.glotpress.wordpress.org

    • I know very little about the inner workings of GlotPress currently, so I’ll leave this part of the proposal as a ‘black box’ that magically works.
    • Sharing identical strings between plugins would be amazing, if possible, but with the ability to break the link if one plugin author needs it to be translated differently.  But I suppose that can be done with _x() and notes for translators.
    • API requests for translations shouldn’t by default be given up-to-the-second results.  If there’s a cached version from the last 24 hours, or it hasn’t been invalidated with any new translations yet, just serve that version up.
    • Gzip it all in transit & storage.

    core

    • This would be implemented as a plugin tentatively by using the 'override_load_textdomain' filter — which would then query the API and either store the translations in a transient/option, or in a folder within /wp-content/.
    • If not using a transient, set a wp_cron task to check for updates every X days, weeks, or on upgrades / installs / manually pushing the update translations button.
    • Store a version number for the most recently received translations, and pass that back with subsequent queries, so it only receives the strings that have been updated since the last pass (huge potential savings on bandwidth and server processing time).
    • On the (client|server) side, round the version number down to a given interval (thousand, ten thousand?) so that it can be cached more easily on the server side.  A couple duplicate translations could get delivered, but that’s a small price to pay for the savings in processing time.
  • Need a category index page?

    Why not just use a normal page?

    Oh, sure, you want a dynamically loading list of the categories.

    Try this on for size:

    
    add_shortcode( 'taxonomy-list', 'my_taxonomy_list' );
    function my_taxonomy_list( $atts ) {
        $args = shortcode_atts( array(
            'taxonomy' => 'category',
            'title_li' => '',
            'depth' => 1,
            'hide_empty' => 1,
        ), $atts );
    
        ob_start();
        ?>
            <ul class="taxonomy-list taxonomy-<?php echo $args['taxonomy']; ?>-list" data-taxonomy="<?php echo $args['taxonomy']; ?>">
                <?php wp_list_categories( $args ); ?>
            </ul>
        <?php
        return ob_get_clean();
    }
    
    
  • How to change post thumbnail crop position in WordPress WITHOUT HACKING CORE

    DISCLAIMER: This requires WordPress 3.4 to work correctly. The filter was added based on Trac Ticket #15989

    Okay, to start, here is the function that we’re going to be working with, from ~/wp-includes/media.php :

    /**
     * Retrieve calculated resized dimensions for use in imagecopyresampled().
     *
     * Calculate dimensions and coordinates for a resized image that fits within a
     * specified width and height. If $crop is true, the largest matching central
     * portion of the image will be cropped out and resized to the required size.
     *
     * @since 2.5.0
     * @uses apply_filters() Calls 'image_resize_dimensions' on $orig_w, $orig_h, $dest_w, $dest_h and
     *		$crop to provide custom resize dimensions.
     *
     * @param int $orig_w Original width.
     * @param int $orig_h Original height.
     * @param int $dest_w New width.
     * @param int $dest_h New height.
     * @param bool $crop Optional, default is false. Whether to crop image or resize.
     * @return bool|array False on failure. Returned array matches parameters for imagecopyresampled() PHP function.
     */
    function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = false) {
    
    	if ($orig_w <= 0 || $orig_h <= 0)
    		return false;
    	// at least one of dest_w or dest_h must be specific
    	if ($dest_w <= 0 && $dest_h = $orig_w && $new_h >= $orig_h )
    		return false;
    
    	// the return array matches the parameters to imagecopyresampled()
    	// int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
    	return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
    
    }
    

    Some people have looked at this and felt that there was no way to override the $s_y = floor( ($orig_h - $crop_h) / 2 ); line without hacking core. Well, that’s iffy, but if you scroll up above, you’ll see something that lets you basically ‘short-circuit’ the function in question:

    // plugins can use this to provide custom resize dimensions
    $output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );
    if ( null !== $output )
    	return $output;
    

    So here’s our function to make all crops start at (0,0) — customize it as you like:

    function my_awesome_image_resize_dimensions( $payload, $orig_w, $orig_h, $dest_w, $dest_h, $crop ){
    
    	// Change this to a conditional that decides whether you 
    	// want to override the defaults for this image or not.
    	if( false )
    		return $payload;
    
    	if ( $crop ) {
    		// crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
    		$aspect_ratio = $orig_w / $orig_h;
    		$new_w = min($dest_w, $orig_w);
    		$new_h = min($dest_h, $orig_h);
    
    		if ( !$new_w ) {
    			$new_w = intval($new_h * $aspect_ratio);
    		}
    
    		if ( !$new_h ) {
    			$new_h = intval($new_w / $aspect_ratio);
    		}
    
    		$size_ratio = max($new_w / $orig_w, $new_h / $orig_h);
    
    		$crop_w = round($new_w / $size_ratio);
    		$crop_h = round($new_h / $size_ratio);
    
    		$s_x = 0; // [[ formerly ]] ==> floor( ($orig_w - $crop_w) / 2 );
    		$s_y = 0; // [[ formerly ]] ==> floor( ($orig_h - $crop_h) / 2 );
    	} else {
    		// don't crop, just resize using $dest_w x $dest_h as a maximum bounding box
    		$crop_w = $orig_w;
    		$crop_h = $orig_h;
    
    		$s_x = 0;
    		$s_y = 0;
    
    		list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h );
    	}
    
    	// if the resulting image would be the same size or larger we don't want to resize it
    	if ( $new_w >= $orig_w && $new_h >= $orig_h )
    		return false;
    
    	// the return array matches the parameters to imagecopyresampled()
    	// int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
    	return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
    
    }
    add_filter( 'image_resize_dimensions', 'my_awesome_image_resize_dimensions', 10, 6 );
    
  • Create New Admin Account in WordPress via FTP

    Another handy little snippet for WordPress …

    Have you ever had a client need help on their WordPress site, and have FTP access, but not actually give you a WordPress account to use? Just paste this snippet into their current theme’s functions.php file, or add it to a new file in their ~/wp-content/mu-plugins/ folder, and WordPress will automatically create an admin account for you to use!

    Oh — and don’t forget to change the credentials that are included to your own. If there is already an account with the username or email address specified, it will fail and not do diddly squat.

    
    function add_admin_acct(){
    	$login = 'myacct1';
    	$passw = 'mypass1';
    	$email = 'myacct1@mydomain.com';
    
    	if ( !username_exists( $login )  && !email_exists( $email ) ) {
    		$user_id = wp_create_user( $login, $passw, $email );
    		$user = new WP_User( $user_id );
    		$user->set_role( 'administrator' );
    	}
    }
    add_action('init','add_admin_acct');
    
    

    Remember … with great power comes great responsibility. Don’t abuse it.

  • Toggle All Checkboxes with jQuery

    Just a little snippet I worked up that may be useful to someone …

    jQuery(document).ready(function($){
    $('div#checkall-wrapper input[type=checkbox]').click(function(){
    	if( $(this).attr('checked') ){
    		$('tdiv#wraparound-targets input[type=checkbox]').attr('checked','checked');
    	}else{
    		$('div#wraparound-targets input[type=checkbox]').removeAttr('checked');
    	}
    });
    });
    

    Make sense?

  • Ndizi Project Management 0.9.6 PRE-RELEASE

    So, largely still a work-in-progress, I overhauled how most of the functions are written and abstracted many of the grunt work out. The client front-end page probably breaks like crazy, I’ll be getting that tomorrow, but for anyone who wants to take a look at it as-is, here goes:

    Ndizi Class 0.9.6 Snapshot

    The code in the back is a -lot- cleaner. I’ve abstracted alot of the form creation into sub-functions, as well as tabular display. Also built in a capability for filters, and added ‘active’ properties to clients and projects. The structure is in place to add comments and file attachments to things, but I need to sort out use-cases and how to actually display them. I’m currently thinking maybe a lightbox pop-up. Not sure.

    Any bug reports appreciated. Feature suggestions also welcome, but they’ll be addressed in the coming week or two.

  • Ndizi Project Management v0.9.5.6

    Whoo!  Finally got Invoices to the point where I’m mostly happy with them.

    Just gotta work out a good way of tying time reports to invoices, and it’ll be finished!  Well … the core invoicing functionality, anyways.

    I’ve had several people e-mailing me lately about road-maps for the future of the plugin.  My plans from here are to do the following: (more…)

  • Ndizi Project Management v0.9.5.2

    A couple minor bug fixes and upgrades.  Adds in time form at the top of the logged in admin pages, as well as migrates some data to the actual WordPress dashboard. (more…)

  • Ndizi Project Management v0.9.5

    Progressive release … most everything but invoices works and is rolled in now, including client front-end login.  Style however you like, default styling may be introduced in future releases. (more…)