Retrieving widget data with MySQL query in WordPress - mysql

I've built up multiple dynamic sidebars for front page item manipulation. Each sidebar contains a Text widget, and I want to retrieve each widget's content (according to widget ID) from wp_options.
Basically, the structure is dbName -> wp_options -> option_id #92 contains the following:
a:9:{i:2;a:0:{}i:3;a:3:
{s:5:"title";s:0:"";s:4:"text";s:2:"mainItem";s:6:"filter";b:0;}i:4;a:3:
{s:5:"title";s:0:"";s:4:"text";s:9:"leftThree";s:6:"filter";b:0;}i:5;a:3:
{s:5:"title";s:0:"";s:4:"text";s:10:"rightThree";s:6:"filter";b:0;}i:6;a:3:
{s:5:"title";s:0:"";s:4:"text";s:8:"rightTwo";s:6:"filter";b:0;}i:7;a:3:
{s:5:"title";s:0:"";s:4:"text";s:8:"rightOne";s:6:"filter";b:0;}i:8;a:3:
{s:5:"title";s:0:"";s:4:"text";s:7:"leftOne";s:6:"filter";b:0;}i:9;a:3:
{s:5:"title";s:0:"";s:4:"text";s:7:"leftTwo";s:6:"filter";b:0;}
s:12:"_multiwidget";i:1;}
[Actually all on one line.]
I want to retrieve the following strings:
mainItem
leftOne/leftTwo/leftThree
rightOne/rightTwo/rightThree
What's the syntax for such a query? And how can I add it to the PHP template?

You can pull all of the information about a type of widget from the database like so:
$text_widgets = get_option( 'widget_text' );
There's no need to use mySQL to get this. This will return an array of all the stored widgets of the type 'text'. Then you can loop through this array and do stuff with the internal properties of each like so:
foreach ( $text_widgets as $widget ) {
extract( $widget );
// now you have variables: $mainItem, $leftOne, $leftTwo, etc.
// do something with variables
}
Or, if you already know the ID's of the widgets you want to interact with, you can access the properties like this:
$mainItem = $text_widgets[17]['mainItem'];

Try below code snippet. It return the array of all widgets stored data.
// 1. Initialize variables
$data = '';
$all_stored_widgets = array();
// 2. Get all widgets using - `$GLOBALS['wp_widget_factory']`
$all_widgets = $GLOBALS['wp_widget_factory'];
foreach ($all_widgets->widgets as $w => $value) {
$widget_data = get_option( 'widget_' . $value->id_base );
foreach ($widget_data as $k => $v) {
if( is_numeric( $k ) ) {
$data['id'] = "{$value->id_base}-{$k}";
$data['options'] = $v;
$all_widgets_css[$value->id_base][] = $data;
}
}
}
// 3. Output:
echo '<pre>';
print_r( $all_stored_widgets );
echo '</pre>';
Output:

Related

array of values from acf repeater into cf7 dropdown

I'm trying to populate a cf7 dropdown with values from an acf repeater. If I use a regular hardcoded array, it works just fine so somehow I'm messing up when getting the values of the repeater field.
Here's what I've got rn, trying to push the values into an array:
add_filter('wpcf7_form_tag_data_option', function($n, $options, $args) {
if (in_array('gigs', $options)){
$gigs = array();
if( have_rows('termine') ):
while ( have_rows('termine') ) : the_row();
$gigs[] = get_sub_field('termin');
endwhile;
endif;
return $gigs;
}
return $n;
}, 10, 3);
tried moving the return statement around a bit but that didn't help either and I am at a loss with my barely existing php knowledge.
Any ideas or pointers where I'm going wrong would be much appreciated.
You do have to return $n which is either null or a value which would be an array. You are close, but your returning the wrong thing. A good example of how to use this filter is by looking at the code from listo.php an you can see the correct usage of this filter.
With that said... without testing your ACF values, I can't say if your function will return those... but the below function is tested and will return data to your select with data:gigs if the ACF function works.
To retrieve the containing post's post_id you need to dig into the unit tag, and get the page id. The global $post won't work inside this filter, as it's not passing any of the loop properties to the function, so you have to specify your ACF field with the second parameter - which needs to be the parent post id.
add_filter( 'wpcf7_form_tag_data_option', 'dd_filter_form_tag_data', 10, 3 );
function dd_filter_form_tag_data( $n, $options, $args ) {
// Get the current form.
$cf7 = wpcf7_get_current_contact_form();
// Get the form unit tag.
$unit_tag = $cf7->unit_tag();
// Turn the string into an array.
$tag_array = explode( '-', $unit_tag );
// The 3rd item in the array will be the page id.
$post_id = substr( $tag_array[2], 1 );
if ( in_array( 'gigs', $options, true ) ) {
$gigs = array();
if ( have_rows( 'termine', $post_id ) ) :
while ( have_rows( 'termine', $post_id ) ) :
the_row();
$gigs[] = get_sub_field( 'termin' );
endwhile;
endif;
$n = array_merge( (array) $n, $gigs );
}
return $n;
}

Convert datetimes from MySQL table to ISO8601 to create JSON feed in WordPress for use with FullCalendar

I've written an action in WordPress that grabs the rows from a table and encodes them in JSON format, so I can use them with the FullCalendar javascript event calendar.
The date fields from the table need to be formatted ISO8601.
In other words, when the DB renders the date/time: 2017-08-06 10:22:20, I need it converted after the query to: 2017-08-06T10:22:20 for the date fields in the query.
I'm not concerned about timezone offsets.
My function:
add_action( 'getmyevents', 'get_my_events' );
function get_my_events( $atts = [], $content = null ) {
// Use WordPress database functions
global $wpdb;
// List of events will be stored in JSON format
$json = array();
// Query retrieves list of events
$mytable = $wpdb->prefix . "my_events";
$myids = $wpdb->get_results("SELECT * FROM " . $mytable );
// sending the encoded result to success page
echo json_encode( $myids, JSON_UNESCAPED_SLASHES );
// return JSON
return $json;
}
Can someone give me a quick, direct way to convert the datetime strings in the query to ISO8601?
Maybe you can try something like this.
Although I don't know the name of your column. Uncomment the print_r to get the column name.
foreach ($myids as $key => $row) {
// print_r($row);
$date_reformatted = strtotime($row->date_col);
$myids[$key]->date_col = date( 'c', $date_reformatted );
}
It isn't the ideal answer I was looking for, but I did come up with a working solution. Mark's suggestion about filtering during the query gave me the clue I needed for it.
add_action( 'getmyevents', 'get_my_events' );
function get_my_events( $atts = [], $content = null ) {
global $wpdb;
// Values sent via ajax to calendar from my_events table
// List of events
$json = array();
// Query that retrieves events
$mytable = $wpdb->prefix . "my_events";
$myids = $wpdb->get_results( 'SELECT id, title, url, DATE_FORMAT( start, "%Y-%m-%d\T%H:%i:%s" ) as start, DATE_FORMAT( end, "%Y-%m-%d\T%H:%i:%s" ) as end, allDay FROM ' . $mytable );
// sending the encoded result to success page
echo json_encode( $myids, JSON_UNESCAPED_SLASHES );
// return JSON
return $json;
}
However, if someone else can come up with an answer that doesn't require me to specify columns by name, that would be great. Even better would be not formatting within the query at all, but rather formatting afterward. I always like to minimize processor use by MySQL as much as possible.

Retrieve every model and return three values

I am looking for a way to retrieve all models in a database. Then loop through all of the models and read out the values for name, firstname and phonenumber.
So far I've gotten this and failed to go past it:
$searchModel = new EmployeeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
I am then looking to implement those three values in a simple HTML table:
<tr><td>$firstname</td><td>$name</td><td>$phone</td></tr>
The table should be part of a PDF output, so ideally I would save it to a variable:
$html_table = '<tr><td>$firstname</td><td>$name</td><td>$phone</td></tr>';
I would need to get this for every model that fulfills the criteria of status = 'active' in the database.
So far I've only been able to get tables via gridView and not in a HTML template either.
You don't really need a data provider to achieve this, you could simply try :
$models = Employee::find()->where(['status'=>'active'])->orderBy('name ASC')->all();
foreach ($models as $model) {
echo "<tr><td>{$model->firstname}</td><td>{$model->name}</td><td>{$model->phone}</td></tr>";
}
Read more : http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#querying-data
You can get all models like this:
$employees = Employee::find()
->select('firstname, name, phone')
->asArray()
->where(['status'=>'active'])
->all();
This way you will get an array of arrays containing the 3 selected fields, so now you only need to use a foreach to loop through them and create the table:
$html = '<table>';
foreach($employees as $employee) {
$html .= '<tr><td>'.$employee['firstname'].'</td><td>'.$employee['name'].'</td><td>'.$employee['phone'].'</td></tr>';
}
$html .= '</table>'

