WordPress/Codeigniter Integration - Pass WP shortcode attribute to CI script - php

I have successfully integrated WordPress with Codeigniter. I have created a plugin that adds a shortcode that can be used in the editor. This also works as expected. Here is my code:
function get_property_filters($atts) {
foreach ($atts as $key => $value) {
$_POST['property_type'] = $value;
}
return 'Something to replace shortcode in WP Page';
}
add_shortcode('property_filters', 'get_property_filters');
What I need to do is send a POST variable from my WP plugin to a CI script, hence the line:
$_POST['property_type'] = $value;
I understand that the return value of the function that handles the shortcode is meant to replace the shortcode with some text or widget, etc in the Page/Post. I plan to replace the shortcode with an empty string. But, within the function that handles the shortcode, how can I send a POST variable to my Codeigniter script?
I have searched for hours on this. It seems to be a very specific question. Your help is appreciated.
EDIT: I had a thought about using session variables to save the value, but it doesn't seem like I can set a session variable in WP and access it from CI. Any suggestions along this line of thought?
EDIT 2: I also had the idea to query the WP database from the CI script using $wpdb. It is possible to do this and already works in some scenarios, however, I cannot get the post_content field directly from the WP database, instead I get the rendered text. i.e. My shortcode is replaced with the word "land", but I want the query to return the shortcode that was used in the WP page, not the replacement string.

If you want to send a POST data directly into a CodeIgniter script, you can use PHP's cURL library (make sure it is installed in your web server).
Important: First you will need to disable CodeIgniter's CSRF check. You could disable from the entire framework, or you could create a pre-system hook to disable CSRF in a specific controller.
Here is an example of a cURL request in your WP script:
$value = "POST VALUE";
$post_data = array();
$post_data["property_type"] = $value;
$codeigniter_url = "http://example.com/codeigniter/handle_post";
$post = curl_init();
curl_setopt($post, CURLOPT_URL, $codeigniter_url); //The URL to send the request
curl_setopt($post, CURLOPT_POST, count($post_data)); //Amount of POST fields
curl_setopt($post, CURLOPT_POSTFIELDS, $post_data); //The POST data.
curl_setopt($post, CURLOPT_RETURNTRANSFER, TRUE); //Returns the output from the requested script
curl_setopt($post, CURLOPT_SSL_VERIFYPEER, FALSE); //Do not verify the SSL certificate.
//The variable below will have the output from your Controller function in CodeIgniter.
$result = trim(curl_exec($post));
//The variable below will have any possible errors from the cURL request.
$errors = trim(curl_error($post));
//Now you can work with the $result variable which contains the results from your CI
//Controller.
Then, you can create your controller to handle your post request in CodeIgniter:
class Handle_post extends CI_Controller {
public function index()
{
$property_type = $this->input->post("property_type");
//Your actions here...
echo "RESULT FROM THE CONTROLLER IN CODEIGNITER";
}
}
For more information about PHP's cURL library, you can read the manual.
Best regards.

Just for addition to your approach regarding retrieval of content from Wordpress DB.
You can also make use of REST web-service means then from CI you only need to call the url and which correspondingly provides the required data in json or any format that you like.
And for creating a web-service inside WordPress, you can make use of this plugin :
https://wordpress.org/plugins/json-api/

I had to solve this using a completely different solution than any of the ones I mentioned above. The code below still needs to be tweaked, but you can get the idea.
I had to add this function to my WP plugin:
function save_shortcodes_to_db($content) {
global $post;
$postID = $post->ID;
global $wpdb;
if (has_shortcode($content, 'property_filters')) {
$filterArr = array('area=', 'prop_type=', 'agent=', 'office=');
foreach ($filterArr as $filter) {
$filterpos = strpos($content,$filter); //63
if ($filterpos !== false) {
$filterstrlen = strlen($filter); //10
$filterendpos = $filterpos + $filterstrlen - 1;
$offset = $filterendpos;
$valuestartpos = $filterendpos + 1;
$endbracket = ']';
$endbracketpos = strpos($content,$endbracket,$offset);
$valuelen = $endbracketpos - $valuestartpos;
$meta_value = substr($content,$valuestartpos,$valuelen);
$meta_key = 'rc_'.rtrim($filter,'=');
$data = array('post_id' => $postID, 'meta_key' => $meta_key, 'meta_value' => $meta_value);
$wpdb->insert('wp_postmeta', $data);
}
}
}
return $content;
}
add_filter( 'content_save_pre' , 'save_shortcodes_to_db' , 10, 1);
Then, in my CI controller index function, I added this:
global $wpdb;
if ($this->session->userdata('referer')) {
$pageurl = $this->session->userdata('referer');
$pos = strpos($pageurl,'listings');
if ($pos !== false) {
$page_by_path = get_page_by_path($pageurl);
$postid = $page_by_path->ID;
$content = $wpdb->get_col("SELECT post_content FROM $wpdb->posts WHERE ID=".$postid.";");
$prop_type_meta_value = $wpdb->get_col("SELECT meta_value FROM $wpdb->postmeta WHERE post_id=".$postid." AND meta_key = 'rc_prop_type';");
$data['wp_content'] = $content[0];
}
}
Basically, before the WP page is updated, my WP function saves some information from the shortcode(s) that were entered into the page by the end user to the postmeta table in WP. Then, my controller function retrieves the information, and uses it in the rest of the code. The only issues I still need to address are:
when the WP page is new, there will not be a post_id
I need to replace values in the WP postmeta table that have already been set for the page
I am sure these are easily fixed. As for a solution to the original question - set data in WP and retrieve it in CI - this answer is complete.

Related

All validation errors displaying in CMS (pulling data from api call into CMS)

I'm trying to pull data from an API and when the information is pulled into the fieldsets within my CMS, I want to ensure that whatever has been pulled from the API is validated properly with the rules I currently have set up within my CMS (eg. an image can be no bigger that 1920x1080 in dimensions).
Here is my code:
use App\Utilities\BardUtil;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Http;
use Statamic\Eloquent\Entries\EntryModel;
use Statamic\Events\EntrySaved;
use Statamic\Facades\Entry;
public function handle(EntrySaved $event): void
{
$entry = $event->entry->model();
if ($entry->collection != 'companies') {
return;
}
$data = collect($entry->data);
if (!isset($data['tickers'][0])) {
return;
}
$tickerId = $data['tickers'][0];
$ticker = EntryModel::find($tickerId);
if ($ticker && $ticker->title) {
$tickerTitle = $ticker->title;
$response = Http::get('apicallurlexample');
$fields = $event->entry->blueprint()->fields();
$items = $response->json('results.0');
$items['companyName'] = $items['exchangeName'];
$data = $data->merge($items);
$data['slug'] = $entry->slug;
$data['date'] = $entry->date;
$fields = $fields->addValues($data->toArray());
$collection = $event->entry->collection();
$site = $event->entry->site();
$rules = Entry::updateRules($collection, $site);
$replacements = [
'id' => $entry->id,
'collection' => $collection,
'site' => $site,
];
$fields
->validator()
->withRules($rules)
->withReplacements($replacements)
->validate();
$event->entry->data($fields->values()->all());
$event->entry->saveQuietly();
}
}
I think the issue lies within the following code:
$fields
->validator()
->withRules($rules)
->withReplacements($replacements)
->validate();
What's happening when I save the company details is that it displays all the validation errors, even if the data hasn't went against any of the rules. Any help would be appreciated and thanks in advance.
Sorry for the rather late reply but thought I'd update this thread anyways for others who find this later.
Statamic only uses the validation rules you define in your blueprint/fieldset when saving entries/terms/etc in the Control Panel.
When you save data manually (eg. via PHP or directly editing the Markdown files), no validation checks are ran on it. You'll need to manually do any kind of validation in your code, before the entry is created in Statamic.

Problems receiving POST variables from PHP

I have a function developed by PHP that at the moment all I want it to do is to return the value of the variable $_POST['token']
I tried:
public function actionGetuserbytoken() {
$data = json_decode(file_get_contents("php://input"), TRUE);
$id = $data['token'];
return $id;
}
Or I also just tried:
public function actionGetuserbytoken() {
return $_POST['token'];
}
I tried doing the POST with Insomnia to check what is going on:
I feel this is a very absurd question but I can't understand why I can't get the value of the POST in either of the two ways.
The php://input stream can only be read once per request. Yii is likely reading the payload before you can, which means that the body is empty when you read the data.
Instead of using php://input, try the following:
$data = json_decode(Yii::app()->request->getRawBody(), true);

Database request in routing controller

