Jump to content
Sign in to follow this  

Disappearing Announcements

Recommended Posts

Bit stumped.

The Setup:  Say I have an announcement in English, and I have not made any other language text by hook or by the Admin interface for Announcements.

Using AnnouncementEdit hook, on save, I add a record in tblannouncements, set to the second language (parentid = englishid, language = newlanguage)

I do that addition with insertGetId, and yeah, I get the new id for the inserted tblannouncements record just fine.    It's sequential, the next one that was available.

However, a second later, the record is not there.   Doing a refresh on the tblannouncements table in phpMyAdmin, the new language  record never shows, like it never existed.

I'm able to take that insertGetId number and put it into a different table, which is why I know what it is and that it existed.

So the id advances one each time -- but on save, something erases the new announcement  record made in my hook.

Can someone point me to where this happens?   Cuz it's not in my hook, spent like 5 hours going over it.

Guessing it is a "nobody but WHMCS is allowed to insert an announcement record with parentid" feature 👊


Share this post

Link to post
Share on other sites
Posted (edited)

Without knowing the code, it is difficult to make a conclusion. If I were in this situation, the first thing I would do would be to see if the entry was really added (even if the ID was incremented, and that speaks for it) by looking for the ID in the database right after the insertGetId query and logging the content via:

logActivity (json_encode($query->field));

If the expected content is logged, I would then grep for any hooks that change something in the announcement table.

Edit: The other thing I would think of is that WHMCS may automatically remove incorrect entries. For example, if some relation is not correct. To exclude this thesis, you can place the existing values of an entry in your hook, delete the entry from the database and see what happens if you run the hook again.

Edited by string

Share this post

Link to post
Share on other sites


When the initial announcement is created or edited, the AnnouncementEdit/AnnouncementAdd hook point is run. 

After this hook point is run, the announcement logic will sync the languages within the announcement based on the data entered in the form just submitted. Part of the sync removes all child entries and then loops through each language and loops through only inserting rows where the content has been defined for the language.

Your issue here is that you are attempting to insert a row into the table just before the sync happens.

I have opened CORE-16927 internally to change when the hook points mentioned above run to ensure that all the announcement data has been written. 

Share this post

Link to post
Share on other sites

I have just noticed, as a workaround, you could use the API to add/update your announcements where this hook does run differently, without the additional language sync.

Share this post

Link to post
Share on other sites
Posted (edited)

Andrew and string, thanks so much for the investigation, and yes, I suspected there was some check and clear routine associated with the Add/Edit hooks.

My workaround was fairly simple -- I just moved the function to the AdminAreaPage hook and tested for filename/pagetitle to filter.  Worked fine there, avoided the extra checking from the other hook points.

Really appreciate you confirming this was an intended feature.

We're using the announcements table as product pages -- the explanation of the products/services for the clients, adding pid and gid columns to suit.

My code is auto-inserting the language rows for the announcements (we have quite a few), using automated translations hooks to fetch the translations and insert them on the fly.   Native language staff later review the auto-translations, only making minor corrections,  rather than starting with a blank page.

Andrew,  appreciate the job to look at adjustment in hook point running: 

On 23/07/2021 at 11:35 AM, WHMCS Andrew said:

I have opened CORE-16927 internally to change when the hook points mentioned above run to ensure that all the announcement data has been written. 

string, I did use your:

On 22/07/2021 at 1:08 AM, string said:

logActivity (json_encode($query->field));

most useful, thanks for that -- and yes, it is created for a few milliseconds and then gets "cleaned up" by the AnnouncementEdit hook.

Cheers mates!


The function where this was happening -- at the insertGetId , made a note about 1/3 way down:

