Skip to content

Instantly share code, notes, and snippets.

@qutek
Last active October 9, 2017 11:24
Show Gist options
  • Save qutek/5a6913a843f218e2cca810635f333fda to your computer and use it in GitHub Desktop.
Save qutek/5a6913a843f218e2cca810635f333fda to your computer and use it in GitHub Desktop.
WP Quiz
<?php
/**
* Question #1
* Scenario:
* 1. We have a list of companies in the Company custom post type.
* 2. Each Company has a ranking which is stored in post meta with a key called `ranking. The ranking is a decimal value between 0 and 100. A sample `ranking` is 94.9.
* 3. Each Company can also be marked as sponsored. If a Company is sponsored, a post meta with a key called `sponsored` is updated to 1. Otherwise, the `sponsored` meta value is `0` for each Company.
*
* Problem:
* Given the above scenario, provide the correct array of $args to pass into a new WP_Query instance so that we can return 100 companies with the "sponsored" companies first, and then after that sorted, from highest to lowest based off the `ranking` value.
*
* Assumed:
* - The custom post type key for Company is `company`
* - The ACF Field Name / metakey for Sponsored is `sponsored`
* - The ACF Field Name / metakey for Ranking is ``ranking``
* - Both Sponsored Company and Non Sponsored Company should be displayed on result,
* but keep the sponsored company on top of result as well as sorted by highest ranking
*/
add_action( 'pre_get_posts', 'sort_by_sponsored_and_rank', 10, 1 );
function sort_by_sponsored_and_rank($query){
/**
* Only process if on archive page of custom post type `company`
* or may you can change per your need like `$query->is_home()` if this query need to be perform on homepage
*/
if( is_admin() || !$query->is_main_query() || !is_post_type_archive( 'company' ) )
return;
/**
* Get original meta_query,
* in case some other scripts has modified the meta_query
* so we are not screwed up other functionality
* @var [type]
*/
$meta_query = $query->get('meta_query');
/**
* Add our meta query to the original meta queries
* on WordPress 4.0 above we can now pass an array to WP_Query as the value for orderby
* and use an associative array, with a key for each meta clause
* @see https://make.wordpress.org/core/2014/08/29/a-more-powerful-order-by-in-wordpress-4-0/
*/
$meta_query[] = array(
'relation' => 'AND',
'sponsored_clause' => array(
'key'=>'sponsored',
// 'value'=>'1', // uncomment this if you want to exclude non sponsored company
'compare' => 'EXISTS', // change `compare` to `=` if you want to exclude non sponsored company
'type' => 'NUMERIC' // make sure we are cast the value as number / float
),
'ranking_clause' => array(
'key'=>'ranking',
// 'value'=>'0',
'compare' => 'EXISTS',
'type' => 'NUMERIC'
)
);
// set meta query
$query->set('meta_query',$meta_query);
// set order by
$query->set('orderby', array(
'sponsored_clause' => 'DESC',
'ranking_clause' => 'DESC',
));
$query->set('posts_per_page', 100); // set 100 per page
}
<?php
/**
* Question #2
* Scenario:
* 1. We have a list of companies in the Company custom post type.
* 2. We have a custom admin interface that we built that allows for the owners of the company to update the data about the company.
* 3. One of the pieces of data that is stored on each company is an array of email addresses.
* The email addresses are stored in an Advanced Custom Field Repeater field that has a key of: `email_notifiers`.
* Each item in this repeater field has one field which is called `email`.
* The `email` contains the email address.
* 4. In the custom admin interface, we have a form where the owner can add new email addresses and save them (into the `email_notifiers` repeater field)
*
* Problem:
* Given the above scenario, provide the code for the API endpoint that would allow us to make POST request to this URL to perform the action outlined below
* - Endpoint example : http://yourwpsite.dev/wp-admin/admin-ajax.php?action=add-notifier-email&[email protected] m&company_id=12345
* - add the submitted email address to the `email_notifiers` ACF repeater field on the submitted `company_id` Company post.
*
* Assumed:
* - Ajax button has beed set
* - Ajax action name is `add-notifier-email`
* - The ACF Field Name / metakey for Email Notifiers is `email_notifiers`
* - The ACF Sub Field Name / metakey for email is `email`
* - Non logged in user allowed to perform the ajax action
* - Ajax response returning json
*/
add_action( 'wp_ajax_add-notifier-email', 'ajax_add_notifier_email_to_company' );
add_action( 'wp_ajax_nopriv_add-notifier-email', 'ajax_add_notifier_email_to_company' ); // allow non logged in user to perform this action
/**
* Uncomment if you want to add test ajax button on footer
*/
// add_action( 'wp_footer', 'add_ajax_button' );
/**
* Ajax callback to add email on `email_notifiers` repater fields
* on `company` post type
* @return [type] [description]
*/
function ajax_add_notifier_email_to_company(){
$response = array(
'success' => false,
'message' => 'Failed to process.'
);
try {
/**
* May need to perform authentication / security check with nonce
*/
// if(!isset($_POST['nonce']) || ! wp_verify_nonce( $_POST['nonce'], 'add-notifier-email' )){
// throw new Exception("Security check not passed!");
// }
// make sure company id posted
if(!isset($_POST['company_id'])){
throw new Exception("Company ID is required!");
}
// make sure email is valid
if(!isset($_POST['email']) || !is_email( $_POST['email'] ) ){
throw new Exception("Email address not valid!");
}
// try to add row to `email_notifiers` field
$index = add_row('email_notifiers', array('email' => sanitize_text_field($_POST['email']) ), absint( $_POST['company_id'] ));
if(!$index){
throw new Exception("Failed to insert notifier email!");
}
// all done.
$response['success'] = true;
$response['message'] = 'Email added successfully.';
} catch (Exception $e) {
$response['message'] = $e->getMessage();
}
// send ajax response as json.
wp_send_json( $response );
}
/**
* Sample ajax button on footer
*/
function add_ajax_button(){
?>
<p><a href="#" id="test-ajax">Test Add Notifier</a></p>
<script type="text/javascript">
(function($){
$(document).on('click', '#test-ajax', function(e){
e.preventDefault();
var _nonce = "<?php echo wp_create_nonce( 'add-notifier-email' ); ?>";
if(typeof(ajax_url) == 'undefined'){
var ajax_url = "<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>";
}
$.ajax( {
dataType: 'json',
data: {
action: 'add-notifier-email',
email: '[email protected]',
company_id: 8,
nonce: _nonce,
},
type: 'post',
url: ajax_url,
success: function(response) {
console.log(response);
alert(response.message);
}
} );
});
})(jQuery);
</script>
<?php
}
<?php
/**
* Question #3
* Scenario:
* 1. We have a list of companies in the Company custom post type.
* 2. We added a new field called "Upgraded" which is a True/False ACF field with the key of `upgraded`
* 3. When we deploy the new code, we need to make sure that the `upgraded` key is set to `true` on all Company posts that are already published
*
* Problem:
* In order to set all existing Company posts to have the "Upgraded" ACF field set to `true`,
* we are going to write a WP_CLI command to loop through all company posts, and then update the field value to true for the `upgraded` True/False ACF field.
*
* Assumed:
* - WP CLI already installed
* - The CLI comman is `wp upgrade-company`
* - The ACF Field Name / metakey for Upgraded is `upgraded`
* - By default it will update all posts with type `company`
* - By default the process will the field value to `true`
*
* To see available options you can run `wp upgrade-company --help`
*/
if ( !defined( 'WP_CLI' ) || !WP_CLI ) {
return;
}
WP_CLI::add_command( 'upgrade-company', 'Upgrade_Company_CLI' );
/**
* Upgrade ACF value for company.
*/
class Upgrade_Company_CLI extends WP_CLI_Command {
/**
* Update acf custom field `upgrade` using WP CLI
*
* ## OPTIONS
*
* [--company_id=<id>]
* : Limit to process specific company id
*
* [--value=<value>]
* : Set upgrade value, default is true
*
* ## EXAMPLES
*
* wp upgrade-company --company_id=12 --value=false
*
* @alias upgrade-company
*/
public function __invoke( $args, $assoc_args ) {
global $wpdb;
$start_time = microtime( true );
if( !isset( $assoc_args['company_id'] )){
$company_id = false;
WP_CLI::line( "Updating upgrade status for all companies." );
} else {
$company_id = $assoc_args['company_id'];
WP_CLI::line( sprintf("Updating upgrade status for company %d.", $company_id) );
}
try {
/**
* Base variable
* @var string
*/
$post_type = 'company';
$field_key = 'upgrade';
$new_value = isset( $assoc_args['value'] ) ? $assoc_args['value'] : true; // default is true / 1
$args = array(
'posts_per_page' => -1,
'post_type' => $post_type,
'fields' => 'ids',
);
if($company_id){
$args['post__in'] = (array) $company_id;
}
$query = new WP_Query( $args );
$ids = $query->posts;
if(empty($ids)){
throw new Exception("Company id not found.");
}
/**
* May need to write some log
* @var array
*/
$failed = array();
$success = array();
foreach ($ids as $company_id) {
$update = update_field( $field_key, $new_value, $company_id );
if(!$update){
// if the update process return false, might it because the value is already same
if($new_value != get_field( $field_key, $company_id ) ){
$failed[] = $company_id;
} else {
$success[] = $company_id;
}
} else {
$success[] = $company_id;
}
}
if(!empty($failed)){
WP_CLI::warning( sprintf( "Failed to process : %s.", implode(',', $failed) ) );
}
if(!empty($success)){
WP_CLI::success( sprintf("Update successfully for company : %s", implode(',', $success) ) );
}
// maybe count the process time
$endtime = microtime(true) - $start_time;
WP_CLI::line( "Process completed!" );
} catch (Exception $e) {
WP_CLI::error( $e->getMessage() );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment