Insert PHP file in functions.php then echo variables from that file in Wordpress - wordpress

After trying to find a solution to this, I've decided I'm not bright enough. So, please help.
Here the idea: have a file (ip.php) detect the visitors' country/city, call it once in functions.php (or header.php), then echo/print variables from this ip.php file into the other Wordpress theme files (for example footer.php).
This is the ip.php content:
<?php
function getUserIP()
{
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
$_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
$client = #$_SERVER['HTTP_CLIENT_IP'];
$forward = #$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote = $_SERVER['REMOTE_ADDR'];
if(filter_var($client, FILTER_VALIDATE_IP))
{
$ip = $client;
}
elseif(filter_var($forward, FILTER_VALIDATE_IP))
{
$ip = $forward;
}
else
{
$ip = $remote;
}
return $ip;
}
$user_ip = getUserIP();
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;
$cityDbReader = new Reader('/html/nocache-ip/GeoLite2-City.mmdb');
$record = $cityDbReader->city($user_ip);
$country = $record->country->name;
?>
Using the following in the header.php works fine for the header:
require_once( ABSPATH . '/nocache-ip/ip.php' );
echo "\nYou came from $country\n";
The country, city names are displayed. But when trying to use the same code again in the footer.php, it doesn't work (Undefined variable: country).
So this is the issue. How can I make echo/print the visitor's country in other parts of the theme, while calling the ip.php only once?
I've read about having to make all this into a function, then add it to functions.php somehow and then calling the variables with country(); unfortunately this is above my head.

You can use include so that your function is available, example: <?php include 'yourfunctionpage.php';?>

Related

Get parameter from url and pass it in add_filter not returning dynamic value wordpress

I am facing a weird problem. I am trying to override value in a function using apply_filter.
Here is the code which I am using in the theme's functions.php file:
function customized_params_6e9668( $attrs ) {
$subfolder = isset($_GET["sub"]) ? '/'.$_GET["sub"] : '';
$attrs["folder"] = $attrs["folder"].$subfolder; // if getting the value from the url then not working in this case
//$attrs["folder"] = $attrs["folder"]."/testing"; // if I use static name then working in this case
echo $attrs["folder"];
return $attrs;
}
add_filter( "customized_params_6e9668", "customized_params_6e9668");
Here is the function where I am using apply_filter to override the values in the plugin's file.
function getFolderData(){
global $wpdb;
$folder_data = $wpdb->get_row(
$wpdb->prepare(
'SELECT * FROM ' . $wpdb->prefix . 'folders WHERE key=%s',
trim(sanitize_text_field($_REQUEST["data_key"]))
)
);
if(!empty($folder_data)){
$folder_data = apply_filters( 'customized_params_'.$folder_data->key, $folder_data );
print_r($folder_data);
}
}
This function is getting the list of data from the database. overriding the value of the folder using add_filter.
Please correct me where I am doing wrong.
Thanks in advance.

Unit Testing with Fat-Free-Framework

