In WordPress, I am creating a plugin where I am sending emails to users. For that, I am using WordPress cron job. So basically what it will do is just send emails to users every hour.
So my code looks like this
public function __construct() {
add_action('init', array( $this, 'send_emails_to_users') );
add_action('cliv_recurring_cron_job', array( $this, 'send_email') );
}
public function send_emails_to_users() {
if(!wp_next_scheduled('cliv_recurring_cron_job')) {
wp_schedule_event (time(), 'hourly', 'cliv_recurring_cron_job');
}
}
public function send_email() {
//send email code goes here
}
Here everything looks good but it does not send the email.
If I make my code like this
public function __construct() {
add_action('head', array( $this, 'send_email') );
}
Then it sends the email. But the problem is here it sends the email on every time the page loads or when the user visits the site.
That's why I want to use wp_schedule_event to make emails every hour.
So can someone tell me how to resolve this issue?
Any suggestions or help will be really appreciated.
First of all ,
1) You need to setup crontab in your server if you want to work dynamically
2) if you want manually wordpress scheduler will call after the page is run
so,
for the crontab setup below is useful link:
crontab
If you want to run your cron in every one hour then you need to add below code:
public function __construct() {
// Call function for cron
add_action('init', array( $this, 'send_emails_to_users') );
}
public function send_emails_to_users() {
if(!wp_next_scheduled('cliv_recurring_cron_job')) {
// Add "cliv_recurring_cron_job" action so it fire every hour
wp_schedule_event(time(), 'hourly', 'cliv_recurring_cron_job');
}
}
add_action('cliv_recurring_cron_job', array( $this, 'send_email') );
public function send_email() {
//send email code goes here
}
for more information see link
Related
My action is called by WP Cron so I'm trying to prevent it from running twice at the same time. So, I have the following function that uses doing_action function to check if the action is running. Apparently, the code below can't run even when the action is not running. But when I removed the doing_action check, the code runs.
function upload_to_ipfs() {
if ( !doing_action( 'upload_file' ) ) {
//Code to run here
}
}
add_action( 'upload_file', 'upload_to_ipfs' );
You should probably have a look at site transients.
<?php
function so_73821350_get_transient_name() {
return 'so_73821350_transient_name'; // replace this with whatever you want
}
function so_73821350_upload_to_ipfs() {
// get the existing transient
//
// If the transient does not exist, does not have a value, or has expired,
// then the return value will be false.
$process_running = get_site_transient( so_73821350_get_transient_name() );
if ( $process_running ) {
// bail out in case the transient exists and has not expired
// this means the process is still running
return;
}
// set the transient to flag the process as started
// 60 is the time until expiration, in seconds
set_site_transient( so_73821350_get_transient_name(), 1, 60);
// Run the upload process here
upload_function();
// ...
// delete the transient to remove the flag and allow the process to run again
delete_site_transient( so_73821350_get_transient_name() );
}
add_action( 'upload_file', 'so_73821350_upload_to_ipfs' );
docs:
get_site_transient()
set_site_transient()
delete_site_transient()
You're running into a scenario where the code won't run because it's calling !doing_action on itself because the action IS running.
Also,
Wordpress doing_action works by looking at a global PHP variable is all.
This will not work since you're probably not on the same thread process (since a new one is started with every PHP request on most servers).
In which case you'll have to resort to an alternative method for checking.
One such alternative is checking the servers running processes for the action. Take a look at something like this https://write.corbpie.com/check-if-a-process-is-running-on-linux-with-php/ to help guide you in the right direction.
function is_server_doing_action(string $process): bool
{
if (empty(trim(shell_exec("pgrep $process")))) {
return false;
} else {
return true;
}
}
function upload_to_ipfs() {
if ( !is_server_doing_action( 'upload_file' ) ) {
//Code to run here
}
}
add_action( 'upload_file', 'upload_to_ipfs' );
I'm working on a feature to send a "cascade" or a chain of notifications with a delay between them with different channel. For example:
Email -> (30 minutes later) -> Push -> (30 minutes later) -> SMS
That flow is working good, now is the user completes something or does an action I want the chain to stop. So I stop or prevent the notification to be sent. This is what I've tried, but nothing seems to stop them.
I've tried:
public function via($notifiable)
{
if (whatever condition to stop) {
return null; // also tried with return []
}
return ['mail'];
}
Also
public function __construct(array $data = [])
{
if (whatever condition to stop) {
exit; // are you desperate, bruh?
}
}
Is there something super obvious I'm not seeing? Might be related to our custom scheduler, tho.
Do you have an idea where can I break the app to prevent the notification to be sent?
Actually, this was enough:
public function via($notifiable)
{
if (whatever condition to stop) {
return [];
}
return ['mail'];
}
The problem was something else, Docker was showing me a cached version of the files, so they were always returning a return ['mail'];
How can I send data from my custom job to custom PHP script in custom module.
For example my custom job do some actions and generate array $data
I want send $data to custom/modules/accounts/mysctipt.php.
I try use $GLOBALS, but in my opinion they are different for job.php and custom/modules/accounts/mysctipt.php.
try use '$_SESSION' - dont work.
"/sugarcrm/custom/Extension/modules/Schedulers/Ext/ScheduledTasks/acc_activities.php" code:
<?php
array_push($job_strings, 'acc_activities');
function acc_activities() {
session_start();
$_SESSION['test'] = 'all_ok';
return true;
}
"/sugarcrm/custom/modules/Accounts/views/view.list.php" code:
require_once('include/MVC/View/views/view.list.php');
class AccountsViewList extends ViewList
{
public function preDisplay()
{
var_dump($_SESSION['test']);
parent::preDisplay();
$this->lv->targetList = true;
}
}
Understood what using session in my problem stupid..
How correctly implement what I want without DB. Any simple solution.
I am facing an issue with Contact Form 7 for Wordpress. I want to disable the email notification which i did using
demo_mode: on
At the same time i want to redirect on submit which i used to do using
on_sent_ok: "location = 'http://domain.com/about-us/';"
Both would work when used individually.But i want to use both at the same time.
I tried doing
on_sent_ok: "location = 'http://domain.com/about-us/';"
demo_mode: on
Doesnt seem to work. Kindly advice.
The plugin author has changed as of at least 4.0 the way you should do this again. The skip_mail property is now private :
class WPCF7_Submission {
private $skip_mail = false;
...
}
You should use this filter : wpcf7_skip_mail
For example :
function my_skip_mail($f){
$submission = WPCF7_Submission::get_instance();
if(/* YOUR TEST HERE */){
return true; // DO NOT SEND E-MAIL
}
}
add_filter('wpcf7_skip_mail','my_skip_mail');
The author of the plugin Contact Form 7 has refactored some of the code for its version 3.9 and since then the callback function for the hook wpcf7_before_send_mail must be written differently.
To prevent Contact Form 7 from sending the email and force it to redirect after the form has been submitted, please have a look at the following piece of code (for version >= 3.9):
add_action( 'wpcf7_before_send_mail', wpcf7_disablEmailAndRedirect );
function wpcf7_disablEmailAndRedirect( $cf7 ) {
// get the contact form object
$wpcf7 = WPCF7_ContactForm::get_current();
// do not send the email
$wpcf7->skip_mail = true;
// redirect after the form has been submitted
$wpcf7->set_properties( array(
'additional_settings' => "on_sent_ok: \"location.replace('http://example.com//');\"",
) );
}
Hook into wpcf7_before_send_mail instead of using the flag .
add_action("wpcf7_before_send_mail", "wpcf7_disablemail");
function wpcf7_disablemail(&$wpcf7_data) {
// this is just to show you $wpcf7_data and see all the stored data ..!
var_dump($wpcf7_data); // disable this line
// If you want to skip mailing the data..
$wpcf7_data->skip_mail = true;
}
Just an update. The following works in 4.1.1.
on_sent_ok: "location = 'http://domain.com/about-us/';"
demo_mode: on
Set skip_mail: on does the trick.
There might have been a change to contact-form-7, because I wasn't able to access the $skip_mail variable in the WPCF7_Submission object. I looked at the submission.php object in the \wp-content\plugins\contact-form-7\includes\submission.php file and found this:
private $skip_mail = false;
Since the variable is private, and there are no getters or setters in the file, you're not going to be able to change it externally. Just change it to this:
public $skip_mail = false;
and then you can change the variable like this in your functions.php file:
add_filter('wpcf7_before_send_mail', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url( $form)
{
$submission = WPCF7_Submission::get_instance();
$submission->skip_mail = true;
}
A reminder, if you update the contact-form-7 plugin, it will probably nullify your change, so keep that in mind.
Simple code
Copy and paste the following code in your activated theme functions.php file.
add_filter('wpcf7_skip_mail','__return_true');
UPDATE WPCF7 ver. 7.5: There is now a filter specifically to handle this.
function my_skip_mail($f){
$submission = WPCF7_Submission::get_instance();
$data = $submission->get_posted_data();
if (/* do your testing here*/){
return true; // DO NOT SEND E-MAIL
}
}
add_filter('wpcf7_skip_mail','my_skip_mail');
I have a controller action that is supposed to collect some preliminary information prior to user registration (head's up, I haven't hooked up auth yet, no one bug out on security plz!) and then redirect to the appropriate controller action, but I can't figure out how to pass an entire array of data. It's possible that I'm just too tired and I'm going to wake up to a facepalm here, but if anyone can set me straight I'd appreciate it.
public function register() {
if ($this->request->is('post')) {
if ($this->request->url == "users/register") {
$data = $this->request->data('Registration');
switch($data['UserType']) {
case "student_reg":
/* I've tried this, and it feels right.. do have I to stop autorender or something? */
$this->studentReg($data);
break;
case "educator_reg":
/* and this: */
$this->redirect(array("action" => "educatorReg", "params" => $data));
break;
/* ... and so on.... */
}
}
}
$this->loadModel("Account");
$accounts = $this->Account->find( 'all');
$provinces = Hash::combine($accounts, '{n}.Account.province_id', '{n}.Province.name');
$this->set(compact('accounts','provinces'));
}
public function studentReg($data) {// and so forth
If you just do return $this->studentReg($data); you should be fine. Cake shouldn't render another view if one has already been rendered.