Get random posts through WordPress API - php

I am building a self-test project which can give 10 questions at one time from a question list. I want the 10 questions should be different every time I start the test. The front-end is React and the back-end is WordPress by using WordPress API.
Previously I used orderby=rand in the query by implementing a plug-in
<?php
/**
* Plugin Name: REST API - Post list randomize
* Description: Randomize the content list in REST API passing `orderby=rand` as parameter.
* Version: 1.0.0
* Author: Felipe Elia | Codeable
* Author URI: https://codeable.io/developers/felipe-elia?ref=qGTOJ
*/
/**
* Add `rand` as an option for orderby param in REST API.
* Hook to `rest_{$this->post_type}_collection_params` filter.
*
* #param array $query_params Accepted parameters.
* #return array
*/
function add_rand_orderby_rest_post_collection_params( $query_params ) {
$query_params['orderby']['enum'][] = 'rand';
return $query_params;
}
add_filter( 'rest_post_collection_params', 'add_rand_orderby_rest_post_collection_params' );
It worked perfectly until 2 weeks ago. Without modifying any code, it was just broken. I used Postman to test, such as http://localhost/wp/wp-json/wp/v2/questions?per_page=10&orderby=rand. The response is
"code": "rest_invalid_param",
"message": "Invalid parameter(s): orderby",
"data": {
"status": 400,
"params": {
"orderby": "orderby is not one of author, date, id, include, modified, parent, relevance, slug, include_slugs, title."
}
}
Two weeks ago if I used the same query, it could give me 10 random questions. It looks like the plug-in cannot add rand successfully as a parameter for orderby in WordPress like before.
BTW, the functionality of orderby=rand in WP isn't broken because if I manually add rand as a parameter in WP core code, the above query can work again.
Does anybody know what's wrong with the plug-in or some latest updates in WP causing the problem?
Another thing is I saw some articles mentioning ORDERBY = RAND() in MySQL will affect the performance severely when the database is large. So I wonder whether I should use orderby=rand in the query to get random questions or think about other ways to do the job. Does anybody have any suggestions for this performance issue? Thanks!

Found the answer. I need to make the first parameter rest_post_collection_params of add_filter function to the correspondent post type.
The original rest_post_collection_params is for the WP default posts type. Because I use ACF(Advanced Custom Fields, another plug-in to create customized post types) to create my own post types, such as books, I need to change the first parameter to rest_books_collection_params. If you have more customized post types, just create as many as add_filter functions for each of them.
Just have no ideas why I could use rest_post_collection_params for all my customized post types 3 weeks ago but not now. Anyway, since it is solved, don't bother. My project is more front-end oriented. WP is just storage.
BTW, probably someone has noticed that rest_post_collection_params is for the WP default post type posts. In the parameter it uses single form post for the plural form posts. This only works for the WP default post type. For customized types, if it is books, the parameter should be rest_books_collection_param; if questions, then rest_questions_collection_param. Keep the parameter exactly the same as the post type.