Is there a way to use PHPUnit where I have a test folder with indexTest.php inside that tests routes in my index.php file?
The fat-free guide gives snippets of code for mocking route requests and POSTS. I have only managed to get such a test to work if I generate the route directly in my test file with whatever functionality in it.
What I would like is to mock a route with tokens, allow it to run from a route in index.php and through the controller and test f3 variables that should be set by running the route.
<?php
class indexTest extends \PHPUnit_Framework_TestCase
{
public function test()
{
$f3 = Base::instance();
// Don't write to STDOUT
$f3->set('QUIET', true);
$f3->route('GET /path', function(){ echo 'TEXT'; });
$this->assertNull($f3->mock('GET /path'));
$this->assertSame('TEXT', $f3->get('RESPONSE'));
$f3->route('GET /verify/#answer/#value',
function($f3, $params){
$errors = array();
$answer = $params['answer'];
$value = $params['value'];
$prefix = substr($answer, 0, 3); //pre, ans, pos
$id = (int)substr($answer, 3); //question id number (1, 2, 3, 4)
//$value is the input value from user
$result = check_id($prefix, $id, $value);
if($result !== true){
$errors[] = $result;
}
$f3->set('errors', $errors);
return $errors;
});
function check_id($prefix, $id, $value)
{
if($prefix == 'pre' || $prefix == 'pos'){
if($value <= 0 || $value > 180 || $value === NULL){
echo 'The input value of ' . $prefix . $id . ' question was out of bounds';
return 'The input value of ' . $prefix . $id . ' question was out of bounds';
}else{
return true;
}
}else if($prefix == 'ans'){
if($value < 0 || $value > 10 || $value === NULL){
echo 'The value of quiz ans' + $id + ' was out of bounds';
return 'The value of quiz ans' + $id + ' was out of bounds';
}else{
return true;
}
}else {
return 'The prefix does not match';
}
}
$this->assertNotNull($f3->mock('GET /verify/ans1/8'));
$this->assertEmpty($f3->get('RESPONSE')[0]);
$this->assertNotNull($f3->mock('GET /verify/dsk4/6'));
$this->assertSame('6', $f3->get('PARAMS.value'));
$this->assertSame('dsk4', $f3->get('PARAMS.answer'));
$this->assertEmpty($f3->get('RESPONSE')[0]);
$this->assertNotNull($f3->mock('GET /verify/pre4/250'));
$this->assertSame('The input value of pre4 question was out of bounds', $f3->get('errors')[0]);
$this->assertNotSame('pre4', $f3->get('PARAMS.answer'));
$f3->set('QUIET',FALSE); // allow test results to be shown later
$f3->clear('ERROR'); // clear any errors
}
}
I'd prefer not to declare the entire route like this, maybe I am entirely wrong and this is not possible? The above code works running vendor/bin/phpunit. Relative examples and tutorials are difficult to find on this.
Short answer
Separate your controller code from bootstrapping and routing code
Reuse the routing configuration in your environments, e.g. website, CLI and testing environment
Use Base->mock() in your tests to mock the previously defined routes
Don't execute Base->run() in the testing environment
Long answer
I'm planning for a long time to write an article about testing F3 routes but due the lack of time I will just give some points here instead:
Create a reusable file which defines the routes (e.g. a routes.php file or a INI file with route defintions)
Load the routes before running test code. This could be easily done with a custom bootstrap file for PHPUnit (--bootstrap <FILE> or use the according directive in PHPUnit's configuration).
Write the PHPUnit tests
Example
The following example is an adaption of my GitHub Gist:
bootstrap-website.php
<?php
$f3 = Base::instance();
require 'bootstrap-shared.php';
// [Custom rules only for the website here]
require 'routes.php';
$f3->run();
bootstrap-test.php
<?php
$f3 = Base::instance();
require 'bootstrap-shared.php';
// [Custom rules only for testing environment here]
$f3->set('QUIET', true);
$f3->set('APP.TEST', true);
require 'routes.php';
routes.php
<?php
/**
* #var $f3 Base
*/
$f3->route('GET /path', function(){ echo 'TEXT'; });
ExampleTest.php
class ExampleTest extends PHPUnit_Framework_TestCase {
public function test() {
// Could also be provided by a custom base TestCase.
$f3 = Base::instance();
$this->assertNull($f3->mock('GET /path'));
$this->assertSame('TEXT', $f3->get('RESPONSE'));
}
}
Some notes:
bootstrap-test.php is the custom bootstrapping file for PHPUnit
bootstrap-website.php is the bootstrapping file for the website
bootstrap-shared.php contains information shared by all environments. The file could include routing information. I separated the routing information in the example: routes.php
ExampleTest.php is a regular PHPUnit test
The $f3->set('QUIET', true); snippet should be added to the custom bootstrap file. It's also a good idea to introduce a variable showing that the application is running in a test mode, for instance $f3->set('APP.TEST', true)
F3 doesn't clean up your variables between tests/mocks. You could store the original state before running tests and then restore the state in PHPUnit's setUp() method
Instead of rendering pages it could also be sufficient to collect only the data which should be available for rendering. In this case use the introduced APP.TEST variable in your view to skip rendering
Notes for later answer updates
ini_set('error_log','./phpunit/error.log')
$f3->set('ONERROR',function(){});

Download multiple images in zip in Wordpress

I am working on my personal wordpress site that distribute images.
In single post page, I registered several images via ACF(Advanced Custom Fields) and I know how to get image path/filename through get_field ACF function.
I just googled then found this page, but how can I apply this technique to wordpress site?
Download multiple images into zip
Now I am stuck...
On single post page, place the url of download_zip.php file, where you will place all your code for creating zip.
On single post page:
Download ZIP
In variable 'model_id', place the post id of the single post.
Now create a download_zip.php file on the root of your wordpress setup, where wp-config.php file exists.
Here is the code of download_zip.php file.
<?php
/*File for downloading the gallery zip files*/
$post_id = $_GET['model_id'];
require_once('wp-blog-header.php');
require_once('/wp-admin/includes/file.php');
WP_Filesystem();
$files_to_zip = array();
$zip = new ZipArchive();
$title = get_the_title($post_id);
$destination = wp_upload_dir();
//var_dump($destination);
$destination_path = $destination['basedir'];
$DelFilePath = str_replace(" ","_",$title).'_'.$post_id.'_'.time().'.zip' ;
$zip_destination_path = $destination_path."/".$DelFilePath;
if(file_exists($destination_path."/".$DelFilePath)) {
unlink ($destination_path."/".$DelFilePath);
}
if ($zip->open($destination_path."/".$DelFilePath, ZIPARCHIVE::CREATE) != TRUE) {
die ("Could not open archive");
}
//this is only for retrieving Repeater Image custom field
$row1 = get_field('acf_field_name1',$post_id);
$row1 = get_field('acf_field_name2',$post_id);
$rows = array($row1,$row2);
if($rows) {
foreach($rows as $row): ?>
<?php
$explode = end(explode("uploads",$row));
$index_file = array($destination_path,$explode);
$index_file = implode("",$index_file);
$new_index_file = basename($index_file);
$zip->addFile($index_file,$new_index_file);
endforeach;
}
$zip->close();
if(file_exists($zip_destination_path)) {
send_download($zip_destination_path);
}
//The function with example headers
function send_download($file) {
$basename = basename($file);
$length = sprintf("%u",filesize($file));
header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.$basename.'"');
header('Content-Transfer-Encoding: binary');
header('Pragma: public');
header('Content-Length: ' . $length);
set_time_limit(0);
ob_clean();
flush();
readfile($file); // "Outputs" the file.
unlink($file);
}
?>
Please modify this code according to your requirement such as get_field(), place your image field name inside it, & define your upload directory, so that you can break the url in $explode variable for defining path of image in $index_file variable.
And please also check your destination path stored in $destination_path variable is correct or not.
Hope, this may be helpful to you.

