Forum for discussing general topics related to Couch.
16 posts Page 2 of 2
Wow..... That's cool... Happy to help you.. Let me know what type of app and help you need from my side....
KK wrote: Hi,

Perhaps the following post would help? -
viewtopic.php?f=2&t=9268



Dear KK,

I tried the mentioned way and could successfully send notifications to mobile device on page save.
Thank you so much.

This is how I tried:

I added a radio button in news.php
Code: Select all
<cms:editable  name="push_noti"  label="Push Notification Settings"  opt_values='Ignore Notification=0 | Notify Users=1'  type='radio' opt_selected = '1' />


Then in kfunctions.php,

Code: Select all
$FUNCS->add_event_listener( 'page_saved', 'my_page_save_handler');
$FUNCS->add_event_listener( 'page_presave', 'my_pre_save_handler', 10 );

$CTX->global_noti_val = 0;
function my_pre_save_handler( &$page ){
    global $CTX;
    if( $page->tpl_name == 'news.php' ){
   if($page->_fields['push_noti']->get_data() == '1') {
      $CTX->global_noti_val = 1;
      $page->_fields['push_noti']->store_posted_changes( '0' );
   }
    }
}

function my_page_save_handler( &$page, &$error_count){
   global $CTX;
    if( $page->tpl_name=='news.php' ){
        if((!$error_count) && ($CTX->global_noti_val == 1)){
         $CTX->global_noti_val = 0;
      
         //$name_en = $page->_fields['name_en']->get_data();
         // Send Notifcation block
         // sendNotification($name_en);
      }
   }
}



But, now again I need your help here.
I am saving the notification tokens in a cloned page named 'notification_tokens.php'.
I need to iterate through 'notification_tokens.php' page in 'my_page_save_handler' or 'sendNotification' functions to get the notification tokens.
I tried few things in my way, but didn't work out.


Thanks in advance.


--Asha
Dear KK,

I was away from work last few weeks and rejoined my duties 2days back.

I have somehow done the Firebase notification part.
Want to post the update here, if someone else needs it. :idea:

As I said earlier, I added a radio button in news.php and events.php
Code: Select all
<cms:editable  name="push_noti"  label="Push Notification Settings"  opt_values='Ignore Notification=0 | Notify Users=1'  type='radio' opt_selected = '1' />


Also, have the device tokens saved in a file named noti.php.

Then the changes in kfunctions.php,
Note: The apps and website are multilingual, English & Arabic

Code: Select all
$FUNCS->add_event_listener( 'page_saved', 'uam_page_save_handler');
$FUNCS->add_event_listener( 'page_presave', 'uam_pre_save_handler', 10 );

$CTX->global_noti_val = 0;
function uam_pre_save_handler( &$page ){
    global $CTX;
    if( $page->tpl_name == 'news.php' || $page->tpl_name == 'events.php'){
      $pushfield = $page->_fields['push_noti']->get_data();
      if($pushfield && $pushfield == '1') {
         $CTX->global_noti_val = 1;
         $page->_fields['push_noti']->store_posted_changes( '0' );
      }
    }
}

function uam_page_save_handler(&$page, &$error_count){
   global $CTX, $DB;
   if(($page->tpl_name == 'news.php' || $page->tpl_name == 'events.php') && !$error_count && $CTX->global_noti_val == 1){
      $CTX->global_noti_val = 0;
      setUpNotifications($page);
   }    
}


function setUpNotifications($page) {
   global $CTX, $DB;
   $rs = $DB->select( K_TBL_PAGES . " p inner join ".K_TBL_TEMPLATES." t on t.id=p.template_id", array('p.*'), "t.name='" . "noti.php". "'" );
   if( count($rs) ){
      foreach ($rs as $result) {
         $pg = new KWebpage( $result['template_id'], $result['id'] );
         if( !$pg->error ){
            $token = $pg->_fields['device_token']->get_data();
            if(strlen($token) >= 100) {         
               $notilang = $pg->_fields['device_app_language']->get_data();
               $pagename =  substr($page->_fields[(($notilang == "ae") ? 'name_ae': 'name_en')]->get_data(),0,125);
               $descfield = $page->_fields[(($notilang == "ae") ? 'content_ae': 'content_en')];
               $pagedesc = $descfield ? substr(strip_tags($descfield->get_data()),0,1025) : "";
               $pagesection = explode(".php", $page->tpl_name)[0];
               $pageSectionName = "";
               if($pagesection == "news") $pageSectionName = ($notilang == "en") ? "News: " : "الأخبار: ";
               if($pagesection == "events") $pageSectionName = ($notilang == "en") ? "Events: " : "الأحداث: ";
               sendNotification($token, $pagedesc, $pageSectionName.$pagename, '{FIREBASE KEY}', $pagesection , $page->id);
            }
         }
       }
   }
}

