Problems, need help? Have a tip or advice? Post it here.
16 posts Page 1 of 2
Hello,

I need to create a notification system inside my project.
At the point I am in the project, I cannot use something else than Couch, so I have to find a way to make this work.

What I need, is to set notifications to be sent using send_mail (or something else if possible, whatever works), at a specific set date and time, using a field in the clonable page edit page.

In the admin, it looks a bit like this:
Image

I need to set a date and time, click the "Set notification", and make sure (by having a confirmation) that the email will be sent, filled with information from that page, at the date and time entered, automatically.

How can I achieve this?
I can pay if needed. Like I said, I cannot go back and choose another CMS, so I have to make this work within CouchCMS.

Thanks a lot!
A review of this job hints on 2 parts:

First part is to make CouchCMS execute some template code at exact minute, regardless of any visitors online. As you probably noticed, CouchCMS does not run in the background every moment. (Very much as other CMSs) It fires up only when someone actually requested a page with Couch code. So, one must refer to any other instrument that *is* working in background constantly to periodically call up one of CouchCMS-managed pages. This task is usually delegated to OS. For example, unix-based hosting servers do have a "cron" utility that has a special purpose - execute something at a certain time and periodically. You may check with your hosting company about this.

Second and last part is to code the sending script. This part can solely rely on CouchCMS and, in particular, "cms:pages" to find all contracts with matching time and "cms:send_mail" to actually do the job.
Thanks.

I can work with Cron Jobs on my server.

Basically, here's what I tried :

Created a file named "notifications.php" with the following code:
Code: Select all
<?php require_once( 'edit/cms.php' ); ?>
<cms:pages masterpage='contract.php'>
<cms:send_mail from='sender@whatever.com' to='receiver@whatever.com' subject='Test Email' >
Hello <cms:show name/>, here's the content of your contract:
<cms:show contract_pricing/>
</cms:send_mail>
</cms:pages>
<?php COUCH::invoke(); ?>


And on my server, there's a cron job that is supposed to run the file every 5 minutes (just to test it), but nothing happens.
What am I doing wrong? Is that because this particular file doesn't know at what time the cron is supposed to run? Or maybe it doesn't know which client is related to that notification?
If nothing happens, check it in the following order:

1. Is "notifications.php" registered by superadmin and visible in the backend?
2. Temporarily place following code in notifications.php to check if cron works okay and file log.txt in site's root updated:
Code: Select all
<cms:log "cron job started at <cms:date format='H:i:s' />" />


If above things are okay, we can now be sure that any valid code placed in the template is successfully called upon (every 5 minutes, as you said).
I can't make it work.

The code of the notifications.php page is:
Code: Select all
<?php require_once( 'edit/cms.php' ); ?>
<cms:log "cron job started at <cms:date format='H:i:s' />" />
<?php COUCH::invoke(); ?>


And my Cron line is:
Code: Select all
*/5 * * * * php -f -q /home/mediod7/public_html/calendar/notifications.php


Nothing gets log to the txt file.
But if I visit that notifications.php page, it works.

Any idea?
Thank you very much
If logging works in case you visit the page manually, without cron, this, I am afraid, is not something that couch code could solve.. Maybe path in your cron def is not correct?
You were right!
I managed to make it right. I was using the wrong Cron command line.

I changed the content of that page for "send_mail", and it worked too.

Now that the cron thing is working, what is left is allowing the user to fire the script at a specific time for that specific clonable page, set by the user via the admin. That cron job should be sent at the date the user selected.

Any idea how I can achieve this?
Thank you again
fire the script at a specific time for that specific clonable page


Okay, it worked. So, to achieve what you need with couch, I think an editable type='datetime' would be very helpful. viewtopic.php?p=12667#p12667 Or maybe you plan to use publish_date for that?
I am using the "datetime" region as you can see in my first post image.
I am not sure on how to first, set the time and date a cron job should be fired, and 2, how to make sure it sends the email containing the data related to the one clonable page I have clicked on "Set notification".

The email should contain details concerning an upcoming event.
So basically, when I create a contract for an event, the client linked with this event should receive an email 24 hours before the event to remind them about that said event.

Of course, if I decide to set multiple notifications, set a different times for different contracts, it should work too.

Any idea?
Thank you very much once again
Okay, great. So now we have all parts set up. Could you also post your final *working* cron command? Maybe it will help those who come to this topic much later.

--
I am not sure on how to first, set the time and date a cron job should be fired

Your cron job, as you said, requests "notifications.php" every 5 minutes. So, every 5 minutes a script should look for pages that have the datetime editable set at this time (+/- 1 minute, maybe). It is important to understand, that we do not set any specific date to cron, instead we let it run periodically. (It will run even if you don't have any notifications yet). This helps to concentrate the efforts on the couch script.

The button "set notification" can be removed in my opinion, because it creates an illusion that notification is being set somewhere if pressed. Just choose the date and time in the editable and save the cloned page. Template should have the code to find pages that have the same time (or close to that) in editable. This task is handled via regular "cms:pages" with custom_field parameter. For a notification scheduled to Apr 25, 2018 6:10 am the following code finds the page with that notification (my editable is named my_datetime). I realize that script might have a delay of some kind or time sync issues, so to make sure I look for anything from 6:09 and 6:11.
Code: Select all
<cms:pages masterpage='notifications.php' show_future_entries='1' custom_field="my_datetime >= '2018-04-25 06:09' | my_datetime <= '2018-04-25 06:11' " >
...
</cms:pages>


If you (or anyone else) use the publish_date, the same search could be done via "cms:pages" with parameters start_on, stop_before, there are samples in docs for that, so I won't repeat it now.


--
script sends the email containing the data related to the one clonable page

When you have this cloned page found - you can place whatever ("cms:send_mail", as you said) within the "cms:pages" block.


--
if I decide to set multiple notifications

If you mean to set several dates and times, then perhaps this could be handled via several datetime editables? Alternative solution is to move everything regarding notifications to a separate template, so a contract can have a relation editable set to that template with type="many" and therefore have an unlimited number of notifications, associated with the contract. Each notification becomes a separate cloned page. Fortunately, the method to find cloned pages is absolutely the same - with custom_field we look for pages which time falls in a desired (current) time period.

One final note to the sample above. You want to find the pages when cron calls the script, so the date in custom_field must be set programmatically to the date and time of request. Here is a sample modification (pay attention to quotes as we have an expression):
Code: Select all
<cms:pages masterpage='notifications.php' show_future_entries='1' custom_field="my_datetime == <cms:date format='Y-m-d H:i:00' />" >
...
</cms:pages>


I really urge you to test things *not* programmatically and step by step, using some real page and type in your date in a static form, to make sure each and every step works fine before the last modification of the code.

Above I use "cms:date" to return the time when the page was accessed. It works just fine, and note that I typed "00" instead of "s" in time format, because seconds are always zeroed in a datetime editable. I think you can see that it is a deep caveat to fall into (with seconds) when using date set programmatically.

A very important consideration: datetime editable in database is stored in format like "2018-04-25 06:10:00" (Y-m-d H:i:s), so database will search for exactly this format in case you have "==" in custom_field (second sample).
Otherwise, if you use "<=" and ">=" as in my first sample, then it is possible to have a diminished format, like "<cms:date format='Y-m-d H:i' />, which is handy to skip seconds as well (though they can be zeroed as above). Finally, if you need to programmatically return time +/-1 minute, there is a topic on that viewtopic.php?f=8&t=10559
16 posts Page 1 of 2