Naming Drupal 7 template files based on url

If I have a page whose url alias is "/api/user/create", how can I name a template file based on the url such as "page-api-user-create.tpl.php".
You need to name it:
page--api--user--create.tpl.php
(note double dashes in the file name).
See http://drupal.org/node/1089656 for more info.
You can set up a page level template file to reflect the url, as was explained by Maciej Zgazdaj.
To do the same with a node level template file you have to add this to your template.php file:
function YOURTHEME_preprocess_node(&$variables) {
$url = str_replace("-", "", $variables['node_url']);
$urlParts = explode("/", $url);
unset($urlParts[0]);
if($urlParts[1] !== false) {
$out = array();
$sug = "node";
foreach($urlParts as $val) {
$sug .= "__".$val;
$out[] = $sug;
}
$variables['theme_hook_suggestions'] =
array_merge($variables['theme_hook_suggestions'], $out);
}
}
Replace YOURTHEME with .. well your theme. Check the offered suggestions with devel_themer.

Wordpress Author Permalinks

I know how to change the base of the author permalinks, however on my site, I refer to users not by their username but by a number based on their User ID, so User number 5 wrote this post, rather than JohnDoe123 wrote this post.
The problem comes when I go to that users archives and instead of seeing something like example.com/authors/5/ I see example.com/authors/johndoe123/ .
How do I change permalinks so that I can pull up author archives using the following structure? :
[wordpress_site_url]/authors/[user_ID]/
This can be done by adding new rewrite rules for each user in exactly the same way you would when changing or removing the author base. So, adapting code from a previous answer, you would add your rewrite rules something like this:
add_filter('author_rewrite_rules', 'my_author_url_with_id_rewrite_rules');
function my_author_url_with_id_rewrite_rules($author_rewrite) {
global $wpdb;
$author_rewrite = array();
$authors = $wpdb->get_results("SELECT ID, user_nicename AS nicename from {$wpdb->users}");
foreach ($authors as $author) {
$author_rewrite["authors/{$author->ID}/page/?([0-9]+)/?$"] = 'index.php?author_name=' . $author->nicename . '&paged=$matches[1]';
$author_rewrite["authors/{$author->ID}/?$"] = "index.php?author_name={$author->nicename}";
}
return $author_rewrite;
}
And then filter the author link:
add_filter('author_link', 'my_author_url_with_id', 1000, 2);
function my_author_url_with_id($link, $author_id) {
$link_base = trailingslashit(get_option('home'));
$link = "authors/$author_id";
return $link_base . $link;
}
Actually I don't think you need to create rules for each user in this case, the following two rules should suffice:
add_filter('author_rewrite_rules', 'my_author_url_with_id_rewrite_rules');
function my_author_url_with_id_rewrite_rules($author_rewrite) {
$author_rewrite = array();
$author_rewrite["authors/([0-9]+)/page/?([0-9]+)/?$"] = 'index.php?author=$matches[1]&paged=$matches[2]';
$author_rewrite["authors/([0-9]+)/?$"] = 'index.php?author=$matches[1]';
return $author_rewrite;
}

Resources