function sendNotification($devicetoken, $mesg, $title, $api_key, $section, $page_id) {
    $registrationIds = $devicetoken;
    $msg = array
        (
        "body" => $mesg,
        "title" => $title,
      'sound' => 'default'
    );
   $data = array
        (
        "body" => $mesg,
        "title" => $title,
      "section" => $section,
      "id" => $page_id,
      'sound' => 'default',
      "vibrate" => true,
      "alert" => $title,
      "channel" => "{YOUR CHANNEL}",
    );
    $fields = array
        (
        'to' => $registrationIds,
        'notification' => $data,
      'data' => $data,
        'priority' => 'high',
    );
    $headers = array
        (
        'Authorization: key=' . $api_key,
        'Content-Type: application/json'
    );
   #Send Reponse To FireBase Server   
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    $result = curl_exec($ch);
    curl_close($ch);
    $cur_message = json_decode($result);
    if ($cur_message->success == 1)
        return $result;
    else
        return $result ;
}



Am sure this is not the best way to do it, but somehow achieved in sending Firebase notifications to the app installed devices on News & Events page updates.

One major issue I face here is the delay in page save with sending notifications on, as the process is synchronous and I have lot of device tokens now.
Will be great if you could guide me to avoid the delay in proper way and even to make the code more precise & better.


And again and again...
COUCHCMS IS THE BEST. LOVE IT MORE & MORE & SPENDING MORE TIME ON IT NOW. :o 8-)

Thanks a lot KK.


--
Asha



ashaantony wrote:
KK wrote: Hi,

Perhaps the following post would help? -
viewtopic.php?f=2&t=9268



Dear KK,

I tried the mentioned way and could successfully send notifications to mobile device on page save.
Thank you so much.

This is how I tried:

I added a radio button in news.php
Code: Select all
<cms:editable  name="push_noti"  label="Push Notification Settings"  opt_values='Ignore Notification=0 | Notify Users=1'  type='radio' opt_selected = '1' />


Then in kfunctions.php,

Code: Select all
$FUNCS->add_event_listener( 'page_saved', 'my_page_save_handler');
$FUNCS->add_event_listener( 'page_presave', 'my_pre_save_handler', 10 );

$CTX->global_noti_val = 0;
function my_pre_save_handler( &$page ){
    global $CTX;
    if( $page->tpl_name == 'news.php' ){
   if($page->_fields['push_noti']->get_data() == '1') {
      $CTX->global_noti_val = 1;
      $page->_fields['push_noti']->store_posted_changes( '0' );
   }
    }
}

function my_page_save_handler( &$page, &$error_count){
   global $CTX;
    if( $page->tpl_name=='news.php' ){
        if((!$error_count) && ($CTX->global_noti_val == 1)){
         $CTX->global_noti_val = 0;
      
         //$name_en = $page->_fields['name_en']->get_data();
         // Send Notifcation block
         // sendNotification($name_en);
      }
   }
}



But, now again I need your help here.
I am saving the notification tokens in a cloned page named 'notification_tokens.php'.
I need to iterate through 'notification_tokens.php' page in 'my_page_save_handler' or 'sendNotification' functions to get the notification tokens.
I tried few things in my way, but didn't work out.


Thanks in advance.


--Asha
ashaantony wrote: Dear KK,
..
One major issue I face here is the delay in page save with sending notifications on, as the process is synchronous and I have lot of device tokens now.
Will be great if you could guide me to avoid the delay in proper way and even to make the code more precise & better.

Maybe my idea could also help here? :)

/ There is a garbage collector in Couch that runs jobs asynchronously @couch/addons/mosaic/gc/gc.php so perhaps that could inspire you?

/ Your current code fetches all pages from a dedicated template and runs curl for each of the page. Now, if I encountered the process too slow due to more than a handful of pages involved, I would personally try to request a single special template which would in turn request itself in a paginated way, starting a self-expanding chain of page calls in background (with a small timout). ( I think I already tried that while working on a function that runs any code paginated by parts ).