function checkAnnounce ($pid, $lang) {
    $product = Capsule::table('tblproducts')->where('id',$pid)->first();
    if ($product) {
        $trantime = date('Y-m-d H:i:s');
        $productname = trim($product->name);
        if (strlen($productname) < 3) {
            $productname = '('.Lang::trans('product.placeholder').' for Solution '.$pid.')';
        $hourly = intval($product->is_hourly);
        $pid = intval($product->id);
        $aid = intval($product->aid);
        $gid = intval($product->gid);
        $kid = intval($product->kid);
        $slug = trim($product->slug);
        $descproduct = trim($product->description);
        $thisannounce = Capsule::table('tblannouncements')->where([['pid',$pid],['language','']])->first();
        $descannounce = $thisannounce->announcement;
        if ($descannounce == null) {
            $descannounce = ' '.Lang::trans('thisnewsolution');
        $tranparent = $thisannounce->id;
        //additional languages added here in foreach after beta
        $tranlang = 'romanian';
        $tranphrase = '<h5>În prezent traducem această pagină în limba română</h5>';
        if (strlen($descannounce) < 10) {
            $descannounce = $descproduct;
        /*in case the friggin' name changed, update English version... */
        $update = Capsule::table('tblannouncements')->updateOrInsert(array('pid'=> $pid, 'language'=>''), array('date' => $trantime,'updated_at' => $trantime, 'pid'=>$pid,'gid'=>$gid,'kid'=>$kid, 'published'=>1, 'language'=>'', 'parentid' => 0, 'announcement' => $descannounce));
        $getenglish = Capsule::table('tblannouncements')->where([['pid',$pid],[ 'language','']])->first();
        if ($getenglish && ($aid == 0 || $aid !== $getenglish->id)) {
            $aid = $getenglish->id; //the aid has changed.
            $productupdate =  Capsule::table('tblproducts')->where('id',$pid)->update(array('aid'=>$aid,'gid'=>$gid,'name'=>$productname));
            $tranparent = $getenglish->id;
        $gettran = Capsule::table('tblannouncements')->where([['pid',$pid],[ 'language',$tranlang],['parentid',$tranparent]])->first();
        if ($gettran) {
            $tranaid = $gettran->id; //the aid has changed.
            //check for defective tran (too short compared to english)
            if (strlen($gettran->announcement) < (.9*strlen($getenglish->announcement))) {
                $updatetran = Capsule::table('tblannouncements')->where([['pid',$pid],[ 'language',$tranlang],['parentid',$tranparent]])->update(array('announcement'=>$getenglish->announcement));
        } else {
            /* This is where the announcement was created and then deleted when run with trigger of AnnouncementEdit hook */
            $tranannounce = Capsule::table('tblannouncements')->insertGetId(array('date' => $trantime,'updated_at'=>$trantime,'title' => $productname,'pid'=>$pid,'gid'=>$gid,'kid'=>$kid, 'published'=>0, 'language'=>$tranlang, 'parentid'=>$tranparent, 'announcement' => $tranphrase.$thisannounce->announcement));
            $tranaid = $tranannounce;
        $gettran = Capsule::table('tblannouncements')->where([['pid',$pid],[ 'language',$tranlang],['parentid',$tranparent]])->first();
        //now see if we can move any Solutions translations into the foreign Solutions page name/desc IF needed (short announcement)
        if (strlen($gettran->announcement) < 15) {

            //Finally update (or make additional) announcement records in foreign language using only the dynamic translations IF there is no foreign announcment, and dynamic record exists. 
            $trans = Capsule::table('tbldynamic_translations')->where([['related_id', $pid],['related_type','product.{id}.name'],['language',$tranlang]]) ->get();
            $tranname = $productname; //incase there are no trans for later
            $targetname = $tranname;
            foreach ($trans as $tran) {
                if ($tran->language !== 'english') {
                    $tranname = $tran->translation;
                    $tranlang = $tran->language;
                    #if ($tranlang == $lang) {
                        $targetname = $tranname;
                } else {
                    //in case there is NO foreign announcement for the pid yet. 
                    $tranname = $productname.' '.ucwords($tranlang);
                    $tranlang = ''; // english in announcements is blank, not 'english'
                    $parentid = 0;
                $targetname = $tranname;
                $tranannounce = Capsule::table('tblannouncements')->updateOrInsert(array('parentid'=> $tranparent, 'language'=>$tranlang), array('date' => $trantime,'title' => $tranname,'pid'=>$pid,'gid'=>$gid,'kid'=>$kid, 'published'=>1, 'language'=>$tranlang, 'parentid'=>$tranparent)); 
            $transdescs = Capsule::table('tbldynamic_translations')->where([['related_id', $pid],['related_type','product.{id}.description'],['language',$tranlang]]) ->get();
            $trandesc = $descproduct; //in case there are no trans for later 
            $targetdesc = $trandesc;
            foreach ($transdescs as $tran) {
                $trandesc = $tran->translation;
                $tranlang = $tran->language;
                $targetdesc = $trandesc;
                $announce = Capsule::table('tblannouncements')->where([['parentid',$tranparent],['language',$tranlang]])->first();
                 if ($announce && strlen($announce->announcement) < 10 ) { 
                    $tranannounce = Capsule::table('tblannouncements')->where([['parentid',$tranparent],['language',$tranlang]])->update(array('date' => $trantime,'announcement' => $trandesc));
        foreach ($needtrans as $needtran) {
            $tranaid = $needtran->id;
            //make a new todo record for Zapier
            $product = Capsule::table('tblproducts')->select('description')->where(id,$needtran->pid)->first();
            $descproduct = trim($product->description); //needed for intro
            $strsize = 960;
            $maxsize = 998;
            $helpphrase = htmlspecialchars('<br/><h6><a href="https://domain.name/helpdesk">Let us know how else we may help you!</a></h6>');//this will be later translated by Zapier
            $announcement = str_replace($tranphrase,'',$needtran->announcement);
            if (strlen($announcement) > 0) {
                $announcement = htmlspecialchars($announcement.' ',ENT_NOQUOTES);
                $announcement = str_replace('&amp;amp;','&',$announcement);
                $descannounce1 = null;
                $descannounce2 = null;
                $descannounce3 = null;
                $descannounce4 = null;
                $descannounce5 = null;
                $descannounce6 = null;
                $nextstart = 0;
                $thislen = $strsize;
                for ($d = 1; $d < 6; $d++) { 
                    $dstring = 'descannounce'.$d;
                    $$dstring = substr($announcement,$nextstart,$strsize);
                    $lastspace = $strsize + 1;
                    while ($thislen > 0 && $lastspace > $strsize) {
                        $lastspace = strrpos($$dstring," "); //last space
                        $$dstring = substr($$dstring,0,$lastspace);
                        $thislen = strlen($$dstring);
                        $nextstart += $thislen;
                    if ($thislen == 0) {
                        $$dstring = null;
                        $lastdstring = 'descannounce'.($d-1);
            if ($thislen == 0 && strlen($$lastdstring) < ($strsize-strlen($helpphrase))) {
                $$lastdstring .= $helpphrase;
            } else {
                $$dstring .= $helpphrase; 
            $trantodo = Capsule::table('tbltodolist')->insert(array('aid'=> $tranaid,'date' => $trantime,'admin'=>1,'title' => trim($needtran->title),'intro'=>$descproduct,'description'=>$descannounce1,'description2'=>$descannounce2,'description3'=>$descannounce3,'description4'=>$descannounce4,'description5'=>$descannounce5, 'description6'=>$descannounce6,'status'=>'In Progress','do_announce'=>true,'do_product'=>false));
        $viewbutton = viewButton($aid,$pid,$gid,$kid,$lang);
        $editbutton = editButton ($aid,$lang);
        if (1==2) {
            $transReplace = tranUpdates();
            $trandone = $transReplace['trandone'];
            $trancount = $transReplace['trancount'];
        return array("tranname"=>$targetname,"trandesc"=>$targetdesc,"tranlang"=>$tranlang,"viewbutton"=>$viewbutton,"editbutton"=>$editbutton);


Edited by HancoEuropa
Included code from function

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated