Include "required questions" in a random selection - php

I'm selecting a set of random questions without any duplicates using the following:
<?php
$amount = get_field('select_number_of_questions');
$repeater = get_field("step_by_step_test");
shuffle($repeater);
$repeater_limit = array_slice($repeater,0,$amount);
foreach($repeater_limit as $repeater_row) {
echo "<p>".$repeater_row['question']."</p>";
$rows = $repeater_row['answer_options'];
foreach($rows as $row) {
echo $row['answer']."<br />";
}
}
?>
Each question has a field: get_field('required_question'); that has a yes/no dropdown. The questions that have yes selected ALWAYS have to be incorporated into the loop above.
E.g The test has 20 questions to select from, 10 will be selected at random. Within the 20 questions, there are 2 required questions (i.e these will always be selected). So it will need to grab the 2 required questions and select 8 other random questions.
How can I include the required questions within the random selection?

The Question doesn't state it, but all suggests this is an Advanced Custom Fields set up using the Repeater Add-on.
In that case, this is the test configuration I've done:
Note that here I'm using $repeater_row['title'] instead of the OP's $repeater_row['question']. Also, I removed the answer_options part. See comments for details:
// Get fields
$amount = get_field( 'select_number_of_questions' );
$repeater = get_field( 'step_by_step_test' );
// Auxiliary arrays to separate fields by Field Name
$not_enabled = array();
$enabled = array();
// Separate
foreach( $repeater as $field )
{
if( 'no' == $field['enabled'] )
$not_enabled[] = $field;
else
$enabled[] = $field;
}
// Discount the enabled from the the total amount
$amount = (int)$amount - count( $enabled );
// Shuffle before slicing
shuffle( $not_enabled );
$repeater_limit = array_slice( $not_enabled, 0, $amount );
// Add enabled fields and shuffle again
$final_array = array_merge( $repeater_limit, $enabled );
shuffle( $final_array );
foreach( $final_array as $repeater_row ) {
echo "<p>" . $repeater_row['title'] . "</p>";
}

First you need to filter out the required questions like so:
$all_questions = get_field("step_by_step_test");
$required = $optional = array();
foreach($all_questions as $question) {
if( $a['required_question']) $required[] = $question;
else $optional[] = $question;
}
$amount = get_field("select_number_of_questions")-count($required);
shuffle($optional);
$final = array_merge($required,array_slice($optional,0,$amount));
foreach($final as $repeater_row) {
...
}
Hope I helped you again :p

Related

How can I get count of total submission in Forminator Plugin

I have tried to get all quizzes submission count but there is get only first-page quizzes count (http://prntscr.com/phcby8). I need to get all the quizzes submission count.
I have tried this way :
function get_all_quiz_form_id() {
$forms = Forminator_API::get_quizzes();
$form_ids = array();
foreach ( $forms as $form ) {
$form_ids[] = $form->id;
}
return $form_ids;
}
$get_count = get_all_quiz_form_id();
$count = 0;
foreach ( $get_count as $key => $FORM_ID ) {
$entries = Forminator_API::get_entries( intval( $FORM_ID ) );
$count+= count( $entries );
}
echo $count;
I want to get a count of all 64 quizzes submission.
I have fixed this issue. I have to get count using custom queries and Forminator_API is take a time to get data when lots of data in the database so Custom query is best for the count.
function get_all_submission_count() {
ob_start();
global $wpdb;
$table_name = $wpdb->prefix . 'frmt_form_entry';
$count_query = "select count(*) from $table_name";
$count = $wpdb->get_var($count_query);
return $count;
}
Thanks :)

How to store product quantities in an array