/ Almost similar alternative is that clicking Save opens a new page in browser ( visible to admin ), which will use well known `paginated` approach used in CSV importer, based on javascript-set timeout and page reload. Helpful to review the process of sending out notifications in case of logged errors, possible action buttons (pause, restart, ignore error and continue etc. ).

/ If that wouldn't work as desired, then I'd try to add the single cron job which would go through published pages in the dedicated template, fire a notification and unpublish successfully processed pages. In this scenario your option (Save and Notify) would merely set pages in dedicated template as `published` and be terminated (later cron would actually send a notification).

/ Also current code can be modified a bit to avoid checks for named templates, to make code more portable (perhaps this better be a dedicated notifications addon).

/ I won't be surprised if there is some other good advice here from @KK :)
@trendoman, the GC was designed for low priority background jobs (e.g. completely deleting removed pages and templates). So, while it will work, there would be no guarantees as to how much time the process takes to complete.

I think for this use-case, using the 'staggered' approach (either adapting the CSV importer (viewtopic.php?f=5&t=8803) or the special template technique you mentioned) would be more apt. Setting up a server cronjob will also be fine if immediate feedback is not required.

@ashaantony, to trigger a separate template that sends out the notifications incrementally, upon successful page save you may inject into the template either some JS to spawn a separate window or inject an IFRAME.

If that interests you, following is my reply to @ivo who wanted something similar (open up the template on the frontend automatically upon saving it) - perhaps you'll find it useful.

========================== quote ========================
My question is - can pressing the Save button for specific non-cloning templates execute this code - thus eliminating the need for the admin to press the Browse button after each entry?

Please try the following -
1. Suppose your template is named 'test.php', we'll override its 'content_form.html' snippet (you'll recall that this renders the form view in admin-panel). The process is explained in detail here viewtopic.php?f=2&t=10438&p=25693#p25696 - it would mean that we'll have to rename the template to content_form_test-php.html.

2. So now whatever changes we make in the overridden template, will show up in the edit panel of our template.
At the very top of the template you'll see the following block of code -
Code: Select all
<cms:if "<cms:get_flash 'submit_success' />" >
    <cms:admin_add_js>
        $(function() {
            toastr.success("Your changes have been saved", "Success", { // TODO: localize
                "positionClass": "toast-bottom-right",
                "showDuration": "250",
                "hideDuration": "250",
                "timeOut": "2500",
                "extendedTimeOut": "500",
                "icon": '<cms:show_icon 'check' />'
            });
        });
    </cms:admin_add_js>
</cms:if>

Modify it to make it as follows -
Code: Select all
<cms:if "<cms:get_flash 'submit_success' />" >
    <cms:admin_add_js>
        $(function() {
            toastr.success("Your changes have been saved", "Success", { // TODO: localize
                "positionClass": "toast-bottom-right",
                "showDuration": "250",
                "hideDuration": "250",
                "timeOut": "2500",
                "extendedTimeOut": "500",
                "icon": '<cms:show_icon 'check' />'
            });
        });
    </cms:admin_add_js>
   
    <cms:admin_add_html>
        <iframe src="<cms:show k_page_link />" scrolling="no" frameborder="0"></iframe>
    </cms:admin_add_html>
</cms:if>

Now whenever you save the template, you'll see an IFRAME added to the page that loads the template from the frontend (this should be the same as you manually visiting the template on the frontend).

Once you are happy with the arrangement, add a CSS style to the IFRAME to set its display to none.

==========================quote end =====================

You can set the 'src' of the IFRAME to your target template (or use this technique to open up a separate browser window by putting in some JS)..

Hope this helps.
Your current code fetches all pages from a dedicated template and runs curl for each of the page. Now, if I encountered the process too slow due to more than a handful of pages involved, I would personally try to request a single special template which would in turn request itself in a paginated way, starting a self-expanding chain of page calls in background (with a small timout). ( I think I already tried that while working on a function that runs any code paginated by parts ).


to trigger a separate template that sends out the notifications incrementally, upon successful page save you may inject into the template either some JS to spawn a separate window or inject an IFRAME.


@trendoman & @KK
Initially I tried this way only,
To open the noti.php, pass the details to the page and process the notification from the page. But was not successful in doing it from the page_save_handler
Any working examples will be really appreciated.

@KK,
Will try the way you mentioned...
16 posts Page 2 of 2