Changeset 6153

Show
Ignore:
Timestamp:
07/23/08 18:27:55 (4 months ago)
Author:
p_lindheimer
Message:

#2069 Migrate recordings to recording ids

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/branches/2.5/ringgroups/functions.inc.php

    r6061 r6153  
    3939        } else { 
    4040                return false; 
     41        } 
     42} 
     43 
     44function ringgroups_recordings_usage($recording_id) { 
     45        global $active_modules; 
     46 
     47        $results = sql("SELECT `grpnum`, `description` FROM `ringgroups` WHERE `annmsg_id` = '$recording_id' OR `remotealert_id` = '$recording_id' OR `toolate_id` = '$recording_id'","getAll",DB_FETCHMODE_ASSOC); 
     48        if (empty($results)) { 
     49                return array(); 
     50        } else { 
     51                //$type = isset($active_modules['ivr']['type'])?$active_modules['ivr']['type']:'setup'; 
     52                foreach ($results as $result) { 
     53                        $usage_arr[] = array( 
     54                                'url_query' => 'config.php?display=ringgroups&extdisplay=GRP-'.urlencode($result['grpnum']), 
     55                                'description' => "Ring Group: ".$result['description'], 
     56                        ); 
     57                } 
     58                return $usage_arr; 
    4159        } 
    4260} 
     
    6381                                        $postdest = $grp['postdest']; 
    6482                                        $grppre = (isset($grp['grppre'])?$grp['grppre']:''); 
    65                                         $annmsg = (isset($grp['annmsg'])?$grp['annmsg']:''); 
     83                                        $annmsg_id = (isset($grp['annmsg_id'])?$grp['annmsg_id']:''); 
    6684                                        $alertinfo = $grp['alertinfo']; 
    6785                                        $needsconf = $grp['needsconf']; 
    6886                                        $cwignore = $grp['cwignore']; 
    6987                                        $cfignore = $grp['cfignore']; 
    70                                         $remotealert = $grp['remotealert']; 
    71                                         $toolate = $grp['toolate']; 
     88                                        $remotealert_id = $grp['remotealert_id']; 
     89                                        $toolate_id = $grp['toolate_id']; 
    7290                                        $ringing = $grp['ringing']; 
    7391 
     
    132150                                        // group dial 
    133151                                        $ext->add($contextname, $grpnum, '', new ext_setvar('RingGroupMethod',$strategy)); 
    134                                         if ($annmsg != '') { 
     152                                        if ($annmsg_id != '') { 
     153                                                $annmsg = recordings_get_file($annmsg_id); 
    135154                                                $ext->add($contextname, $grpnum, '', new ext_gotoif('$["foo${RRNODEST}" != "foo"]','DIALGRP'));                  
    136155                                                $ext->add($contextname, $grpnum, '', new ext_answer('')); 
     
    139158                                        } 
    140159                                        if ($needsconf == "CHECKED") { 
     160                                                $remotealert = recordings_get_file($remotealert_id); 
     161                                                $toolate = recordings_get_file($toolate_id); 
    141162                                                $len=strlen($grpnum)+4; 
    142163                                                $ext->add("grps", "_RG-${grpnum}-.", '', new ext_macro('dial',$grptime. 
     
    169190} 
    170191 
    171 function ringgroups_add($grpnum,$strategy,$grptime,$grplist,$postdest,$desc,$grppre='',$annmsg='',$alertinfo,$needsconf,$remotealert,$toolate,$ringing,$cwignore,$cfignore) { 
     192function ringgroups_add($grpnum,$strategy,$grptime,$grplist,$postdest,$desc,$grppre='',$annmsg_id='',$alertinfo,$needsconf,$remotealert_id,$toolate_id,$ringing,$cwignore,$cfignore) { 
    172193 
    173194        $extens = ringgroups_list(); 
     
    182203        print_r($extens); 
    183204 
    184         $sql = "INSERT INTO ringgroups (grpnum, strategy, grptime, grppre, grplist, annmsg, postdest, description, alertinfo, needsconf, remotealert, toolate, ringing, cwignore, cfignore) VALUES ('".str_replace("'","''",$grpnum)."', '".str_replace("'", "''", $strategy)."', ".str_replace("'", "''", $grptime).", '".str_replace("'", "''", $grppre)."', '".str_replace("'", "''", $grplist)."', '".str_replace("'", "''", $annmsg)."', '".str_replace("'", "''", $postdest)."', '".str_replace("'", "''", $desc)."', '".str_replace("'", "''", $alertinfo)."', '$needsconf', '$remotealert', '$toolate', '$ringing', '$cwignore', '$cfignore')"; 
     205        $sql = "INSERT INTO ringgroups (grpnum, strategy, grptime, grppre, grplist, annmsg_id, postdest, description, alertinfo, needsconf, remotealert_id, toolate_id, ringing, cwignore, cfignore) VALUES ('".str_replace("'","''",$grpnum)."', '".str_replace("'", "''", $strategy)."', ".str_replace("'", "''", $grptime).", '".str_replace("'", "''", $grppre)."', '".str_replace("'", "''", $grplist)."', '".str_replace("'", "''", $annmsg_id)."', '".str_replace("'", "''", $postdest)."', '".str_replace("'", "''", $desc)."', '".str_replace("'", "''", $alertinfo)."', '$needsconf', '$remotealert_id', '$toolate_id', '$ringing', '$cwignore', '$cfignore')"; 
    185206        $results = sql($sql); 
    186207        return true; 
     
    257278 
    258279function ringgroups_get($grpnum) { 
    259         $results = sql("SELECT grpnum, strategy, grptime, grppre, grplist, annmsg, postdest, description, alertinfo, needsconf, remotealert, toolate, ringing, cwignore, cfignore FROM ringgroups WHERE grpnum = '".str_replace("'", "''", $grpnum)."'","getRow",DB_FETCHMODE_ASSOC); 
     280        $results = sql("SELECT grpnum, strategy, grptime, grppre, grplist, annmsg_id, postdest, description, alertinfo, needsconf, remotealert_id, toolate_id, ringing, cwignore, cfignore FROM ringgroups WHERE grpnum = '".str_replace("'", "''", $grpnum)."'","getRow",DB_FETCHMODE_ASSOC); 
    260281        return $results; 
    261282} 
  • modules/branches/2.5/ringgroups/install.php

    r6061 r6153  
    11<?php 
    22 
     3if (! function_exists("out")) { 
     4        function out($text) { 
     5                echo $text."<br />"; 
     6        } 
     7} 
     8 
     9if (! function_exists("outn")) { 
     10        function outn($text) { 
     11                echo $text; 
     12        } 
     13} 
     14 
    315global $db; 
     16global $amp_conf; 
     17 
     18$sql = " 
     19CREATE TABLE IF NOT EXISTS `ringgroups`  
     20(  
     21        `grpnum` VARCHAR( 20 ) NOT NULL ,  
     22        `strategy` VARCHAR( 50 ) NOT NULL ,  
     23        `grptime` SMALLINT NOT NULL ,  
     24        `grppre` VARCHAR( 100 ) NULL ,  
     25        `grplist` VARCHAR( 255 ) NOT NULL ,  
     26        `annmsg_id` INTEGER, 
     27        `postdest` VARCHAR( 255 ) NULL ,  
     28        `description` VARCHAR( 35 ) NOT NULL ,  
     29        `alertinfo` VARCHAR ( 255 ) NULL ,  
     30        `remotealert_id` INTEGER, 
     31        `needsconf` VARCHAR ( 10 ),  
     32        `toolate_id` INTEGER, 
     33        `cwignore` VARCHAR ( 10 ),  
     34        `cfignore` VARCHAR ( 10 ),  
     35        PRIMARY KEY  (`grpnum`)  
     36)  
     37"; 
     38$check = $db->query($sql); 
     39if(DB::IsError($check)) { 
     40        die_freepbx("Can not create annoucment table"); 
     41} 
    442 
    543// Version 1.1 upgrade 
     
    4280$db->query("ALTER TABLE ringgroups CHANGE alertinfo alertinfo VARCHAR( 255 ) NULL"); 
    4381 
    44 // Version 2.0 upgrade. Yeah. 2.0 baby!  
    45 $sql = "SELECT remotealert FROM ringgroups"; 
     82// If there is no needsconf then this is a really old upgrade. We create the 2 old fields 
     83// here  and then the migration code below will change them as needed but will work properly 
     84// since it now has the fields it is expecting 
     85// 
     86$sql = "SELECT needsconf FROM ringgroups"; 
    4687$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); 
    4788if(DB::IsError($check)) { 
     
    115156} 
    116157 
     158// Version 2.5 migrate to recording ids 
     159// 
     160outn(_("Checking if recordings need migration..")); 
     161$sql = "SELECT annmsg_id FROM ringgroups"; 
     162$check = $db->getRow($sql, DB_FETCHMODE_ASSOC); 
     163if(DB::IsError($check)) { 
     164        //  Add recording_id field 
     165        // 
     166        out("migrating"); 
     167        outn(_("adding annmsg_id field..")); 
     168  $sql = "ALTER TABLE ringgroups ADD annmsg_id INTEGER"; 
     169  $result = $db->query($sql); 
     170  if(DB::IsError($result)) { 
     171                out(_("fatal error")); 
     172                die_freepbx($result->getDebugInfo());  
     173        } else { 
     174                out(_("ok")); 
     175        } 
     176        outn(_("adding remotealert_id field..")); 
     177  $sql = "ALTER TABLE ringgroups ADD remotealert_id INTEGER"; 
     178  $result = $db->query($sql); 
     179  if(DB::IsError($result)) { 
     180                out(_("fatal error")); 
     181                die_freepbx($result->getDebugInfo());  
     182        } else { 
     183                out(_("ok")); 
     184        } 
     185        outn(_("adding toolate_id field..")); 
     186  $sql = "ALTER TABLE ringgroups ADD toolate_id INTEGER"; 
     187  $result = $db->query($sql); 
     188  if(DB::IsError($result)) { 
     189                out(_("fatal error")); 
     190                die_freepbx($result->getDebugInfo());  
     191        } else { 
     192                out(_("ok")); 
     193        } 
     194 
     195        // Get all the valudes and replace them with recording_id 
     196        // 
     197        outn(_("migrate annmsg to ids..")); 
     198  $sql = "SELECT `grpnum`, `annmsg` FROM `ringgroups`"; 
     199        $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); 
     200        if(DB::IsError($results)) { 
     201                out(_("fatal error")); 
     202                die_freepbx($results->getDebugInfo());   
     203        } 
     204        $migrate_arr = array(); 
     205        $count = 0; 
     206        foreach ($results as $row) { 
     207                if (trim($row['annmsg']) != '') { 
     208                        $rec_id = recordings_get_or_create_id($row['annmsg'], 'ringgroups'); 
     209                        $migrate_arr[] = array($rec_id, $row['grpnum']); 
     210                        $count++; 
     211                } 
     212        } 
     213        if ($count) { 
     214                $compiled = $db->prepare('UPDATE `ringgroups` SET `annmsg_id` = ? WHERE `grpnum` = ?'); 
     215                $result = $db->executeMultiple($compiled,$migrate_arr); 
     216                if(DB::IsError($result)) { 
     217                        out(_("fatal error")); 
     218                        die_freepbx($result->getDebugInfo());    
     219                } 
     220        } 
     221        out(sprintf(_("migrated %s entries"),$count)); 
     222 
     223        outn(_("migrate remotealert to  ids..")); 
     224  $sql = "SELECT `grpnum`, `remotealert` FROM `ringgroups`"; 
     225        $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); 
     226        if(DB::IsError($results)) { 
     227                out(_("fatal error")); 
     228                die_freepbx($results->getDebugInfo());   
     229        } 
     230        $migrate_arr = array(); 
     231        $count = 0; 
     232        foreach ($results as $row) { 
     233                if (trim($row['remotealert']) != '') { 
     234                        $rec_id = recordings_get_or_create_id($row['remotealert'], 'ringgroups'); 
     235                        $migrate_arr[] = array($rec_id, $row['grpnum']); 
     236                        $count++; 
     237                } 
     238        } 
     239        if ($count) { 
     240                $compiled = $db->prepare('UPDATE `ringgroups` SET `remotealert_id` = ? WHERE `grpnum` = ?'); 
     241                $result = $db->executeMultiple($compiled,$migrate_arr); 
     242                if(DB::IsError($result)) { 
     243                        out(_("fatal error")); 
     244                        die_freepbx($result->getDebugInfo());    
     245                } 
     246        } 
     247        out(sprintf(_("migrated %s entries"),$count)); 
     248 
     249        outn(_("migrate toolate to  ids..")); 
     250  $sql = "SELECT `grpnum`, `toolate` FROM `ringgroups`"; 
     251        $results = $db->getAll($sql, DB_FETCHMODE_ASSOC); 
     252        if(DB::IsError($results)) { 
     253                out(_("fatal error")); 
     254                die_freepbx($results->getDebugInfo());   
     255        } 
     256        $migrate_arr = array(); 
     257        $count = 0; 
     258        foreach ($results as $row) { 
     259                if (trim($row['toolate']) != '') { 
     260                        $rec_id = recordings_get_or_create_id($row['toolate'], 'ringgroups'); 
     261                        $migrate_arr[] = array($rec_id, $row['grpnum']); 
     262                        $count++; 
     263                } 
     264        } 
     265        if ($count) { 
     266                $compiled = $db->prepare('UPDATE `ringgroups` SET `toolate_id` = ? WHERE `grpnum` = ?'); 
     267                $result = $db->executeMultiple($compiled,$migrate_arr); 
     268                if(DB::IsError($result)) { 
     269                        out(_("fatal error")); 
     270                        die_freepbx($result->getDebugInfo());    
     271                } 
     272        } 
     273        out(sprintf(_("migrated %s entries"),$count)); 
     274 
     275        // Now remove the old recording field replaced by new id field 
     276        // 
     277        outn(_("dropping annmsg field..")); 
     278  $sql = "ALTER TABLE `ringgroups` DROP `annmsg`"; 
     279  $result = $db->query($sql); 
     280  if(DB::IsError($result)) {  
     281                out(_("no annmsg field???")); 
     282        } else { 
     283                out(_("ok")); 
     284        } 
     285        outn(_("dropping remotealert field..")); 
     286  $sql = "ALTER TABLE `ringgroups` DROP `remotealert`"; 
     287  $result = $db->query($sql); 
     288  if(DB::IsError($result)) {  
     289                out(_("no remotealert field???")); 
     290        } else { 
     291                out(_("ok")); 
     292        } 
     293        outn(_("dropping toolate field..")); 
     294  $sql = "ALTER TABLE `ringgroups` DROP `toolate`"; 
     295  $result = $db->query($sql); 
     296  if(DB::IsError($result)) {  
     297                out(_("no toolate field???")); 
     298        } else { 
     299                out(_("ok")); 
     300        } 
     301 
     302} else { 
     303        out("already migrated"); 
     304} 
     305 
     306 
    117307?> 
  • modules/branches/2.5/ringgroups/module.xml

    r6099 r6153  
    22        <rawname>ringgroups</rawname> 
    33        <name>Ring Groups</name> 
    4         <version>2.5.0.1</version> 
     4        <version>2.5.1</version> 
    55        <type>setup</type> 
    66        <category>Inbound Call Control</category> 
     
    99        </description> 
    1010        <changelog> 
     11                *2.5.1* #2069 Migrate recordings to recording ids 
    1112                *2.5.0.1* changed depends to 2.5 
    1213                *2.5.0* #1795, #2845, #2391, #2853, #2925 add tabindexing, Skip Busy Agent and Ignore Call Forward options 
     
    4142        <depends> 
    4243                <version>2.5.0alpha1</version> 
     44                <module>recordings ge 3.3.8</module> 
    4345        </depends> 
    4446        <menuitems> 
  • modules/branches/2.5/ringgroups/page.ringgroups.php

    r6061 r6153  
    2121isset($_REQUEST['grppre'])?$grppre = $_REQUEST['grppre']:$grppre=''; 
    2222isset($_REQUEST['strategy'])?$strategy = $_REQUEST['strategy']:$strategy=''; 
    23 isset($_REQUEST['annmsg'])?$annmsg = $_REQUEST['annmsg']:$annmsg=''; 
     23isset($_REQUEST['annmsg_id'])?$annmsg_id = $_REQUEST['annmsg_id']:$annmsg_id=''; 
    2424isset($_REQUEST['description'])?$description = $_REQUEST['description']:$description=''; 
    2525isset($_REQUEST['alertinfo'])?$alertinfo = $_REQUEST['alertinfo']:$alertinfo=''; 
     
    2727isset($_REQUEST['cwignore'])?$cwignore = $_REQUEST['cwignore']:$cwignore=''; 
    2828isset($_REQUEST['cfignore'])?$cfignore = $_REQUEST['cfignore']:$cfignore=''; 
    29 isset($_REQUEST['remotealert'])?$remotealert = $_REQUEST['remotealert']:$remotealert=''; 
    30 isset($_REQUEST['toolate'])?$toolate = $_REQUEST['toolate']:$toolate=''; 
     29isset($_REQUEST['remotealert_id'])?$remotealert_id = $_REQUEST['remotealert_id']:$remotealert_id=''; 
     30isset($_REQUEST['toolate_id'])?$toolate_id = $_REQUEST['toolate_id']:$toolate_id=''; 
    3131isset($_REQUEST['ringing'])?$ringing = $_REQUEST['ringing']:$ringing=''; 
    3232 
     
    7777                                $conflict_url = framework_display_extension_usage_alert($usage_arr); 
    7878 
    79                         } elseif (ringgroups_add($account,$strategy,$grptime,implode("-",$grplist),$goto,$description,$grppre,$annmsg,$alertinfo,$needsconf,$remotealert,$toolate,$ringing,$cwignore,$cfignore)) { 
     79                        } elseif (ringgroups_add($account,$strategy,$grptime,implode("-",$grplist),$goto,$description,$grppre,$annmsg_id,$alertinfo,$needsconf,$remotealert_id,$toolate_id,$ringing,$cwignore,$cfignore)) { 
    8080                                needreload(); 
    8181                                redirect_standard(); 
     
    9393                if ($action == 'edtGRP') { 
    9494                        ringgroups_del($account);        
    95                         ringgroups_add($account,$strategy,$grptime,implode("-",$grplist),$goto,$description,$grppre,$annmsg,$alertinfo,$needsconf,$remotealert,$toolate,$ringing,$cwignore,$cfignore); 
     95                        ringgroups_add($account,$strategy,$grptime,implode("-",$grplist),$goto,$description,$grppre,$annmsg_id,$alertinfo,$needsconf,$remotealert_id,$toolate_id,$ringing,$cwignore,$cfignore); 
    9696                        needreload(); 
    9797                        redirect_standard('extdisplay'); 
     
    130130                $grptime = $thisgrp['grptime']; 
    131131                $goto = $thisgrp['postdest']; 
    132                 $annmsg = $thisgrp['annmsg']; 
     132                $annmsg_id = $thisgrp['annmsg_id']; 
    133133                $description = $thisgrp['description']; 
    134134                $alertinfo = $thisgrp['alertinfo']; 
    135                 $remotealert = $thisgrp['remotealert']; 
     135                $remotealert_id = $thisgrp['remotealert_id']; 
    136136                $needsconf = $thisgrp['needsconf']; 
    137137                $cwignore = $thisgrp['cwignore']; 
    138138                $cfignore = $thisgrp['cfignore']; 
    139                 $toolate = $thisgrp['toolate']; 
     139                $toolate_id = $thisgrp['toolate_id']; 
    140140                $ringing = $thisgrp['ringing']; 
    141141                unset($grpliststr); 
     
    166166                $grptime = ''; 
    167167                $goto = ''; 
    168                 $annmsg = ''; 
     168                $annmsg_id = ''; 
    169169                $alertinfo = ''; 
    170                 $remotealert = ''; 
     170                $remotealert_id = ''; 
    171171                $needsconf = ''; 
    172172                $cwignore = ''; 
    173173                $cfignore = ''; 
    174                 $toolate = ''; 
     174                $toolate_id = ''; 
    175175                $ringing = ''; 
    176176 
     
    276276                                <td><a href="#" class="info"><?php echo _("Announcement:")?><span><?php echo _("Message to be played to the caller before dialing this group.<br><br>To add additional recordings please use the \"System Recordings\" MENU to the left")?></span></a></td> 
    277277                                <td> 
    278                                         <select name="annmsg" tabindex="<?php echo ++$tabindex;?>"> 
     278                                        <select name="annmsg_id" tabindex="<?php echo ++$tabindex;?>"> 
    279279                                        <?php 
    280280                                                $tresults = recordings_list(); 
    281                                                 $default = (isset($annmsg) ? $annmsg : ''); 
     281                                                $default = (isset($annmsg_id) ? $annmsg_id : ''); 
    282282                                                echo '<option value="">'._("None")."</option>"; 
    283283                                                if (isset($tresults[0])) { 
    284284                                                        foreach ($tresults as $tresult) { 
    285                                                                 echo '<option value="'.$tresult[2].'"'.($tresult[2] == $default ? ' SELECTED' : '').'>'.$tresult[1]."</option>\n"; 
     285                                                                echo '<option value="'.$tresult['id'].'"'.($tresult['id'] == $annmsg_id ? ' SELECTED' : '').'>'.$tresult['displayname']."</option>\n"; 
    286286                                                        } 
    287287                                                } 
     
    295295                                <td> 
    296296                                        <?php 
    297                                                 $default = (isset($annmsg) ? $annmsg : ''); 
     297                                                $default = (isset($annmsg_id) ? $annmsg_id : ''); 
    298298                                        ?> 
    299                                         <input type="hidden" name="annmsg" value="<?php echo $default; ?>"><?php echo ($default != '' ? $default : 'None'); ?> 
     299                                        <input type="hidden" name="annmsg_id" value="<?php echo $default; ?>"><?php echo ($default != '' ? $default : 'None'); ?> 
    300300                                </td> 
    301301                        </tr> 
     
    355355                                <td><a href="#" class="info"><?php echo _("Remote Announce:")?><span><?php echo _("Message to be played to the person RECEIVING the call, if 'Confirm Calls' is enabled.<br><br>To add additional recordings use the \"System Recordings\" MENU to the left")?></span></a></td> 
    356356                                <td> 
    357                                         <select name="remotealert" tabindex="<?php echo ++$tabindex;?>"> 
     357                                        <select name="remotealert_id" tabindex="<?php echo ++$tabindex;?>"> 
    358358                                        <?php 
    359359                                                $tresults = recordings_list(); 
    360                                                 $default = (isset($remotealert) ? $remotealert : ''); 
     360                                                $default = (isset($remotealert_id) ? $remotealert_id : ''); 
    361361                                                echo '<option value="">'._("Default")."</option>"; 
    362362                                                if (isset($tresults[0])) { 
    363363                                                        foreach ($tresults as $tresult) { 
    364                                                                 echo '<option value="'.$tresult[2].'"'.($tresult[2] == $default ? ' SELECTED' : '').'>'.$tresult[1]."</option>\n"; 
     364                                                                echo '<option value="'.$tresult['id'].'"'.($tresult['id'] == $remotealert_id ? ' SELECTED' : '').'>'.$tresult['displayname']."</option>\n"; 
    365365                                                        } 
    366366                                                } 
     
    373373                                <td><a href="#" class="info"><?php echo _("Too-Late Announce:")?><span><?php echo _("Message to be played to the person RECEIVING the call, if the call has already been accepted before they push 1.<br><br>To add additional recordings use the \"System Recordings\" MENU to the left")?></span></a></td> 
    374374                                <td> 
    375                                         <select name="toolate" tabindex="<?php echo ++$tabindex;?>"> 
     375                                        <select name="toolate_id" tabindex="<?php echo ++$tabindex;?>"> 
    376376                                        <?php 
    377377                                                $tresults = recordings_list(); 
    378                                                 $default = (isset($toolate) ? $toolate : ''); 
     378                                                $default = (isset($toolate_id) ? $toolate_id : ''); 
    379379                                                echo '<option value="">'._("Default")."</option>"; 
    380380                                                if (isset($tresults[0])) { 
    381381                                                        foreach ($tresults as $tresult) { 
    382                                                                 echo '<option value="'.$tresult[2].'"'.($tresult[2] == $default ? ' SELECTED' : '').'>'.$tresult[1]."</option>\n"; 
     382                                                                echo '<option value="'.$tresult['id'].'"'.($tresult['id'] == $toolate_id ? ' SELECTED' : '').'>'.$tresult['displayname']."</option>\n"; 
    383383                                                        } 
    384384                                                } 
Donate



Support
Download
Develop
Forums
News
Documentation
Paid Support
About

Paid Ads