I'd like to run a php script from cli which will access a WP plugin's class.
I've seen plenty ways of loading WP environment from cli, most common which I also use is
if( php_sapi_name() !== 'cli' ) {
die("Meant to be run from command line");
}
function find_wordpress_base_path() {
$dir = dirname(__FILE__);
do {
//it is possible to check for other files here
if( file_exists($dir."/wp-config.php") ) {
return $dir;
}
} while( $dir = realpath("$dir/..") );
return null;
}
define( 'BASE_PATH', find_wordpress_base_path()."/" );
define('WP_USE_THEMES', false);
global $wp, $wp_query, $wp_the_query, $wp_rewrite, $wp_did_header;
require(BASE_PATH . 'wp-load.php');
However the above code will not load the plugins and if I try to access a plugin's class i get the error "Call to undefined method". I've also
tried running it from wp-cli using eval-file command, but again with no luck.
any ideas on how to load wordpress environment with plugins from cli ?
Related
Setting:
I have a wordpress site but disabled wp_cron to have the full control of cron.
define('DISABLE_WP_CRON', true);
In crontab -e, I have following cron job:
*/2 * * * * /usr/bin/php /var/www/cron/mycron.php init >> /var/log/error.log 2>&1
The mycron.php has a simple function
if (!empty($argv[1])) {
switch ($argv[1]){
case 'init':
cron_test();
break;
}
}
function cron_test() {
$time = date(DATE_RFC822, time());
write_log("Start:" . $time); //outputs debug to my own log file
};
function write_log($log){
if ( true === WP_DEBUG ) {
if ( is_array( $log ) || is_object( $log ) ) {
write_log( print_r( $log, true ) );
} else {
write_log( $log );
}
}
};
Note that I declared the mycron.php in functions.php for wp:
require_once('parts/mycron.php');
Error log:
In my error.log for the cron, I have the following error:
PHP Warning: Use of undefined constant WP_DEBUG - assumed 'WP_DEBUG'
So, I am guessing there is some sort of disconnection between cron and wp, which is my best guess.
What I am trying to do:
The mycron.php will have many wordpress functions that I would need. How do I make the cron to recognize the wp function such as WP_DEBUG?
Any help will be much appreciated.
Thanks!
You need to load Wordpress functions manually, to use them in a custom script.
require_once("../../../../wp-load.php");
Also answered in depth here,
How to include Wordpress functions in custom .php file?
I am writing integration tests for a plugin, and I did everything using wp-cli and scaffolding the tests. And they are running fine when I run phpunit. But the problem I have is that I am using composer and npm - composer for some extra functionality, and npm for bundling my scripts.
The scripts part is important because I'm enqueueing the scripts from the public folder (build folder)
$main_script = 'public/scripts/application.js';
wp_register_script( 'plugin-scripts', plugin_dir_url( __DIR__ ) . $main_script, array() );
wp_enqueue_script( 'plugin-scripts' );
I need to test if my scripts and styles are enqueued, so I added a test
public function test_enqueued_scripts() {
$this->admin->enqueue_styles();
$this->assertTrue( wp_script_is( 'plugin-scripts' ) );
}
$this->admin is just an instance of the class where my enqueue method is in the setUp() method.
And I get an error because it says that Failed asserting that false is true.
The plugin I'm testing is built and composer is installed. All the folders exist and everything works when I'm locally on my WordPress instance. But the test instance is not the same as my local instance (ofc). I error_loged in the enqueue method to check if the file_exist and I get false.
I need to test this with phpunit (clients requirements are to have full test coverage).
My bootstrap.php looks like this
<?php
/**
* PHPUnit bootstrap file
*
* #package Plugin
*/
$_tests_dir = getenv( 'WP_TESTS_DIR' );
if ( ! $_tests_dir ) {
$_tests_dir = rtrim( sys_get_temp_dir(), '/\\' ) . '/wordpress-tests-lib';
}
if ( ! file_exists( $_tests_dir . '/includes/functions.php' ) ) {
echo "Could not find $_tests_dir/includes/functions.php, have you run bin/install-wp-tests.sh ?" . PHP_EOL;
exit( 1 );
}
// Give access to tests_add_filter() function.
require_once $_tests_dir . '/includes/functions.php';
/**
* Manually load the plugin being tested.
*/
function _manually_load_plugin() {
// Update array with plugins to include ...
$plugins_to_active = array(
'advanced-custom-fields-pro/acf.php',
'my-plugin/my-plugin.php',
);
update_option( 'active_plugins', $plugins_to_active );
require dirname( dirname( dirname( __FILE__ ) ) ) . '/advanced-custom-fields-pro/acf.php';
require dirname( dirname( __FILE__ ) ) . '/my-plugin.php';
}
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
// Start up the WP testing environment.
require $_tests_dir . '/includes/bootstrap.php';
How can I start the build process (npm run build) so that my scripts exist before my unit tests? Also is it possible to have this build step run only once, not once every time I run phpunit?
A very basic solution would be to check for a file that npm creates with file_exists() in your bootstrap.
If it aint there, run the build with shell_exec()
http://php.net/manual/en/function.file-exists.php
http://php.net/manual/en/function.shell-exec.php
You need to run do_action('wp_enqueue_scripts') prior to executing your assertions. This article has more details and an example. So, your test should look like this:
public function test_enqueued_scripts() {
$this->admin->enqueue_styles();
do_action('wp_enqueue_scripts');
$this->assertTrue( wp_script_is( 'plugin-scripts' ) );
}
I've tested this solution and it works.
I am using a PHP page to backup my database and it works just perfectly.
My problem (my future problem, Id better say) is that my cron job in my hosting allows working function only if a response is returned by 5 seconds, otherwise it fails.
My DB so far is quite small and I am not sure how much time it takes but surely less than 5 seconds since it is working.
But when my db will grow up, I reckon issues will start.
How can I make my function working also after 5 seconds?
With an async function will I solve?
hm, do you have shell access?
i made my index.php and its called master class to detect cli mode. like so:
if( php_sapi_name() === 'fpm-fcgi') {
define( 'WEB_MODE', true );
define( 'CLI_MODE', false );
} else if (php_sapi_name() === 'cli') {
define( 'WEB_MODE', false );
define( 'CLI_MODE', true );
} else {
define( 'WEB_MODE', true );
define( 'CLI_MODE', false );
}
then in my script which is executed by http request i do it like so:
$this->asyncShellExecution('/usr/bin/php ' . ROOT_PATH .'/php/index.php -m houseKeeping' );
private function asyncShellExecution(string $str)
{
exec($str . " > /dev/null 2>/dev/null &");
}
in cli mode i call new asyncHouseKeeping()
class asyncHouseKeeping
{
function __construct()
{
$args=getopt("m:t:i:o:l:s:f:");
if($args['m'] == 'houseKeeping') {
$this->doHouseKeeping();
} else {
exit;
}
}
}
that way i am getting the cpu and time critical image optimization process after uploading images by xhr out of the blocking code and it runs it stuff afterwards.
On my server the WP_Filesystem does not work.
If I use the standard file_put_contents and file_get_contents the files are read and written just normally.
Do you know what may be the issue?
THIS DOES NOT WORK (RETURNING NO ERRORS):
global $wp_filesystem;
// Initialize the WP filesystem, no more using 'file-put-contents' function
if (empty($wp_filesystem)) {
require_once (ABSPATH . '/wp-admin/includes/file.php');
WP_Filesystem();
}
if(!$wp_filesystem->put_contents( $path, $file_contents, 0644) ) {
return esc_html__('Failed to put file', 'magellan');
}
THIS WORKS:
file_put_contents($path, $file_contents);
My website having feature requirement of blogging. I have to make blog which would look same like my website appearance.
How to combine CodeIgniter and Wordpress blogging(only) functionality such that it should look like within same website?
I have seen this question: Wordpress template with codeigniter. But didn't got much clue.
Seems like a bit of overkill.
Why not use a Restful service like json_api to retrieve your posts, then copy over the css file(parts)?
You do this you will need to create 2 files and modify 2 existing functions. One function is in CodeIgniter and the other is in Wordpress.
Here are the steps.
1.) Open your configs/hooks.php file and create a pre_controller hook as follows:
$hook['pre_controller'] = array(
'class' => '',
'function' => 'wp_init',
'filename' => 'wordpress_helper.php',
'filepath' => 'helpers'
);
2.) Create a new file in your helpers directory called 'wordpress_helper.php', and add the following code to it:
/**
*
*/
function wp_init(){
$CI =& get_instance();
$do_blog = TRUE; // this can be a function call to determine whether to load CI or WP
/* here we check whether to do the blog and also we make sure this is a
front-end index call so it does not interfere with other CI modules.
*/
if($do_blog
&& ($CI->router->class == "index" && $CI->router->method == "index")
)
{
// these Wordpress variables need to be globalized because this is a function here eh!
global $post, $q_config, $wp;
global $wp_rewrite, $wp_query, $wp_the_query;
global $allowedentitynames;
global $qs_openssl_functions_used; // this one is needed for qtranslate
// this can be used to help run CI code within Wordpress.
define("CIWORDPRESSED", TRUE);
require_once './wp-load.php';
define('WP_USE_THEMES', true);
// Loads the WordPress Environment and Template
require('./wp-blog-header.php');
// were done. No need to load any more CI stuff.
die();
}
}
3.) Open wp-includes/link-template.php and made the following edit:
if ( ! function_exists('site_url'))
{
function site_url( $path = '', $scheme = null ) {
return get_site_url( null, $path, $scheme );
}
}
4.) Copy url_helper.php from the CodeIgniter helper folder to your APPPATH helper folder
and make the following edit:
if ( ! function_exists('site_url'))
{
function site_url($uri = '', $scheme = null)
{
// if we are in wordpress mode, do the wordpress thingy
if(defined('CIWORDPRESSED') && CIWORDPRESSED){
return get_site_url( null, $path, $scheme );
}else{
$CI =& get_instance();
return $CI->config->site_url($uri);
}
}
}
The steps above will allow you to dynamically load either your CI app or your WP site based on some simple filtering. It also gives you access to all CI functionality within WP of that is something you can use.