Adding Metaboxes in WordPress to your admin areas normally involves 3 steps:
This can be done much easier using Custom Metaboxes and Fields for WordPress, which is a metabox, custom fields and forms library. The library provides a bunch of custom fields and also allows you to add your own easily. Much easier to build new Metaboxes fast!
List of field types included:
Simple example from the CMB2 Github page
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
if ( file_exists( __DIR__ . '/cmb2/init.php' ) ) { require_once __DIR__ . '/cmb2/init.php'; } elseif ( file_exists( __DIR__ . '/CMB2/init.php' ) ) { require_once __DIR__ . '/CMB2/init.php'; } add_action( 'cmb2_init', 'cmb2_sample_metaboxes' ); /** * Define the metabox and field configurations. */ function cmb2_sample_metaboxes() { // Start with an underscore to hide fields from custom fields list $prefix = '_yourprefix_'; /** * Initiate the metabox */ $cmb = new_cmb2_box( array( 'id' => 'test_metabox', 'title' => __( 'Test Metabox', 'cmb2' ), 'object_types' => array( 'page', ), // Post type 'context' => 'normal', 'priority' => 'high', 'show_names' => true, // Show field names on the left // 'cmb_styles' => false, // false to disable the CMB stylesheet // 'closed' => true, // Keep the metabox closed by default ) ); // Regular text field $cmb->add_field( array( 'name' => __( 'Test Text', 'cmb2' ), 'desc' => __( 'field description (optional)', 'cmb2' ), 'id' => $prefix . 'text', 'type' => 'text', 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value // 'sanitization_cb' => 'my_custom_sanitization', // custom sanitization callback parameter // 'escape_cb' => 'my_custom_escaping', // custom escaping callback parameter // 'on_front' => false, // Optionally designate a field to wp-admin only // 'repeatable' => true, ) ); } |
The current Google Analytics Dashboard for WordPress integrates no Opt-Out to disable tracking, which is required in Europe. Here is a workaround for that.
Paste this into your theme function.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
if ( !is_user_logged_in() && class_exists('GADWP_Manager') ) { add_action('wp_head', 'ga_optout_script', 1); } function ga_optout_script(){ // Read GA Dashboard Settings $options = (array) json_decode(get_option('gadash_options')); // Get GA Dashboard profiles foreach($options['ga_dash_profile_list'] as $profile){ $ga_ua_profile[$profile[1]] = $profile[2]; } // Get active Analytics profile for the current website $active = $options['ga_dash_tableid_jail']; $activeUA = $ga_ua_profile[$active]; // Add opt-out script + active UA echo "<script> var gaProperty = '".$activeUA."'; var disableStr = 'ga-disable-' + gaProperty; if (document.cookie.indexOf(disableStr + '=true') > -1) { window[disableStr] = true; } function gaOptout() { document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/'; window[disableStr] = true; } </script>"; } |
Then add this to your data privacy document:
1 |
<a href="javascript:gaOptout()">Disable Google Analytics tracking</a> |
When the defer attribute is present in the script tag, it specifies that the script is executed when the page has finished parsing. A requirement that is enforced by Google for example (Page-Speed ranking).
Currently the WordPress wp_enqueue_script provides no easy way to add new attributes, but there is a way around that :)
The below hack / filter needs to be added to your theme function.php. The filter should be your preferred solution, as the clean_url filter has been deprecated.
Make sure that your website / theme is still loading after adding these changes. If needed you can add more exceptions, as I did for jQuery.
Hack for WordPress before 4.1
1 2 3 4 5 6 7 8 |
if(is_admin() === FALSE){ function defer_parsing_of_js ( $url ) { if ( FALSE === strpos( $url, '.js' ) ) return $url; if ( strpos( $url, 'jquery.js' ) ) return $url; return "$url' defer "; } add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 ); } |
Filter for WordPress 4.1+
Updated: 26.04.2015 – using clean Regexp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if(is_admin() === FALSE){ function add_js_defer($tag, $handle, $src){ if( strpos( $tag, 'jquery.js' ) ) return $tag; preg_match_all('/([\w\-.:]+)\s*=\s*("[^"]*"|\'[^\']*\'|[\w\-.:]+)/i', $tag, $match); $newtag = "<script "; foreach($match[1] as $key=> $val){ $newtag .= $val."=".$match[2][$key]." "; } $newtag .= "defer></script>"; return $newtag.PHP_EOL; } add_filter( 'script_loader_tag', 'add_js_defer', 11, 1 ); } |
Will be adding some basic information about using the current Google API with the PHP SDK, this includes Google+, Youtube and other services. For setting up the actual API access see the Google documentation and Google Developer Console
1 2 3 4 5 6 7 8 9 10 11 12 |
require _DIR_TO_AUTOLOAD_SDK_.'/google_sdk/autoload.php'; // Required Information // OAuth 2.0 $google_client_id = _GOOGLE_CLIENT_ID_; $google_client_secret = _GOOGLE_CLIENT_SECRET_; // Public API-Access $google_redirect_url = 'http://yourdomain.com/google_login/?option=do_login'; // API-key for a server application! $google_developer_key = _GOOGLE_DEVELOPER_KEY_; |
1 2 3 4 5 6 7 |
$gClient = new Google_Client(); $gClient->setAccessType('offline'); $gClient->setApplicationName('Application Name'); $gClient->setClientId($google_client_id); $gClient->setClientSecret($google_client_secret); $gClient->setRedirectUri($google_redirect_url); $gClient->setDeveloperKey($google_developer_key); |
1 2 3 4 5 6 7 8 9 10 |
$gClient->setScopes(array( 'https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'https://gdata.youtube.com', 'https://www.googleapis.com/auth/youtube.readonly', 'https://www.googleapis.com/auth/youtubepartner' ) ); |
1 |
$plus = new Google_Service_Plus($gClient); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
session_start(); // A simple check for the login to get a fresh token if($_GET['option'] == "do_login" && empty($_SESSION['google_token'])){ // Check for redirect from Google & Auth if (empty($_GET['code'])) { // Create Auth redirect header('Location: '.$gClient->createAuthUrl()); } else { $gClient->authenticate($_GET['code']); $access_token = $gClient->getAccessToken(); //Store the token in a session or your database for later use $_SESSION['google_token'] = $access_token; } } // You have already logged in if(!empty($_SESSION['google_token'])){ $gClient->setAccessToken($_SESSION['google_token']); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Making sure we have a valid access token if($gClient->getAccessToken()) { try{ // Get your activities $optParams = array('maxResults' => 100); $activities = $plus->activities->listActivities('me', 'public', $optParams); print_r($activities); } } catch (Google_ServiceException $e) { $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>', htmlspecialchars($e->getMessage())); } |
Will be adding some basic information about using the current Facebook API with the PHP SDK. Have been updating a lot of old API integrations over the past 2 months and finally solved many badly documented areas of the new API. Will be updating this in the future, as I dive deeper into the latest API changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
require_once _DIR_TO_AUTOLOAD.'/facebook_sdk/autoload.php'; use Facebook\FacebookSession; use Facebook\FacebookRedirectLoginHelper; use Facebook\FacebookRequest; use Facebook\FacebookResponse; use Facebook\FacebookSDKException; use Facebook\FacebookRequestException; use Facebook\FacebookAuthorizationException; use Facebook\GraphObject; use Facebook\Entities\AccessToken; use Facebook\HttpClients\FacebookCurlHttpClient; use Facebook\HttpClients\FacebookHttpable; |
Depending on what you want to do with the API, the above needs to be adjusted. Check the Facebook API documentation for more details.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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 |
// Session should be started after all files have been included session_start(); // init app with app id and secret FacebookSession::setDefaultApplication( _FB_APP_ID_, _FB_APP_SECRET_ ); // login helper with redirect_uri $helper = new FacebookRedirectLoginHelper( 'http://yourdomain.com/FB_LOGIN/'); // Check for Facebook redirect & retrieve session try { $session = $helper->getSessionFromRedirect(); } catch( FacebookRequestException $ex ) { // When Facebook returns an error } catch( Exception $ex ) { // When validation fails or other local issues } if ( isset( $session ) ) { /* Store the session for later reuse, in this case even getting a long lived session. You should store this in your database. The session can be reused with: $session = new FacebookSession($_SESSION['long']->getToken()); */ if(empty($_SESSION['long'] )){ $_SESSION['long'] = $session->getLongLivedSession(); } // graph api request for user data try { $user_profile = (new FacebookRequest( $session, 'GET', '/me' ))->execute()->getGraphObject(GraphUser::className()); echo "Name: " . $user_profile->getName(); } catch(FacebookRequestException $e) { echo "Exception occured, code: " . $e->getCode(); echo " with message: " . $e->getMessage(); } } else { // show login url if no session available // request special permissions, optional. $params = array( 'manage_pages', 'publish_pages','publish_actions','user_videos' ); echo '<a href="' . $helper->getLoginUrl($params ) . '">Login</a>'; } |
As part of our complete network upgrade, portalZINE.TV gets a complete facelift as well. The whole website has been streamlined in preparation for the new season.
While building plugins for WordPress is fun, it often means repeating tasks over and over again. I love clean and organized code! For my last internal project, a Visual Composer addon bundle, I decided to build a modular system.
So I have one central plugin, handling multiple modules that access methods from the plugin. This allows me to reuse public and admin routines. In combination with _autoload and traits, this makes the codebase lean and mean.
I also decided to use TWIG fully for the presentation layer. Each module can be activated, deactivated, registers their own public and admin views, admin menus, ajax calls, dashboard widgets and additional context.
I am currently in the process of cleaning this up and will share some more details soon.
Cheers
Alex
I have been working on a full integration of fullpage.js into Visual Composer for WordPress. This allows to easily build fullpage layouts, with different pages and full slide capabilities. Also added iScroller functionality, to allow overflow content to work nicely on certain pages. All of this is working with simple drag & drop :) and can be used by any unexperienced user.
I am currently cleaning up the addon, but I am not sure yet if I will offer it as a commercial addon or keep it for my internal projects only :)
Will post a video later this week.
Cheers
Alex
Currently reading up on the IMAP protocol, as one of my customers is using a server without IMAP support compiled :)
I will be using a simple INBOX check for failed email notifications (sockets are your best friend). That will allow me to set a flag for every new user account that is still unconfirmed and used a broken email address for their registration. These accounts can than be verified manually :)
Happy socket = happy customer.
Btw, here is a nice piece of code to quickly parse the email header in PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$parsed = array(); $blocks = preg_split('/\n\n/', $response['data']); $lines = array(); $matches = array(); foreach ($blocks as $i => $block) { $parsed[$i] = array(); $lines = preg_split('/\n(([\w.-]+)\: *((.*\n\s+.+)+|(.*(?:\n))|(.*))?)/', $block, -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($lines as $line) { if(preg_match('/^\n?([\w.-]+)\: *((.*\n\s+.+)+|(.*(?:\n))|(.*))?$/', $line, $matches)) { $parsed[$i][$matches[1]] = preg_replace('/\n +/', ' ', trim($matches[2])); } } } |
Audiosprite is a node.js ffmpeg wrapper to concat small audio files into one single file. It even allows you to define the gap between each file.
Continue reading Audiosprite – node.js ffmpeg wrapper to concat small audio files into one