For Getting Unique Questions:
table: wp_question_filter_list
id ip_address question_list
1 1.21.23 1,2,3,4,5
2 1.21.24 1,4,6,7,8
3 1.21.25 4,5,6,8,9
function get_unique_questions($ip_address){
global $wpdb;
$table_name = $wpdb->prefix . 'question_filter_list';
$unique_id_list=$wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE ip_address=%d",$ip_address), ARRAY_A);
if (count($unique_id_list) > 0) {
$question_data=$unique_id_list[0];
$arr_question=array();
if(isset($question_data['question_list']) && $question_data['question_list']!=''){
$arr_old_question_id_list=explode(",",$question_data['question_list']);
}
$excludes = implode(',', $arr_old_question_id_list);
$arr_question_id_list=$wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE ip_address='".$ip_address."' AND id NOT IN('".$excludes."') "), ARRAY_A);
set_unique_questions($ip_address,$arr_question_id_list);
}
function set_unique_questions($ip_address,$arr_question_id_list){
global $wpdb;
$table_name = $wpdb->prefix . 'question_filter_list';
$unique_id_list=$wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE ip_address=%d",$ip_address), ARRAY_A);
if (count($unique_id_list) > 0) {
$question_data=$unique_id_list[0];
$arr_question=array();
if(isset($question_data['question_list']) && $question_data['question_list']!=''){
$arr_old_question_id_list=explode(",",$question_data['question_list']);
}
if(is_array($arr_question_id_list) && !empty($arr_question_id_list)){
foreach($arr_question_id_list as $single_question){
array_push($arr_question,$single_question);
}
}
$str_question_id_list=implode(",",$arr_question);
$wpdb->update($table_name, array(
'question_list' => $str_question_id_list
), array(
'ip_address' => $ip_address
));
}else{
$str_question_id_list=implode(",",$arr_question_id_list);
$data = array(
'ip_address' => $ip_address,
'question_list' => $str_question_id_list,
);
$wpdb->insert($table_name, $data);
}
$result = $wpdb->insert($table_name, $item);
}
$ip_address=$_SERVER['REMOTE_ADDR'];
$arr_question_list=get_unique_questions($ip_address);
echo "<pre>";
print_r($arr_question_list);

Related

How to access wooCommerce config for cuustom WP Query

Maybe this is already answered somewhere else, but I couldn't find it after researching for 5 days.
I've a custom WP Query that returns products for JavaScript AJAX client. My client wants to handle the "number of rows" and "columns" through wooCommerce config that is available through customization of shop page.
Here's my basic implementation for custom WP Query:
function loadProducts(){
// Access the number of rows and columns input here from customization page??
}
add_action("wp_ajax_loadprods","loadProducts");
add_action("wp_ajax_nopriv_loadprods","loadProducts")
From the ref: /wp-content/plugins/woocommerce/includes/wc-template-functions.php
function loadProducts(){
$columns = get_option('woocommerce_catalog_columns', 4);
$rows = absint(get_option('woocommerce_catalog_rows', 4));
echo json_encode(array('columns' => $columns, 'rows' => $rows));
wp_die();
}
add_action("wp_ajax_loadprods","loadProducts");
add_action("wp_ajax_nopriv_loadprods","loadProducts")

Change Variable after each Rest API Call out of a list of Stock symbol names until the list is done in Wordpress?

I'm trying to use the alphavantage REST API to output stock prices through Advanced Custom Fields. My issue right now is that I don't know how I can create a list of stocksymbol names (we have specific stocks we want to check) that changes each call until all stocks have been checked.
This is my current Wordpress Code in functions.php
/* Register Stock Price Custom Post Type */
add_action('init', 'register_aktienpreise_cpt');
function register_aktienpreise_cpt(){
register_post_type('aktienpreise', [
'label' => 'Aktienpreise',
'public' => true,
'capability_type' => 'post'
]);
}
add_action( 'wp_ajax_nopriv_get_aktienpreise_from_api', 'get_aktienpreise_from_api' );
add_action( 'wp_ajax_get_aktienpreise_from_api', 'get_aktienpreise_from_api' );
/* Initialize Function */
function get_aktienpreise_from_api(){
/* Set Log File */
$file = get_stylesheet_directory() . '/report.txt';
/* Declare Current Symbol Variable and check if its not empty */
$current_symbol = ( ! empty($_POST['current_symbol']) ) ? $_POST['current_symbol'] : '';
$aktienpreise = [];
/* Results output for AlphaVantage Rest API + APIKEY - Add Current Symbol Set for each API Call */
$results = wp_remote_retrieve_body( wp_remote_get('https://www.alphavantage.co/query?function=GLOBAL_QUOTE&apikey=demo&symbol=' . $current_symbol_set ));
file_put_contents($file, "Current Symbol: " . $current_symbol. "\n\n", FILE_APPEND);
// turn it into a PHP array from JSON string
$results = json_decode( $results );
// Either the API is down or something else spooky happened. Just be done.
if( ! is_array( $results ) || empty( $results ) ){
return false;
}
/* Change Current Stock Symbol for the next call until empty */
$current_symbol = $current_symbol + $current_symbol_set;
/* Repeat Calls until results are empty */
wp_remote_post( admin_url('admin-ajax.php?action=get_aktienpreise_from_api'), [
'blocking' => false,
'sslverify' => false,
'body' => [
'current_symbol' => $current_symbol
]
] );
}
At this part
/* Change Current Stock Symbol for the next call until empty */
$current_symbol = $current_symbol + $current_symbol_set;
I'd like to have a list of specific stocks I want to check (for example Apple, IBM etc.).
The goal is that on each call the variable changes to the next stock (lets say first call Apple, second IBM), then writes those into the specific ACF Fields that I can showcase in a table on our website.
If the restapi urls would just have number increases it would be easy, but how do I do it with specific terms like "IBM" etc.
Furthermore if there are easier solutions to this please tell me so since I'm fairly new to REST APIs.
The Goal in general is to just display current stockprices of specific stocks inside a table on our website, preferably inside an ACF Field so we can do math formulas on the price (for example price x 2 for another table field).
Thanks for everyone taking their time to help me out!
Why don't you use an array for the stock symbols and do the AlphaVantage API calls inside a loop?
I will give you a quick example:
$my_symbols = [
'IBM',
'Microsoft',
'Tata'
];
foreach( $my_symbols as $current_symbol ) // iterate through the array elements
{
//... make the API calls to AlphaVantage
//... do any other business logic, like storing the API result in file or update the stocks, etc..
}
One thing to keep in mind is that you should make sure the script won't get a timeout. So increase the max_execution_time to a higher value.
Also, you don't have to call your own API here. I mean you don't have to do the wp_remote_post() to your own website.

Is there a limit to wp_remote_get and/or simplexml_load_string from Vimeo?

I know *wp_remote_get* is a WordPress function, and that I should be posting this in wordpress.stackexchange, however, I am almost certain my issue lies more on the general PHP side.
The problem: I need to retrieve all Vimeo videos found within an album, yet I am only getting 20.
The approach:
$vmg_feed_url = 'http://vimeo.com/api/v2/';
$vmg_user = '2212323';
if($vmg_type == 'user'){ /** just an input variable checking whether the function should search for user or for album. in our case, it searches for album **/
$vmg_type_url = '';
} else {
$vmg_type_url = $vmg_type . '/';
}
$vmg_videos_url = $vmg_feed_url . $vmg_type_url . $vmg_user . '/videos.xml';
$videos_result = wp_remote_get($vmg_videos_url);
$vmg_videos = simplexml_load_string($videos_result['body']);
The resulting XML is http://vimeo.com/api/v2/album/2212323/videos.xml - and as you can see, I am only retrieving 20 videos.
The question: Am I missing something? Is there a function/variable that sets a limit to the amount of videos I can retrieve? I know that wp_remote_get gives me these attributes (from the WordPress Codex):
$url
(string) (required) Universal Resource Locator (URL).
- Default: None
$args
(array) (optional)
- Default: method: GET, timeout: 5, redirection: 5, httpversion: 1.0, blocking: true, headers: array(), body: null, cookies: array()
Any help is truly appreciated. Please let me know if I forgot about any details!
Yor problem is not in wordpress or PHP. It is API limits:
http://developer.vimeo.com/apis/simple
Simple API responses include up to 20 items per page.
You can get more by adding ?page parameter in next requests.

Drupal/Ubercart custom price php code for roles

Im building an e-commerce site for wholesale foods and the pricing for products change depending on the user logged in. Ive looked at member pricing and basically every module i could find to do with altering the price but they are either for drupal 6 or not really what im after. Im using Drupal 7 with ubercart 3.
Ive found this module http://drupal.org/project/uc_custom_price. It adds a field within product creation that allows custom php code to be added to each individual product which is exactly what im after. however im not that good with php which is why ive been hunting modules instead of changing code.
What ive got at the moment is:
if ([roles] == 'test company') {
$item->price = $item->price*0.8;
}
Except the [roles] part is the wrong thing to use there and it just throws errors. Ive tried using things like $users->uid =='1' to try to hook onto a user like that but that didnt work either.
what would be the correct variable to put there?
thanks
try this Drupal 7 global $user object
global $user; // access the global user object
if(in_array("administrator",$user->roles)){ // if its administrator
$item->price = $item->price*0.8;
}elseif(in_array("vip",$user->roles)){ // if its a vip
//..
}elseif(in_array("UserCompanyX",$user->roles)){ // if its a user from company X
//..
}
or
if($user->roles[OFFSET] == "ROLE"){
// price calculation
}
$user->roles is an array of the roles assigned to the user.
hope it helped
Make your own module with UC Price API:
http://www.ubercart.org/docs/developer/11375/price_api
function example_uc_price_handler() {
return array(
'alter' => array(
'title' => t('Reseller price handler'),
'description' => t('Handles price markups by customer roles.'),
'callback' => 'example_price_alterer',
),
);
}
function example_price_alterer(&$price_info, $context, $options = array()){
global $user;
if (in_array("reseller", $user->roles)) { //Apply 30% reseller discount
$price_info["price"] = $context["subject"]["node"]->sell_price - (
$context["subject"]["node"]->sell_price * 0.30) ;
}
return;
}
See also: http://www.ubercart.org/forum/development/14381/price_alteration_hook

How do I pull the subscriber count from a MailChimp list with the API?

I'm trying to display the subscriber count from a MailChimp mailing list using their API, and I've got it partially working, except the code below is currently spitting out the subscriber count for all lists, rather than for one specific list. I've specified the list id in the line $listId ='XXX'; but that doesn't seem to be working. Because I have five lists in total, the output from the PHP below shows this:
10 0 0 1 9
What do I need to do in my code below to get the subscriber count from a specific list id?
<?php
/**
This Example shows how to pull the Members of a List using the MCAPI.php
class and do some basic error checking.
**/
require_once 'inc/MCAPI.class.php';
$apikey = 'XXX';
$listId = 'XXX';
$api = new MCAPI($apikey);
$retval = $api->lists();
if ($api->errorCode){
echo "Unable to load lists()!";
echo "\n\tCode=".$api->errorCode;
echo "\n\tMsg=".$api->errorMessage."\n";
} else {
foreach ($retval['data'] as $list){
echo "\t ".$list['stats']['member_count'];
}
}
?>
I just came across this function (see below) that let's me return a single list using a known list_id. The problem is, I'm not sure how to add the list_id in the function.
I'm assuming I need to define it in this line? $params["filters"] = $filters;
The MailChimp lists() method documentation can be referred to here: http://apidocs.mailchimp.com/rtfm/lists.func.php
function lists($filters=array (
), $start=0, $limit=25) {
$params = array();
$params["filters"] = $filters;
$params["start"] = $start;
$params["limit"] = $limit;
return $this->callServer("lists", $params);
}
I'd strongly recommend not mucking with the internals of the wrapper as it's not going to be nearly as helpful as the online documentation and the examples included with the wrapper. Using the wrapper means the line you tracked down will effectively be filled when make the proper call.
Anywho, this is what you want:
$filters = array('list_id'=>'XXXX');
$lists = $api->lists($filters);
Mailchimp provides a pre-built php wrapper around their api at http://apidocs.mailchimp.com/downloads/#php. This api includes a function lists() which, according to its documentation, returns among other things:
int member_count The number of active members in the given list.
It looks like this is the function which you are referring to above. All you should have to do is iterate through the lists that are returned to find the one with the proper id. From there you should be able to query the subscriber count along with a number of other statistics about the list.

Categories