I have a data array that totals all the items in the cart for all the products as one number.
I've been trying to figure out a way to get a data array count() all the different totals of all the different items in the cart and have them presented in my data layer comma separated. I hope that makes sense.
if ($order->getId()) {
$items = $order->getAllVisibleItems();
$itemIds = array();
$itemNames = array();
$itemPrices = array();
$itemMargins = array();
$itemTypes = array();
$itemGenders = array();
$itemSports = array();
$itemCategoryIds = array();
$itemCategoryNames = array();
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// Get the parent item - it is NOT included in the quote due to
// customizations made by the OrganicInternet module for simple
// product pricing. So I had to come up with another way to get it.
$options = $item->getProductOptions();
$parent = $item->getProduct();
if (array_key_exists('info_buyRequest', $options)) {
if (array_key_exists('cpid', $options['info_buyRequest'])) {
$parentId = $options['info_buyRequest']['cpid'];
$parent = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('season')
->addAttributeToSelect('gender')
->addAttributeToSelect('sport')
->addAttributeToFilter('entity_id', $parentId)
->getFirstItem();
}
}
$itemIds[] = $item->getSku();
$itemNames[] = $parent->getName();
$itemPrices[] = $item->getBasePrice() ?: 0;
$itemMargins[] = $this->_calculateMargin($parent, null, $item);
$itemTypes[] = $parent->getAttributeText('season');
$itemGenders[] = $parent->getAttributeText('gender');
$itemSports[] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
}
// # Products
$data['u1'] = count($items);
The above will return:
dataLayer = [{"visitorLoginState":"Logged out","visitorType":"NOT LOGGED IN","visitorLifetimeValue":0,"visitorExistingCustomer":"No","u1":2,"u2":["889623392590","889623135517"]
It shows a total of 2 products for the U1 variable and the two sku's for the u2 variable in the data array.
If i have multiple products for the first sku i want it to seperate the quantities. ie.. "u1":1,1,3
Would i use array_sumor some type of multi-dimensional array to acquire my needs?
If i have multiple products for the first sku i want it to seperate
the quantities. ie.. "u1":1,1,3
It is not exactly clear to me is the relationship between sku and product and which variables in your array refer to which. I make the following presumptions:
1) A product is equivalent to one $items element
2) A sku is a unique $itemIds[] value
I use the array key as a simple way to keep track for each unique sku and the value to keep track of the product count for the sku.
if ($order->getId()) {
$items = $order->getAllVisibleItems();
$itemIds = array();
$itemNames = array();
$itemPrices = array();
$itemMargins = array();
$itemTypes = array();
$itemGenders = array();
$itemSports = array();
$itemCategoryIds = array();
$itemCategoryNames = array();
// My addition (UPDATE: fixed to the correct variable name)
$uniqueItemIds = array();
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// Get the parent item - it is NOT included in the quote due to
// customizations made by the OrganicInternet module for simple
// product pricing. So I had to come up with another way to get it.
$options = $item->getProductOptions();
$parent = $item->getProduct();
if (array_key_exists('info_buyRequest', $options)) {
if (array_key_exists('cpid', $options['info_buyRequest'])) {
$parentId = $options['info_buyRequest']['cpid'];
$parent = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('season')
->addAttributeToSelect('gender')
->addAttributeToSelect('sport')
->addAttributeToFilter('entity_id', $parentId)
->getFirstItem();
}
}
// *******************************
// My addition / changes
$sku = $item->getSku();
$itemIds[] = $sku; // I don't use this but keep $itemIds for compatibility
// use the array key to track counts for each sku
if (!isset($uniqueItemIds[$sku])){
$uniqueItemIds[$sku] = 1; // UPDATE: fixed to start at 1 not 0
} else {
$uniqueItemIds[$sku]++;
}
// *******************************
$itemNames[] = $parent->getName();
$itemPrices[] = $item->getBasePrice() ?: 0;
$itemMargins[] = $this->_calculateMargin($parent, null, $item);
$itemTypes[] = $parent->getAttributeText('season');
$itemGenders[] = $parent->getAttributeText('gender');
$itemSports[] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
}
// show # Products
// "u1":1,1,3 NOTE: this should be a string => "u1":"1,1,3"
$data['u1'] = "";
foreach ($uniqueItemIds as $key => $val)
// show unique skus in u2
$data['u2'][] = $key;
// show counts for each sku in u1
if (strlen($data['u1'] == 0)){
$data['u1'] = (string)$value;
} else {
$data['u1'] .= ("," . $value);
}
}
How about something like...
if ($order->getId()) {
.....
.....
.....
/** #var Mage_Sales_Model_Quote_Item $item */
$sku_based_array = array();
foreach ($items as $item) {
......
......
......
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
if (isset($sku_based_array[$item->getSku()])) {
$sku_based_array[$item->getSku()] = $sku_based_array[$item->getSku()]++;
} else {
$sku_based_array[$item->getSku()] = 1;
}
}
// # Products
$data['u1'] = array_values($sku_based_array);
Looking at the code it looks like it will only every return one product as the $parent variable is overwritten to get a first item. I have added a new variable named $itemProductCounts this will be returned to the output $data array as itemProductCounts I suspect this will always equal one.
<?php
if ($order->getId()) {
$items = $order->getAllVisibleItems();
$itemIds = array();
$itemNames = array();
$itemPrices = array();
$itemMargins = array();
$itemTypes = array();
$itemGenders = array();
$itemSports = array();
$itemCategoryIds = array();
$itemCategoryNames = array();
$itemProductCounts = array();
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// Get the parent item - it is NOT included in the quote due to
// customizations made by the OrganicInternet module for simple
// product pricing. So I had to come up with another way to get it.
$options = $item->getProductOptions();
$parent = $item->getProduct();
if (array_key_exists('info_buyRequest', $options)) {
if (array_key_exists('cpid', $options['info_buyRequest'])) {
$parentId = $options['info_buyRequest']['cpid'];
$parent = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('season')
->addAttributeToSelect('gender')
->addAttributeToSelect('sport')
->addAttributeToFilter('entity_id', $parentId)
->getFirstItem();
}
}
$itemIds[] = $item->getSku();
$itemNames[] = $parent->getName();
$itemPrices[] = $item->getBasePrice() ?: 0;
$itemMargins[] = $this->_calculateMargin($parent, null, $item);
$itemTypes[] = $parent->getAttributeText('season');
$itemGenders[] = $parent->getAttributeText('gender');
$itemSports[] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
$itemProductCounts[$item->getSku()] = count($parent);
}
// # Products
$data['u1'] = count($items);
$data['itemProductCounts'] = $itemProductCounts;
With that all being said, the code above should get you close to what you need, you should replace the line $itemProductCounts[$item->getSku()] = count($parent); with the correct array with the product counts for that SKU.
Part of the issue with your data here is that everything in an $item is hidden behind an accessor. Rather than creating multitudes of arrays, I would suggest either creating a new object to house the information, or just modifying the $item directly.
Messing with the object directly has the risk of you accidentally using a variable name that exists in a protected or private scope though, so probably best to use your own, like so.
if ($order->getId()) {
$items = $order->getAllVisibleItems();
// only need one array, no need for all data points to have their own
$myItems = [];
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// basic shell
$myItem = [];
// get $options and $parent
// ...
// build your own data object
$myItem['sku'] = $item->getSku();
$myItem['name'] = $parent->getName();
$myItem['price'] = $item->getBasePrice() ?: 0;
$myItem['margin'] = $this->_calculateMargin($parent, null, $item);
$myItem['type'] = $parent->getAttributeText('season');
$myItem['gender'] = $parent->getAttributeText('gender');
$myItem['sport'] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$myItem['categoryId'] = $categories['id'];
$myItem['categoryName'] = $categories['name'];
$myItems[] = $myItem;
}
// At this point, $myItems is manipulable by all the array_* functions
// number of items e.g. 3
$data['u1'] = count($myItems);
// array of skus e.g. ["889623392590","889623392590","889623135517"]
// note: can use objects for $myItem if on PHP 7
// if you like -> notation better (in the loop)
$skus = array_column($myItems, 'sku');
// array of skus with counts e.g. ["889623392590" => 2, "889623135517" => 1]
$skus_with_counts = array_count_values($skus);
// just the counts (assuming indexes on other arrays must match) e.g. [2, 1]
// note: might be useful if you want to keep the counts as an array in dataLayer
$sku_counts = array_values($skus_with_counts);
// if you want this as a comma-separated list for u1, e.g. "2,1"
// note: will also work if you implode $skus_with_counts
$data['u1'] = implode(',', $sku_counts);
// get a list of unique SKUs (both will work), e.g. ["889623392590","889623135517"]
$data['u2'] = array_unique($skus);
$data['u2'] = array_keys($skus_with_counts);
}
Most of these kinds of PHP functions will work on your other data types as well if you want to do counting and clustering, and as you point out, you can run sum operations over them as well if you wish.
PHP array manipulation references: array_column, array_count_values, array_values, implode, array_unique, array_keys.
As a sidebar, Mage_Sales_Model_Quote_Item does have a getParentItemId() method available and a getQtyOptions method, which returns both the quantity and the product model.
I think you are mixing things.
In a simple sistem you should have:
Order has an array of OrderedItems
Each OrderedItem stores ProductObject and OrderedQuantity
And the ProductObject contains all product data.
So in your example instead of counting SKUs you must have $item->quantity field and you should work with that when you add/delete/edit order contents.