Not able to render external DB data on admin tab

I am trying to to show external database data onto custom admin tab but getting error.Can some one help me to resolve this . I am able to fetch data from external DB but when i pass it to the GridField it gives me this error.
Error###
"get_class() expects parameter 1 to be object, array given"
and here is my code
public function getList() {
$externalDB = $object = Injector::inst ()->create ( 'ExternalDatabase' );
$results = $externalDB->query ( 'SELECT "Course" FROM "Courses"' );
$list = ArrayList::create ();
foreach ( $results as $row ) {
$list->push ( $row ) ;
}
return $list;
}
I have ExternalDatabase Class which resolve my query and return result.
Instead of pushing the row directly, try doing
$list->push(ArrayData::create($row));

Incrementing child element database fetching in codeigniter

I'm trying to fetch a series of ids from a database table that includes cross-referencing - each element, a "topic", includes a column for "parent topic" that is within the same table. Given a single parent topic, I want to build an array of all the subtopics that have it as their parent, and then all of the subtopics of those topics, etc.
This doesn't seem like it's that hard, but as a self-taught programmer I feel I'm using all the wrong tools. The merge-array() and var_dump() sections, in particular, feel wrong and I'm not sure about the overall approach. What should I replace these elements with?
function get_subtopics($parent_topic)
{
//returns an array of subtopics minus the first
$all_subs = array();
$query = $this->db->get_where('topics', array('parent_topic' => $parent_topic));
$subs = $query->result_array();
$resubs = array();
$query->free_result();
//push subs to all_subs
//while the subs array has members, find their child
while (count($subs)>0) {
foreach ($subs as $s) {
$query = $this->db->get_where('topics', array('parent_topic' => $s['id']));
$resubs = array_merge($resubs, $query->result_array());
$query->free_result();
}
$all_subs = array_merge($all_subs, $resubs);
var_dump($resubs);
}
//Returns an array of ids
return $all_subs;
}
EDIT:
The objective of this is to form a "pool" of topics from which problems will be drawn for a random generator - I'm trying to get all of the subtopics into one array, with no tree structure to differentiate them. Users that specify a parent topic, like "math" should get an even mix of math subtopics like "algebra", "algebra:quadratics" or "calculus" from which problems will be drawn. Hope that clarifies a little.
There are 2 ways to do this either just get all the records from the database and build a tree structure using a php recursive function like below.
//Build menu array containing links and subs
$items = Array(
//highest level
'cms' => Array(
'title' => 'CMS',
//Array containing submenu items for cms
'subs' => Array(
'intro-to-cms' => Array('title' => 'Intro to CMS'),
'specific-cms' => Array('title' => 'Specific CMS'),
'installing-a-cms' => Array('title' => 'Installing a CMS')
),
)
);
//Display the menu
echo navlinks($items, $page);
/**
* Recursive function creates a navigation out of an array with n level children
* #param type $items
* #return string containing treestructure
*/
function navlinks($items, $page=false)
{
$html = '<ul>';
foreach ($items AS $uri => $info) {
//Check if the pagename is the same as the link name and set it to current when it is
$html .= '<li'.($info['title'] == $page ? ' class="current"' : '').'>';
echo ' ' . $info['title'] . '';
//If the link has a sub array, recurse this function to build another list in this listitem
if (isset($info['subs']) && is_array($info['subs'])) {
$html .= navlinks($info['subs']);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
In order to just filter on 1 parent with its underlying children you will need a rather tricky query in advance like explained in a previous comment on stackoverflow. (link below)
MySQL parent -> child query