I'm making a website with categories and products. The categories and the products are both contenttypes. Categories can't be a taxonomy type because the editor of the website has to change data for the categories. To solve this problem i created a custom routing:
products:
path: /{catslug}/{slug}
defaults: { _controller: 'Bolt\Controllers\Frontend::record', contenttypeslug: 'products' }
requirements:
catslug: 'Bolt\Controllers\Routing::getAnyCategorieRequirement'
I added a function in Routing.php (I will later move it to an extension):
public function getAnyCategorieRequirement()
{
$slugs = array();
foreach($this->app['storage']->getContent("categories") as $cat){
$slugs[] = $cat['slug'];
}
return implode("|", $slugs);
}
But then I bumped into a problem:
Accessed request service outside of request scope. Try moving that call to a before handler or controller.
So I temporarily commented out the database request and added a default slug to $slugs:
public function getAnyCategorieRequirement()
{
$slugs = array();
$slugs[] = "hollandse-kazen";
return implode("|", $slugs);
}
This way everything worked as expected. Now my question: How can I do this database request in the routing controller, or is there a workaround for this problem?
Ross Riley's first solution worked for me:
$slugs = array();
//Do complicated request because of [url to stackoverflow]
$stmt = $this->app['db']->query('SELECT slug FROM bolt_categories');
while($cat = $stmt->fetch()){
$slugs[] = $cat['slug'];
}
return implode("|", $slugs);
This way it works as expected:)
This is unfortunately a known issue with Bolt's getContent() method that depends on being in the request loop, as discussed here: https://github.com/bolt/bolt/issues/2129
The two ways around it are to use $app['db'] to make a raw query to the db, rather than using getContent()
The other is to temporarily overwrite $app['request'] to allow it to work. Something like this will do the job.
use Symfony\Component\HttpFoundation\Request;
.....
$oldRequest = $app['request'];
$app['request'] = Request::createFromGlobals();
....
<do database call here>
....
$app['request'] = $oldRequest;

Open Graph Meta Tag Overwritting Yoast, WordPress

I'm trying to change the og:url content on specific posts but I am unsure how to implement my changes from the functions.php file.
I have tried doing this using the content I have found on the internet but believe it has been updated since then.
I have updated the class-opengraph.php file in the the wordress-seo plugin folder which works, please find my edits below:
public function url() {
$url = apply_filters('wpseo_opengraph_url',
WPSEO_Frontend::get_instance()->canonical(false));
if (is_string($url) && $url !== '' ) {
if (is_page(32721)) {
$this->og_tag('og:url', esc_url('testing'));
} else {
$this->og_tag( 'og:url', esc_url( $url ) );
}
return true;
}
return false;
}
It's not good to modify the plugin files directly because when you update the plugin, you will lose all your changes to those files.
There are two solutions that I have found to do such thing.
You get the instance of the class WPSEO_Frontend, then update it's options for the og:url.
e.g.
$object = WPSEO_Frontend::get_instance();
$object->options['og_url'] = esc_url( $url );
This can be added before the wp_head()
You can use add_filter to hook a function to the filter action. We use the filter action below.
Filter: 'wpseo_opengraph_url' - Allow changing the OpenGraph URL
e.g.
function update_og_url($url) {
return "http://www.yoursampleurl.com";
}
add_filter('wpseo_opengraph_url', 'update_og_url', 10, 1);
Source: Wordpress SEO API

WordPress Custom Filter - apply_filters multiple

I'm building a way to extend a WordPress plugin I'm developing using the following filter for grabbing the html content from a different plugin:
$content = apply_filters('satl_render_view', array($view, $slides));
With just one plugin this works perfectly, but once I activate a second plugin utilizing this same filter it stops working, $content is null for either plugin:
I'm adding the filters on the plugins in the __construct() method:
add_filter('satl_render_view', array('SatellitePortraitPlugin','addRender'));
and
add_filter('satl_render_view', array('SatelliteAwesomePlugin', 'addRender'));
Anyone run into this before?
In case it helps, this is the addRender method as it currently stands:
public static function addRender($params)
{
list($view, $slides) = $params;
$plugin = new SatelliteAwesomePlugin();
return $plugin->render($view, array('slides' => $slides, 'frompost' => 'false'), false);
}
For the record, I've tried remove_filter() if there is no content to return, but that didn't solve the problem.
Params get passed to callback function, in this case addRender() and contain all the HTML of what is wanted to display to the second plugin using that same filter. To utilize this bit of information one must change the method:
public static function addRender($params)
{
if (is_array($params)) {
list($view, $slides) = $params;
$plugin = new SatelliteAwesomePlugin();
return $plugin->render($view, array('slides' => $slides, 'frompost' => 'false'), false);
} else {
return $params;
}
}
You also need to make sure to update how the render() method passed the proper information back to the apply_filters method so the next plugin would have the proper array to run the addRender()
} else {
return array($file,$params['slides']);
}
Main Learning: WordPress apply_filters is much dumber than you'd think. You can't assume it merges everything for you, it just passes the information along and your code needs to make sense of it.

Categories