using 2 loops in PHP foreach(...)

I have this PHP foreach loop:
foreach($emails_list as $email)
but i want to do something like
foreach($emails_list as $email and $forename_list as $forename)
my code above the foreach loop is:
$sql2="SELECT * from contacts where company_sequence = '".$customersequence."' and contactstatus = '' ";
$rs2=mysql_query($sql2,$conn) or die(mysql_error());
while($result2=mysql_fetch_array($rs2))
{
$emails_list[] = $result2["email"];
}
si i want to be able to include $result["forename"]; within the loop too
will the above work to make 2 loops?
Not sure if understand, but try use for instead:
$emails_list = array("01#gmail.com", "02#gmail.com", "03#gmail.com", "04#gmail.com");
$forename_list = ("01 something", "02 something", "03 something", "04 something");
if($emails_list == $forename_list){
$count = count($emails_list);
for($i=0;$i<$count;$i++){
echo 'Email: '.$emails_list[$i].', Name: '.$forename_list[$i];
}
} else { echo 'Troubles'; }
there is no way to do this in foreach in a one statment
for this use for loop like
for ($i=0;$i<=count($emails_list); $i++) {
echo $emails_list[$i];
echo $forename_list[$i];
}
All the examples listed with a basic for loop will work fine for numeric arrays, however what about associative arrays?
The best way to do this would be something like the following:
$arr_1 = array( 'foo'=>'bar', 'fizz'=>'bang' );
$arr_2 = array( 'hello'=>1, 2=>'world' );
$array_size = count( $arr_1 ); // NOTE: This assumes the arrays are of the same size.
// Reset the internal array pointers
reset( $arr_1 );
reset( $arr_2 );
for ($i = 0; $i < $array_size; $i++ ) {
$first_array_element = current( $arr_1 );
$second_array_element = current( $arr_2 );
// code here
next( $arr_1 );
next( $arr_2 );
}
This will handle both associative and numeric arrays.

