10, "offset" => 10, "post_type" => 'any', "post_status" => 'any' )); foreach ( $allposts as $_post ) { $postmeta = get_post_meta($postinfo->ID, $key); die( '
' . print_r( $postmeta, true ) . ''); } $keys = array('address', 'address2', 'city', 'state', 'zip'); //Add post meta keys here foreach ( $keys as $key ) { foreach( $allposts as $postinfo) { // Fetch array of custom field values //print_r($postinfo); if (!empty($postmeta) ) { // Delete the custom field for this post (all occurrences) delete_post_meta($postinfo->ID, $key); // Insert one and only one custom field update_post_meta($postinfo->ID, $key, $postmeta[0]); } } } break; default: break; } //$wpdb->query( "DELETE a,b,c FROM {$wpdb->posts} a LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id) LEFT JOIN {$wpdb->postmeta} c ON (a.ID = c.post_id) WHERE a.post_type = 'revision'" ); //$wpdb->query( "DELETE pm FROM wp_postmeta pm LEFT JOIN wp_posts wp ON wp.ID = pm.post_id WHERE wp.ID IS NULL;" ); //$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE ('_site_transient_%');" ); //$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE ('_transient_%');" ); } /** * Looks for a json or a php file in specified directory, if the file is not found traverse up and look for it again until its found or until a document root is reached * * * @todo Honor the "nocase" option setting. * @todo Perhaps wrap simplexml_load_file into - potanin@UD * * @since 0.3.2 * @method findUp * @param string $name - Name of file to find. * @param string $cwd - Directory to start seeking from. Defaults to __DIR__ * @param string $required - If the file is required - if not found, will trigger an error. * @author tosheen@UD * @return array|bool|mixed|\SimpleXMLElement */ static public function findUp( $name = false, $cwd = false, $required = false ) { // No name provided, bail. if( !$name ) { return false; } // If first argument appears to be an object/array, treat it as a configuration object. if( is_array( $name ) || is_object( $name ) ) { // Apply default settings to passed argument. $_settings = self::defaults( $name, array( "cwd" => $cwd ? $cwd : null, "required" => $required ? $required : false, "nocase" => true )); $name = $_settings->name; $cwd = $_settings->cwd; $required = $_settings->required; $nocase = $_settings->nocase; } // No CWD set, backtrace to determine caller. $cwd = $cwd ? $cwd : dirname( self::backtrace_caller()->file ); // Determine if file is JSON $fileData = explode( '.', $name ); $fileExtension = $fileData[ count( $fileData ) - 1 ]; // Determine traverse path $_path = ( !empty( $cwd ) ? $cwd : $_SERVER[ 'DOCUMENT_ROOT' ] ); $file = $_path . DIRECTORY_SEPARATOR . $name; // Trigger Error and bail on failures. if( !is_dir( $_path ) ) { // Trigger error if required, otherwise fail silently. if( $required ) { trigger_error( __( 'Required file not found.', self::$text_domain ), E_USER_ERROR ); } return false; } if( file_exists( $file ) ) { // Fetch and parse JSON. if( $fileExtension === 'json' ) { return json_decode( file_get_contents( $file ) ); } // Fetch and parse XML. if( $fileExtension === 'xml' ) { return simplexml_load_file( $file ); } // Include all others. return include_once( $file ); } if( $_path != $_SERVER[ 'DOCUMENT_ROOT' ] ) { $lastDirSeparator = strrpos( $_path, DIRECTORY_SEPARATOR, -1 ); $_path = substr( $_path, 0, $lastDirSeparator ); return self::findUp( $name, $_path ); } // Trigger error if file was required. if( $required ) { trigger_error( __( 'Required file not found.', self::$text_domain ), E_USER_ERROR ); } // Couldn't find anything return false; } /** * Get Caller Object * * @method backtrace_caller * @since 0.3.2 * @author potanin@UD * @param int $depth * @return object */ static public function backtrace_caller( $depth = 1 ) { // Always add one level to backtrace. $_backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, ( $depth ? $depth : 1 ) + 1 ); // Return first hit as object, or a scaffolded object. return $_backtrace[1] ? (object) $_backtrace[1] : (object) array( 'file' => null ); } /** * Set Dot-Notated Array Value * * @param array $arr * @param $path * @param $val * * @return mixed */ static public function _set_val( array &$arr, $path, $val ) { $loc = & $arr; foreach( explode( '.', $path ) as $step ) { $loc = & $loc[ $step ]; } return $loc = $val; } /** * Convert dot-notated array key->value items to nested object * * @param $items * @return array */ static public function unwrap( $items ) { $_result = array(); foreach( (array) $items as $key => $value ) { self::_set_val( $_result, $key, $value ); } return (array) $_result; } /** * Wrapper for wp_parse_args. * * @author potanin@UD * @since 0.3.0 * @param $args * @param $defaults * * @return object */ static public function parse_args( $args, $defaults ) { return (object) wp_parse_args( $args, $defaults ); } /** * Parses Query. * HACK. The current logic solves the issue of max_input_vars in the case if query is huge. * * @see parse_str() Default PHP function * @version 1.1 * @author peshkov@UD * @param $request * @return array|mixed */ static public function parse_str( $request ) { $data = array(); $tokens = explode( "&", $request ); foreach ( $tokens as $token ) { $token = str_replace( '%2B', md5( '%2B' ), $token ); $arr = array(); parse_str( $token, $arr ); array_walk_recursive( $arr, function( &$value,$key ) { $value = str_replace( md5( "%2B" ), "+", $value ); }); $data = self::extend( $data, $arr ); } return $data; } /** * Deep Conversion * * @updated 2.0 * @since 0.1 */ static public function array_to_object( $array = array() ) { return json_decode( json_encode( $array ) ); } /** * Recursively converts object to array * * @since 2.0 * @author peshkov@UD */ static public function object_to_array( $data ) { if ( is_object( $data ) ) { $data = get_object_vars( $data ); } if ( is_array( $data ) ) { foreach ( $data as $k => $v ) { if ( is_object( $v ) ) { $data[ $k ] = self::object_to_array( $v ); } } } return $data; } /** * Parse standard WordPress readme file * * @source Readme Parser ( http://www.tomsdimension.de/wp-plugins/readme-parser ) * @author potanin@UD */ static public function parse_readme( $readme_file = false ) { if( !$readme_file ) { $readme_file = untrailingslashit( TEMPLATEPATH ) . '/readme.txt'; } $file = @file_get_contents( $readme_file ); if( !$file ) { return false; } $file = preg_replace( "/(\n\r|\r\n|\r|\n)/", "\n", $file ); // headlines $s = array( '===', '==', '=' ); $r = array( 'h2', 'h3', 'h4' ); for( $x = 0; $x < sizeof( $s ); $x++ ) { $file = preg_replace( '/(.*?)' . $s[ $x ] . '(?!\")(.*?)' . $s[ $x ] . '(.*?)/', '$1<' . $r[ $x ] . '>$2' . $r[ $x ] . '>$3', $file ); } // inline $s = array( '\*\*', '\'' ); $r = array( 'b', 'code' ); for( $x = 0; $x < sizeof( $s ); $x++ ) { $file = preg_replace( '/(.*?)' . $s[ $x ] . '(?!\s)(.*?)(?!\s )' . $s[ $x ] . '(.*?)/', '$1<' . $r[ $x ] . '>$2' . $r[ $x ] . '>$3', $file ); } // ' _italic_ ' $file = preg_replace( '/(\s)_(\S.*?\S)_(\s|$)/', '$2 ', $file ); // ul lists $s = array( '\*', '\+', '\-' ); for( $x = 0; $x < sizeof( $s ); $x++ ) { $file = preg_replace( '/^[ ' . $s[ $x ] . ' ](\s)(.*?)(\n|$)/m', '
* strip_protected_keys( $my_array, array( 'prefix' => '$$' ) );
*
*
* @since 2.0
* @author potanin@UD
*/
static public function strip_protected_keys( $array, $args = '' ) {
$args = wp_parse_args( $args, array( 'prefix' => '_' ) );
foreach( (array) $array as $key => $value ) {
if( strpos( $key, $args[ 'prefix' ] ) === 0 ) {
unset( $array[ $key ] );
continue;
}
if( is_array( $value ) ) {
$array[ $key ] = self::strip_protected_keys( $value, $args );
}
}
$array = array_filter( $array );
return $array;
}
/**
* Recursively remove empty values from array.
*
* @method array_filter_deep
* @for Utility
*
* @version 1.0.1
* @since 1.0.3
* @author potanin@UD
*/
static public function array_filter_deep( $haystack = array() ) {
foreach( (array) $haystack as $key => $value ) {
if( is_object( $value ) || is_array( $value ) ) {
if( is_object( $haystack ) ) {
$haystack->{$key} = self::array_filter_deep( (array) $value );
} else if( is_array( $haystack ) ) {
$haystack[ $key ] = self::array_filter_deep( (array) $value );
}
}
}
return array_filter( (array) $haystack );
}
/**
* Determines if a passed timestamp is newer than a requirement.
*
* Usage: UD_API::is_fresher_than( $timestamp, '5 minutes' );
*
* @since 1.0.3
*/
static public function fresher_than( $time, $ago = '1 week' ) {
return ( strtotime( "-" . $ago ) < $time ) ? true : false;
}
/**
* Starts a timer for the passed string.
*
* @since 1.0.0.2
* @author potanin@UD
*/
static public function timer_start( $function = 'global' ) {
global $ud_api;
return $ud_api[ 'timers' ][ $function ][ 'start' ] = microtime( true );
}
/**
* Stop a timer.
*
* @since 1.0.0.2
* @author potanin@UD
*/
static public function timer_stop( $function = 'global', $precision = 2 ) {
global $ud_api;
return $ud_api[ 'timers' ][ $function ][ 'start' ] ? round( microtime( true ) - $ud_api[ 'timers' ][ $function ][ 'start' ], $precision ) : false;
}
/**
* Start Profiling, can also double as timer.
*
* Profiling will only start if another profiling process is not already running.
* XHProf is required, other profilers may be added later.
*
* @updated 1.0.4
* @since 1.0.0.2
* @author potanin@UD
*/
static public function profiler_start( $method = false, $args = false ) {
global $ud_api;
if( $ud_api[ 'profiling_now' ] && ( $ud_api[ 'profiling_now' ] != $method ) ) {
return;
}
define( 'UD_API_Profiling', true );
if( extension_loaded( 'xhprof' ) && function_exists( 'xhprof_enable' ) ) {
xhprof_enable( XHPROF_FLAGS_CPU | XHPROF_FLAGS_NO_BUILTINS | XHPROF_FLAGS_MEMORY, $args );
}
return self::timer_start( $ud_api[ 'profiling_now' ] = $method );
}
/**
* Stop Profiling.
*
* @since 1.0.0.2
* @author potanin@UD
*/
static public function profiler_stop( $method = false, $args = false ) {
global $ud_api;
if( $ud_api[ 'profiling_now' ] && ( $ud_api[ 'profiling_now' ] != $method ) ) {
return;
}
if( extension_loaded( 'xhprof' ) && class_exists( 'XHProfRuns_Default' ) ) {
$xhprof_data = xhprof_disable();
$xhprof_runs = new XHProfRuns_Default();
$xhprof_runs->save_run( $xhprof_data, $method );
}
unset( $ud_api[ 'profiling_now' ] );
return self::timer_stop( $method );
}
/**
* Attempt to download a remote files attachments
*
* @param bool $images
* @param array $args
*
* @return bool|object
*/
static public function image_fetch( $images = false, $args = array() ) {
$images = array_filter( (array) $images );
//** Image URLs may be passed as string or array, or none at all */
if( count( $images ) < 1 ) {
return false;
}
self::timer_start( __METHOD__ );
$args = wp_parse_args( $args, array(
'upload_dir' => false,
'timeout' => 30,
) );
/**
* Regular Image Download.
*/
foreach( (array) $images as $count => $url ) {
$url = esc_url_raw( $url );
$_image = array(
'source_url' => $url,
'error' => false
);
//** Set correct filename ( some URLs can have not valid file extensions ) */
$filename = sanitize_file_name( basename( $url ) );
$ext = false;
$filetype = wp_check_filetype( $filename );
if( !$filetype[ 'ext' ] ) {
$file_headers = get_headers( $url, 1 );
if( strpos( $file_headers[ 0 ], '200 OK' ) ) {
if( isset( $file_headers[ 'Content-Type' ] ) ) {
$file_mime = sanitize_mime_type( $file_headers[ 'Content-Type' ] );
switch( $file_mime ) {
case "image/gif":
$ext = 'gif';
break;
case "image/jpeg":
$ext = 'jpg';
break;
case "image/png":
$ext = 'png';
break;
case "image/bmp":
$ext = 'bmp';
break;
}
if( $ext ) {
$filename .= '.' . $ext;
}
}
}
} else {
$ext = $filetype[ 'ext' ];
}
$_wp_error_data = array(
'url' => $url,
'filename' => $filename,
'file_type' => $ext,
);
//** We MUST NOT allow to upload not-image files */
if( !$ext || !in_array( $ext, array( 'gif', 'jpg', 'png', 'bmp', 'jpeg' ) ) ) {
$_image[ 'error' ] = new WP_Error( __METHOD__, __( 'Invalid file type.', self::$text_domain ), $_wp_error_data );
}
//** Set file path */
if( !empty( $args[ 'upload_dir' ] ) ) {
if( wp_mkdir_p( $args[ 'upload_dir' ] ) ) {
$_image[ 'file' ] = trailingslashit( $args[ 'upload_dir' ] ) . wp_unique_filename( $args[ 'upload_dir' ], $filename );
} else {
$_image[ 'error' ] = new WP_Error( __METHOD__, __( 'Could not create mentioned directory.', self::$text_domain ) );
}
} else {
$wp_upload_bits = wp_upload_bits( $filename, null, '' );
if( $wp_upload_bits[ 'error' ] ) {
$_image[ 'error' ] = new WP_Error( __METHOD__, $wp_upload_bits[ 'error' ], $wp_upload_bits );
}
$_image = self::extend( $_image, $wp_upload_bits );
}
if( !is_wp_error( $_image[ 'error' ] ) ) {
$wp_remote_request = wp_remote_request( $url, array_filter( array(
'method' => 'GET',
'timeout' => $args[ 'timeout' ],
'stream' => true,
'filename' => $_image[ 'file' ]
) ) );
if( is_wp_error( $wp_remote_request ) ) {
$wp_remote_request->add_data( $_wp_error_data );
$_image[ 'error' ] = $wp_remote_request;
} else {
$_image[ 'file' ] = $wp_remote_request[ 'filename' ];
$_image[ 'filesize' ] = filesize( $_image[ 'file' ] );
/* Disabled. Was failing multiple images
if( isset( $wp_remote_request[ 'headers' ][ 'content-length'] ) && $_image[ 'filesize' ] != $wp_remote_request[ 'headers' ][ 'content-length'] ) {
$_image[ 'error' ] = new WP_Error( 'image_fetch', __( 'Remote file has incorrect size', self::$text_domain ), array(
'headers' => $wp_remote_request[ 'headers' ],
'image' => $_image
));
}*/
if( 0 == $_image[ 'filesize' ] ) {
$_image[ 'error' ] = new WP_Error( __METHOD__, __( 'Zero size file downloaded', self::$text_domain ) );
}
$_image = self::extend( $_image, wp_check_filetype( $_image[ 'file' ] ) );
//require_once( ABSPATH . 'wp-admin/includes/image.php' );
//wp_update_attachment_metadata( $row->attachment_id, wp_generate_attachment_metadata( $row->attachment_id, $upload[ 'file' ] ) );
}
}
if( is_wp_error( $_image[ 'error' ] ) ) {
@unlink( $_image[ 'file' ] );
}
$return[ $count ] = (object) array_filter( $_image );
} //** End foreach */
return (object) array(
'images' => $return,
'timer' => self::timer_stop( __METHOD__ )
);
}
/**
* Checks if images exist and returns images dimensions
*
* @param mixed $images Image url
* @param mixed $args
*
* @return array
* @author peshkov@UD
*/
static public function image_dimensions( $images = false, $args = array() ) {
$result = array();
$images = array_filter( (array) $images );
//** Image URLs may be passed as string or array, or none at all */
if( count( $images ) < 1 ) {
return $result;
}
self::timer_start( __METHOD__ );
//** Params below are used only by RIM ( getMultiImageTypeAndSize ) **/
$args = wp_parse_args( $args, array(
'max_num_of_threads' => 10,
'time_limit' => 30,
'curl_connect_timeout' => 2,
'curl_timeout' => 3,
) );
//** If PHP 5.3.0, and rim class found, we use it. In other case we use default function getimagesize() */
if( version_compare( PHP_VERSION, '5.3.0' ) >= 0 && method_exists( 'rim', 'getMultiImageTypeAndSize' ) ) {
$rim = new rim();
$response = $rim->getMultiImageTypeAndSize( $images, $args );
if( is_array( $response ) ) {
foreach( $response as $r ) {
$result[ ] = array(
'width' => isset( $r[ 'image_data' ][ 'width' ] ) ? $r[ 'image_data' ][ 'width' ] : 0,
'height' => isset( $r[ 'image_data' ][ 'height' ] ) ? $r[ 'image_data' ][ 'height' ] : 0,
'url' => isset( $r[ 'url' ] ) ? $r[ 'url' ] : false,
'error' => !empty( $r[ 'error' ] ) ? new WP_Error( 'image_fetch', __( 'Could not get image dimensions (headers)', 'wpp' ), $r[ 'error' ] ) : false
);
}
}
} else {
$result = array();
foreach( $images as $image ) {
$r = @getimagesize( $image );
$result[ ] = array(
'width' => isset( $r[ 0 ] ) ? $r[ 0 ] : 0,
'height' => isset( $r[ 1 ] ) ? $r[ 1 ] : 0,
'url' => $image,
'error' => empty( $r ) ? new WP_Error( 'image_fetch', __( 'Could not get image dimensions (headers)', 'wpp' ) ) : false
);
}
}
return $result;
}
/**
* Converts slashes for Windows paths.
*
* @since 1.0.0.0
* @source Flawless
* @author potanin@UD
*/
static public function fix_path( $path ) {
return str_replace( '\\', '/', $path );
}
/**
* Applies trim() function to all values in an array
*
* @source WP-Property
* @since 0.6.0
*/
static public function trim_array( $array = array() ) {
foreach( (array) $array as $key => $value ) {
if( is_object( $value ) ) {
continue;
}
$array[ $key ] = is_array( $value ) ? self::trim_array( $value ) : trim( $value );
}
return $array;
}
/**
* Returns all available image sizes
*
* @method all_image_sizes
* @for Utility
*
* @param $size {String}
*
* @returns array keys: 'width' and 'height'
*/
static public function all_image_sizes( $size = '' ) {
global $_wp_additional_image_sizes;
$image_sizes = (array) $_wp_additional_image_sizes;
$image_sizes[ 'thumbnail' ] = array(
'width' => intval( get_option( 'thumbnail_size_w' ) ),
'height' => intval( get_option( 'thumbnail_size_h' ) )
);
$image_sizes[ 'medium' ] = array(
'width' => intval( get_option( 'medium_size_w' ) ),
'height' => intval( get_option( 'medium_size_h' ) )
);
$image_sizes[ 'large' ] = array(
'width' => intval( get_option( 'large_size_w' ) ),
'height' => intval( get_option( 'large_size_h' ) )
);
foreach( (array) $image_sizes as $_size => $data ) {
$image_sizes[ $_size ] = array_filter( (array) $data );
$image_sizes[ $_size ][ 'label' ] = self::de_slug( $_size );
$image_sizes[ $_size ][ 'crop' ] = isset( $image_sizes[ $_size ][ 'crop' ] ) && $image_sizes[ $_size ][ 'crop' ] ? $image_sizes[ $_size ][ 'crop' ] : false;
}
if( $size ) {
return array_filter( (array) $image_sizes[ $size ] );
}
return array_filter( (array) $image_sizes );
}
/**
* Retrieves the attachment ID from the file URL ( guid )
*
* @global object $wpdb
*
* @param string $guid
*
* @return string
* @author peshkovUD
*/
static public function get_image_id_by_guid( $guid ) {
global $wpdb;
$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE guid='%s';", $guid ) );
return !empty( $attachment[ 0 ] ) ? $attachment[ 0 ] : false;
}
/**
* Returns Image link (url)
*
* If image with the current size doesn't exist, we try to generate it.
* If image cannot be resized, the URL to the main image (original) is returned.
*
* @todo Add something to check if requested image size is bigger than the original, in which case cannot be "resized"
* @todo Add a check to see if the specified image dimensions have changed. Right now only checks if slug exists, not the actualy size.
*
* @param bool $attachment_id
* @param bool $size
* @param array $args
*
* @return array|bool|mixed
*/
static public function get_image_link( $attachment_id = false, $size = false, $args = array() ) {
global $wp_properties;
if( !$size || !$attachment_id ) {
return false;
}
$image_sizes = self::all_image_sizes( $size );
$args = wp_parse_args( $args, array(
'cache_id' => sanitize_title( $attachment_id . $size ),
'return' => 'string',
'default' => '',
'cache_group' => 'ud_api'
) );
//** Added 'return' arg to avoid cache problems odokienko@UD */
$args[ 'cache_id' ] .= $args[ 'return' ];
if( $return = wp_cache_get( $args[ 'cache_id' ], $args[ 'cache_group' ] ) ) {
return $return;
}
$attachment_image_src = ( array ) wp_get_attachment_image_src( $attachment_id, $size );
//** If wp_get_attachment_image_src() returned the information we need, we return it */
if( empty( $image_sizes ) || ( is_array( $attachment_image_src ) && $attachment_image_src[ 1 ] == $image_sizes[ $size ][ 'width' ] ) ) {
$return = $args[ 'return' ] == 'string' ? $attachment_image_src[ 0 ] : array(
'url' => $attachment_image_src[ 0 ],
'link' => $attachment_image_src[ 0 ],
'width' => $attachment_image_src[ 1 ],
'height' => $attachment_image_src[ 2 ],
'crop' => $attachment_image_src[ 3 ]
);
wp_cache_set( $args[ 'cache_id' ], $return, $args[ 'cache_group' ] );
return $return;
}
//** If we are this far, that means that the returned image, if any, was not the right size, so we regenreate */
$image_resize = image_resize( get_attached_file( $attachment_id, true ), $image_sizes[ $size ][ 'width' ], $image_sizes[ $size ][ 'height' ], $image_sizes[ $size ][ 'crop' ] );
if( is_wp_error( $image_resize ) || !file_exists( $image_resize ) ) {
if( $attachment_image_src[ 0 ] ) {
$return = $args[ 'default' ] ? $args[ 'default' ] : $attachment_image_src[ 0 ];
} else {
$return = $args[ 'default' ];
}
}
//** If image was resized, we update metadata, cache our result, and return */
require_once( ABSPATH . 'wp-admin/includes/image.php' );
if( function_exists( 'wp_update_attachment_metadata' ) ) {
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, get_attached_file( $attachment_id, true ) ) );
}
$attachment_image_src = (array) wp_get_attachment_image_src( $attachment_id, $size );
$return = $args[ 'return' ] == 'string' ? $attachment_image_src[ 0 ] : array(
'url' => $attachment_image_src[ 0 ],
'link' => $attachment_image_src[ 0 ],
'width' => $attachment_image_src[ 1 ],
'height' => $attachment_image_src[ 2 ],
'crop' => $attachment_image_src[ 3 ]
);
wp_cache_set( $args[ 'cache_id' ], $return, $args[ 'cache_group' ] );
return $return;
}
/**
* Returns Image link (url) with custom size.
* Almost the same as get_image_link, but the current function can generate images with custom sizes.
* It generates image with custom size only once.
*
* @global $wpdb
*
* @param type $atts
*
* @return string
* @author peshkov@UD
* @since 0.2.5
*/
static function get_image_link_with_custom_size( $attachment_id, $width, $height, $crop = false ) {
global $wpdb;
// Sanitize
$height = absint( $height );
$width = absint( $width );
$needs_resize = true;
// Look through the attachment meta data for an image that fits our size.
$meta = wp_get_attachment_metadata( $attachment_id );
$upload_dir = wp_upload_dir();
$base_url = strtolower( $upload_dir[ 'baseurl' ] );
$src = trailingslashit( $base_url ) . $meta[ 'file' ];
foreach( $meta[ 'sizes' ] as $key => $size ) {
if( ( $size[ 'width' ] == $width && $size[ 'height' ] == $height ) || $key == sprintf( 'resized-%dx%d', $width, $height ) ) {
if( !empty( $size[ 'file' ] ) ) {
$src = str_replace( basename( $src ), $size[ 'file' ], $src );
}
$needs_resize = false;
break;
}
}
// If an image of such size was not found, we can create one.
if( $needs_resize ) {
$attached_file = get_attached_file( $attachment_id );
$resized = image_make_intermediate_size( $attached_file, $width, $height, $crop );
if( is_wp_error( $resized ) ) {
return $resized;
}
// Let metadata know about our new size.
$key = sprintf( 'resized-%dx%d', $width, $height );
$meta[ 'sizes' ][ $key ] = $resized;
if( !empty( $resized[ 'file' ] ) ) {
$src = str_replace( basename( $src ), $resized[ 'file' ], $src );
}
wp_update_attachment_metadata( $attachment_id, $meta );
// Record in backup sizes so everything's cleaned up when attachment is deleted.
$backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
if( !is_array( $backup_sizes ) ) $backup_sizes = array();
$backup_sizes[ $key ] = $resized;
update_post_meta( $attachment_id, '_wp_attachment_backup_sizes', $backup_sizes );
}
return array(
'url' => esc_url( $src ),
'width' => absint( $width ),
'height' => absint( $height ),
);
}
/**
* Insert array into an associative array before a specific key
*
* @source http://stackoverflow.com/questions/6501845/php-need-help-inserting-arrays-into-associative-arrays-at-given-keys
* @author potanin@UD
*/
static public function array_insert_before( $array, $key, $new ) {
$array = (array) $array;
$keys = array_keys( $array );
$pos = (int) array_search( $key, $keys );
return array_merge(
array_slice( $array, 0, $pos ),
$new,
array_slice( $array, $pos )
);
}
/**
* Insert array into an associative array after a specific key
*
* @source http://stackoverflow.com/questions/6501845/php-need-help-inserting-arrays-into-associative-arrays-at-given-keys
* @author potanin@UD
*/
static public function array_insert_after( $array, $key, $new ) {
$array = (array) $array;
$keys = array_keys( $array );
$pos = (int) array_search( $key, $keys ) + 1;
return array_merge(
array_slice( $array, 0, $pos ),
$new,
array_slice( $array, $pos )
);
}
/**
* Attemp to convert a plural US word into a singular.
*
* @todo API Service Candidate since we ideally need a dictionary reference.
* @author potanin@UD
*/
static public function depluralize( $word ) {
$rules = array( 'ss' => false, 'os' => 'o', 'ies' => 'y', 'xes' => 'x', 'oes' => 'o', 'ies' => 'y', 'ves' => 'f', 's' => '' );
foreach( array_keys( $rules ) as $key ) {
if( substr( $word, ( strlen( $key ) * -1 ) ) != $key )
continue;
if( $key === false )
return $word;
return substr( $word, 0, strlen( $word ) - strlen( $key ) ) . $rules[ $key ];
}
return $word;
}
/**
* Convert bytes into the logical unit of measure based on size.
*
* @source Flawless
* @since 1.0.0.0
* @author potanin@UD
*/
static public function format_bytes( $bytes, $precision = 2 ) {
_deprecated_function( __FUNCTION__, '2.3.0', 'size_format()' );
return size_format( $bytes, $precision );
}
/**
* Used to enable/disable/print SQL log
*
* Usage:
* self::sql_log( 'enable' );
* self::sql_log( 'disable' );
* $queries= self::sql_log( 'print_log' );
*
* @since 0.1.0
*/
static public function sql_log( $action = 'attach_filter' ) {
global $wpdb;
if( !in_array( $action, array( 'enable', 'disable', 'print_log' ) ) ) {
$wpdb->ud_queries[ ] = array( $action, $wpdb->timer_stop(), $wpdb->get_caller() );
return $action;
}
if( $action == 'enable' ) {
add_filter( 'query', array( __CLASS__, 'sql_log' ), 75 );
}
if( $action == 'disable' ) {
remove_filter( 'query', array( __CLASS__, 'sql_log' ), 75 );
}
if( $action == 'print_log' ) {
$result = array();
foreach( (array) $wpdb->ud_queries as $query ) {
$result[ ] = $query[ 0 ] ? $query[ 0 ] . ' (' . $query[ 1 ] . ')' : $query[ 2 ];
}
return $result;
}
}
/**
* Return data for UD Log
*
* @updated 1.04
* @sincde 1.03
* @note This is a proof of concept, in future it should be able to support AJAX calls so can be displayed via Dynamic Filter.
* @author potanin@UD
*/
static public function log( $message = '', $args = array() ) {
global $wpdb;
//** Prevents MySQL Gone Away. @todo Should check if connection exists before automatically connecting. */
//$wpdb->db_connect();
//** Create Log if it does not exist */
if( !$wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}ud_log';" ) ) {
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( "CREATE TABLE {$wpdb->prefix}ud_log (
id mediumint(9) NOT NULL AUTO_INCREMENT,
post_id mediumint(9) DEFAULT NULL COMMENT 'ID of related post.',
product VARCHAR(100) DEFAULT '' NOT NULL COMMENT 'Slug of related product.',
feature VARCHAR(100) DEFAULT '' NOT NULL COMMENT 'Slug of specific feature, if applicable.',
message text NOT NULL COMMENT 'Long description of log entry.',
type VARCHAR(100) DEFAULT '' NOT NULL COMMENT 'Type of variable stored in message. May be concatentaetd with other data for additional information.',
action VARCHAR(128) DEFAULT '' NOT NULL COMMENT 'If applicable, a slug for a specific action that triggered the entry.',
method VARCHAR(128) DEFAULT '' NOT NULL COMMENT 'If applicable, PHP method that triggered log entry.',
time int(11) NOT NULL,
UNIQUE KEY id (id),
KEY post_id (post_id),
KEY type (type)
);" );
}
$args = array_filter( (array) shortcode_atts( array(
'post_id' => null,
'type' => gettype( $message ),
'message' => maybe_serialize( $message ),
'product' => null,
'feature' => null,
'action' => null,
'method' => null,
'time' => time()
), $args ) );
//** Only the keys below may be updated via $args */
$wpdb->insert( $wpdb->prefix . 'ud_log', $args );
return $wpdb->insert_id ? $message : false;
}
/**
* Return data for UD Log
*
* @note This is a proof of concept, in future it should be able to support AJAX calls so can be displayed via Dynamic Filter.
* @author potanin@UD
*/
static public function get_log( $args = false ) {
global $wpdb;
$args = wp_parse_args( $args, array(
'offset' => 0,
'limit' => 100,
'last_id' => false,
'sort_type' => 'ASC',
'direction' => 'greater',
'product' => '',
'post_id' => false,
) );
$where = array();
if( $args[ 'last_id' ] && $args[ 'last_id' ] > 1 ) {
$direction = '';
switch( $args[ 'direction' ] ) {
case 'greater':
$direction = '>';
break;
case 'less':
$direction = '<';
break;
}
if( !empty( $direction ) ) {
$where[ ] = " l.id {$direction} {$args['last_id']} ";
}
}
foreach( $args as $k => $v ) {
if( in_array( $k, array( 'product', 'post_id' ) ) && !empty( $v ) ) {
if( is_array( $v ) ) {
$where[ ] = " l.{$k} IN ( '" . implode( "','", $v ) . "' ) ";
} else {
$where[ ] = " l.{$k} = '{$v}' ";
}
}
}
if( !empty( $where ) ) {
$where = " WHERE " . implode( " AND ", $where ) . " ";
} else {
$where = '';
}
$response = $wpdb->get_results( "
SELECT l.*, p.post_title
FROM {$wpdb->prefix}ud_log l
LEFT JOIN {$wpdb->posts} p ON l.post_id = p.ID
{$where}
ORDER BY l.id {$args['sort_type']}
LIMIT {$args['offset']}, {$args['limit']};
" );
//die( '' . print_r( $wpdb->last_query ,true) . '' ); return $response; } /** * Removes data from Logs table * * @param mixed $args * * @author peshkov@UD */ static public function clear_log( $args = array() ) { global $wpdb; $args = array_filter( self::prepare_to_sql( wp_parse_args( $args, array( 'id' => false, 'product' => false, 'feature' => false, 'product_id' => false, 'type' => false, 'action' => false, ) ) ) ); $where = ""; foreach( $args as $k => $v ) { $where .= empty( $where ) ? " WHERE " : " AND "; $where .= " {$k} = '{$v}' "; } return $wpdb->query( "DELETE FROM {$wpdb->prefix}ud_log {$where}" ); } /** * Add an entry to the plugin-specifig log. * * Creates log if one does not exist. * *
* UD\Utility::log( "Settings updated." );
*
*
* @depreciated peshkov@UD
*/
static public function _log( $message = false, $args = array() ) {
$args = wp_parse_args( $args, array(
'type' => 'default',
'object' => false,
'prefix' => 'ud',
) );
extract( $args );
$log = "{$prefix}_log";
if( !did_action( 'init' ) ) {
_doing_it_wrong( __FUNCTION__, sprintf( __( 'You cannot call UD\Utility::log() before the %1$s hook, since the current user is not yet known.' ), 'init' ), '3.4' );
}
$current_user = wp_get_current_user();
$this_log = get_option( $log );
if( empty( $this_log ) ) {
$this_log = array();
$entry = array(
'time' => time(),
'message' => __( 'Log Started.', self::$text_domain ),
'user' => $current_user->ID,
'type' => $type
);
}
if( $message ) {
$entry = array(
'time' => time(),
'message' => $message,
'user' => $type == 'system' ? 'system' : $current_user->ID,
'type' => $type,
'object' => $object
);
}
if( !is_array( $entry ) ) {
return false;
}
array_push( $this_log, $entry );
$this_log = array_filter( $this_log );
update_option( $log, $this_log );
return true;
}
/**
* Helpder function for figuring out if another specific function is a predecesor of current function.
*
* @since 1.0.0.0
* @author potanin@UD
*/
static public function _backtrace_function( $function = false ) {
foreach( debug_backtrace() as $step ) {
if( $function && $step[ 'function' ] == $function ) {
return true;
}
}
}
/**
* Helpder function for figuring out if a specific file is a predecesor of current file.
*
* @since 1.0.0.0
* @author potanin@UD
*/
static public function _backtrace_file( $file = false ) {
foreach( debug_backtrace() as $step ) {
if( $file && basename( $step[ 'file' ] ) == $file ) {
return true;
}
}
}
/**
* Fixed serialized arrays which sometimes get messed up in WordPress
*
* @source http://shauninman.com/archive/2008/01/08/recovering_truncated_php_serialized_arrays
*/
static public function repair_serialized_array( $serialized ) {
$tmp = preg_replace( '/^a:\d+:\{/', '', $serialized );
return self::repair_serialized_array_callback( $tmp ); // operates on and whittles down the actual argument
}
/**
* The recursive function that does all of the heavy lifing. Do not call directly.
*/
static public function repair_serialized_array_callback( &$broken ) {
$data = array();
$index = null;
$len = strlen( $broken );
$i = 0;
while( strlen( $broken ) ) {
$i++;
if( $i > $len ) {
break;
}
if( substr( $broken, 0, 1 ) == '}' ) // end of array
{
$broken = substr( $broken, 1 );
return $data;
} else {
$bite = substr( $broken, 0, 2 );
switch( $bite ) {
case 's:': // key or value
$re = '/^s:\d+:"([^\"]*)";/';
if( preg_match( $re, $broken, $m ) ) {
if( $index === null ) {
$index = $m[ 1 ];
} else {
$data[ $index ] = $m[ 1 ];
$index = null;
}
$broken = preg_replace( $re, '', $broken );
}
break;
case 'i:': // key or value
$re = '/^i:(\d+);/';
if( preg_match( $re, $broken, $m ) ) {
if( $index === null ) {
$index = (int) $m[ 1 ];
} else {
$data[ $index ] = (int) $m[ 1 ];
$index = null;
}
$broken = preg_replace( $re, '', $broken );
}
break;
case 'b:': // value only
$re = '/^b:[01];/';
if( preg_match( $re, $broken, $m ) ) {
$data[ $index ] = (bool) $m[ 1 ];
$index = null;
$broken = preg_replace( $re, '', $broken );
}
break;
case 'a:': // value only
$re = '/^a:\d+:\{/';
if( preg_match( $re, $broken, $m ) ) {
$broken = preg_replace( '/^a:\d+:\{/', '', $broken );
$data[ $index ] = self::repair_serialized_array_callback( $broken );
$index = null;
}
break;
case 'N;': // value only
$broken = substr( $broken, 2 );
$data[ $index ] = null;
$index = null;
break;
}
}
}
return $data;
}
/**
* Determine if an item is in array and return checked
*
* @since 0.5.0
*/
static public function checked_in_array( $item, $array ) {
if( is_array( $array ) && in_array( $item, $array ) ) {
echo ' checked="checked" ';
}
}
/**
* Check if the current WP version is older then given parameter $version.
*
* @param string $version
*
* @return bool
* @since 1.0.0.0
* @author peshkov@UD
*/
static public function is_older_wp_version( $version = '' ) {
if( empty( $version ) || (float) $version == 0 ) return false;
$current_version = get_bloginfo( 'version' );
/** Clear version numbers */
$current_version = preg_replace( "/^([0-9\.]+)-(.)+$/", "$1", $current_version );
$version = preg_replace( "/^([0-9\.]+)-(.)+$/", "$1", $version );
return ( (float) $current_version < (float) $version ) ? true : false;
}
/**
* Determine if any requested template exists and return path to it.
*
* == Usage ==
* The function will search through: STYLESHEETPATH, TEMPLATEPATH, and any custom paths you pass as second argument.
*
* $best_template = UD\Utility::get_template_part( array(
* 'template-ideal-match',
* 'template-default',
* ), array( PATH_TO_MY_TEMPLATES );
*
* Note: load_template() extracts $wp_query->query_vars into the loaded template, so to add any global variables to the template, add them to
* $wp_query->query_vars prior to calling this function.
*
* @param mixed $name List of requested templates. Will be return the first found
* @param array $path [optional]. Method tries to find template in theme, but also it can be found in given list of pathes.
* @param array $opts [optional]. Set of additional params:
* - string $instance. Template can depend on instance. For example: facebook, PDF, etc. Uses filter: ud::template_part::{instance}
* - boolean $load. if true, rendered HTML will be returned, in other case, only found template's path.
* @load boolean [optional]. If true and a template is found, the template will be loaded via load_template() and returned as a string
* @author peshkov@UD
* @version 1.1
*/
static public function get_template_part( $name, $path = array(), $opts = array() ) {
$name = (array)$name;
$template = "";
/**
* Set default instance.
* Template can depend on instance. For example: facebook, PDF, etc.
*/
$instance = apply_filters( "ud::current_instance", "default" );
$opts = wp_parse_args( $opts, array(
'instance' => $instance,
'load' => false,
) );
//** Allows to add/change templates storage directory. */
$path = apply_filters( "ud::template_part::path", $path, $name, $opts );
foreach ( $name as $n ) {
$n = "{$n}.php";
$template = locate_template( $n, false );
if ( empty( $template ) && !empty( $path ) ) {
foreach ( (array)$path as $p ) {
if ( file_exists( $p . "/" . $n ) ) {
$template = $p . "/" . $n;
break( 2 );
}
}
}
if ( !empty( $template ) ) break;
}
$template = apply_filters( "ud::template_part::{$opts['instance']}", $template, array( 'name' => $name, 'path' => $path, 'opts' => $opts ) );
//** If match and load was requested, get template and return */
if( !empty( $template ) && $opts[ 'load' ] == true ) {
ob_start();
load_template( $template, false );
return ob_get_clean();
}
return !empty( $template ) ? $template : false;
}
/**
* The goal of function is going through specific filters and return (or print) classes.
* This function should not be called directly.
* Every ud plugin/theme should have own short function ( wrapper ) for calling it. E.g., see: wpp_css().
* So, use it in template as:
* print_r( self::get_log() );
*
*
* $param string Event description
*
* @depreciated peshkov@UD
* @uses get_option()
* @uses update_option()
* @return array Using the get_option function returns the contents of the log.
*
* @param bool $args
*
* @return array Using the get_option function returns the contents of the log.
*/
static public function _get_log( $args = false ) {
$args = wp_parse_args( $args, array(
'limit' => 20,
'prefix' => 'ud'
) );
extract( $args );
$this_log = get_option( $prefix . '_log' );
if( empty( $this_log ) ) {
$this_log = self::log( false, array( 'prefix' => $prefix ) );
}
$entries = (array) get_option( $prefix . '_log' );
$entries = array_reverse( $entries );
$entries = array_slice( $entries, 0, $args[ 'args' ] ? $args[ 'args' ] : $args[ 'limit' ] );
return $entries;
}
/**
* Delete UD log for this plugin.
*
* @uses update_option()
*/
static public function delete_log( $args = array() ) {
$args = wp_parse_args( $args, array(
'prefix' => 'ud'
) );
extract( $args );
$log = "{$prefix}_log";
delete_option( $log );
}
/**
* Creates Admin Menu page for UD Log
*
* @todo Need to make sure this will work if multiple plugins utilize the UD classes
* @see function show_log_page
* @since 1.0.0
* @uses add_action() Calls 'admin_menu' hook with an anonymous ( lambda-style ) function which uses add_menu_page to create a UI Log page
*/
static public function add_log_page() {
if( did_action( 'admin_menu' ) ) {
_doing_it_wrong( __FUNCTION__, sprintf( __( 'You cannot call UD\Utility::add_log_page() after the %1$s hook.' ), 'init' ), '3.4' );
return false;
}
add_action( 'admin_menu', function() {
add_menu_page( __( 'Log', UD_API_Transdomain ), __( 'Log', UD_API_Transdomain ), current_user_can( 'manage_options' ), 'ud_log', array( 'UD_API', 'show_log_page' ) );
});
}
/**
* Displays the UD UI log page.
*
* @todo Add button or link to delete log
* @todo Add nonce to clear_log functions
* @todo Should be refactored to implement adding LOG tabs for different instances (wpp, wpi, wp-crm). peshkov@UD
*
* @since 1.0.0.0
*/
static public function show_log_page() {
if( $_REQUEST[ 'ud_action' ] == 'clear_log' ) {
self::delete_log();
}
$output = array();
$output[ ] = '';
$output[ ] = '| ' . __( 'Timestamp', self::$text_domain ) . ' | '; $output[ ] = '' . __( 'Type', self::$text_domain ) . ' | '; $output[ ] = '' . __( 'Event', self::$text_domain ) . ' | '; $output[ ] = '' . __( 'User', self::$text_domain ) . ' | '; $output[ ] = '' . __( 'Related Object', self::$text_domain ) . ' | '; $output[ ] = '
|---|---|---|---|---|
| ' . self::nice_time( $event[ 'time' ] ) . ' | '; $output[ ] = '' . $event[ 'type' ] . ' | '; $output[ ] = '' . $event[ 'message' ] . ' | '; $output[ ] = '' . ( is_numeric( $event[ 'user' ] ) ? get_userdata( $event[ 'user' ] )->display_name : __( 'None' ) ) . ' | '; $output[ ] = '' . $event[ 'object' ] . ' | '; $output[ ] = '