How to sort results (by name) of an array?

I am using which code which returns taxonomies which match 2 values.
Everything works as it should, but I can't figure out how to order my results. Right now they are displayed in some set order, it might be date not sure. I am trying to get them to display alphabetically (by name)..
My Code from my php template is pasted here http://pastie.org/5083124
The array I am talking about is this
<?php
foreach ( $all_terms as $all_term) {
//print_r($all_terms);
$tax_test = get_option('woo_categories_panel_taxonomies_'.$all_term->taxonomy);
$post_images = array();
$posts_aray = array();
$parent_id = $all_term->term_taxonomy_id;
$term_name = $all_term->name;
$term_parent = $all_term->parent;
$term_slug = $all_term->slug;
$term_id = $all_term->term_id;
$term_link = get_term_link( $all_term, $all_term->taxonomy );
$counter_value = $all_term->count;
?>
<div class="childListings">
<div class="block">
<a href="<?php echo $term_link; ?>">
<?php
$block_counter++;
?>
</a>
<h2><?php echo $term_name ?> <br/><span>(<?php echo $counter_value; ?> Solicitors)</span></h2>
</div><!-- /.block -->
</div><!-- /.child Listings-->
<?php
if ( $block_counter % 6 == 0 ) {
?>
<div class="fix"></div>
<?php
} // End IF Statement
// End IF Statement
?>
<?php
} // End For Loop
?>
I have looked at a few different options with $args and ksort, but I get a bit lost and can't seem to get my results on the frontend of the site to be sorted alphabetically.
Can anyone identify in my code how I would be able to have my results have a sort order?
Thanks
You can avoid bothering to sort in the PHP by sorting slightly earlier, when you're querying the database. This should be faster.
Change:
$all_terms = $wpdb->get_results("SELECT * FROM ipt1y7_term_taxonomy,ipt1y7_terms WHERE ipt1y7_term_taxonomy.parent='{$ex[2]}' AND ipt1y7_term_taxonomy.term_id=ipt1y7_terms.term_id");
...to:
$all_terms = $wpdb->get_results("SELECT * FROM ipt1y7_term_taxonomy,ipt1y7_terms WHERE ipt1y7_term_taxonomy.parent='{$ex[2]}' AND ipt1y7_term_taxonomy.term_id=ipt1y7_terms.term_id ORDER BY ipt1y7_terms.name");
i.e. just add ORDER BY name to your original query. The results will be returned sorted by name with no need for you to do anything further in the PHP, and the sort will happen on the database server. The WordPress database table terms has an index on the name column, so this should be very fast; effectively the data is pre-sorted for you. (See the description of the terms table in the WP database schema.)
Have a look at the examples in http://php.net/manual/en/function.sort.php
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
The above example will output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
This is possible using usort and your own comparison function:
<?php
/**
* For a bit of testing.
*/
$all_terms = array( );
$names = array( 'foo', 'baz', 'bar', 'qux', 'aaa' );
foreach( $names as $name ) {
$tmp = new stdClass();
$tmp->name = $name;
$all_terms[] = $tmp;
}
/**
* Here, we do the sorting:
*/
usort( $all_terms, function( $a, $b ) {
if( $a->name === $b->name ) {
return 0;
}
return ( $a->name < $b->name ) ? -1 : 1;
});
/**
* And the results:
*/
var_dump( $all_terms );

How to prevent a random post/entry to appear twice using this code?

I am using this function to redirect to a random post. I am trying to find a mechanism to prevent the same random post to appear twice in a row. Can anyone give a hint?
function sofa_view_random_post() {
// make array of all posts IDs
$q = get_posts('numberposts=-1');
$array = array();
foreach($q as $p) {
$array[] = $p->ID;
}
// randomize array to get random post
$k = array_rand($array);
$v = $array[$k];
wp_redirect( get_permalink( $v ) ); exit;
}
I get all posts IDs first and put them to array. I randomize the array to get a value. But not sure how to prevent same value from being triggered.
Store the previous result in the session, and make sure you don't pick that one again:
if( !isset( $_SESSION['last_random_post'])) {
$_SESSION['last_random_post'] = -1;
}
do {
$k = array_rand( $array);
} while( $k == $_SESSION['last_random_post']);
$_SESSION['last_random_post'] = $k;
I'm not sure how this applies to wordpress specifically, but it should be easily adaptable:
For completeness, here is the function incorporating the above code:
function sofa_view_random_post() {
if( !isset( $_SESSION['last_random_post'])) {
$_SESSION['last_random_post'] = -1; // Or null, as long as its an invalid ID
}
// make array of all posts IDs
$q = get_posts('numberposts=-1');
$array = array();
foreach($q as $p) {
$array[] = $p->ID;
}
// randomize array to get random post
do {
$k = array_rand( $array);
} while( $k == $_SESSION['last_random_post']);
$_SESSION['last_random_post'] = $k;
$v = $array[$k];
wp_redirect( get_permalink( $v ) ); exit;
}
Use sessions. Store the last used ID in the session data, and when constructing the list of possible posts, omit that post from the list.
Like this:
function sofa_view_random_post() {
// Initialise last post value as NULL if missing
if (!isset($_SESSION['last_post'])) {
$_SESSION['last_post'] = NULL;
}
// Make array of all posts IDs except last viewed
$q = get_posts('numberposts=-1');
$array = array();
foreach ($q as $p) {
if ($p->ID !== $_SESSION['last_post']) {
// Only add this ID if it's not the last viewed post
$array[] = $p->ID;
}
}
// Get random post ID and store it in the session
$k = array_rand($array);
$_SESSION['last_post'] = $v = $array[$k];
// Redirect user
wp_redirect( get_permalink( $v ) );
exit;
}

Categories