» /rd/vhosts/phone/lib/Action/Phone/Root.php

<?php

class Action_Phone_Root extends Action_Phone_Phone {


    public function 
_common() {
        switch (
RDSite::siteID()) {
        case 
RDSite::SITE_ID_PHONEOWNER_US:
            
$this->cssTableClass 'ownerAddresInformation';
            
$this->cssTableParentClass 'table-scroll';
            break;
        default:
            
$this->cssTableClass 'b-area-code_table_2017';
            
$this->cssTableParentClass 'table-responsive';
        }
        return 
parent::_common();
    }

/**
 *
 *     phoneowner.us - clone of phoneowner.com
 *
 *     M1Data
 *     USBusiness
 *     Shopclub
 *     Allareacodes
 *     PhoneAddress
 *     https://phoneowner.us/61728863
 *
 *     Healthgardes:
 *     https://phoneowner.us/21236105
 *
 *     Zillow
 *     https://phoneowner.us/20147876
 *
 *     Avvo
 *     Martindale
 *     https://phoneowner.us/21273530
 *
 *     BBB
 *     https://phoneowner.us/23945511
 *
 *
 */

    /**
     * default catcher for missing template code in Template class (Controller::dispatch("/page404", $_GET + $_POST, "_layout");)
     * @return string
     */
    
function page404() {
        
do404();
    }
    
    function 
_not_found($msg "") {
        
do404();
    }
    
    function 
not_found() {
        
do404();
    }
    


    function 
_missing_method() {
        
//Usless call. _common is always called before _missing_method();
        //$this->_common();

        
$m $this->method;

        if (
is_numeric($m)) {
            
Template::$TPL->search_phone_form_phone $m;
            
$l strlen($m);
            
$this->_['p'] = $m// emulate P param
            
switch ($l) {
                case 
3:
                    return 
"prefix3";
                case 
6:
                    return 
"prefix6";
                case 
7:
                case 
8:
                    return 
"prefix7";
                case 
10:
                case 
11:
                    
go("/phone/$m");
#                    return "phone";
            
}

            
do404();
        }

        
$this->gz 0;
        if (
substr($m, -3) == '_gz') {
            
$this->gz 1;
            
$this->method $m substr($m0, -3);
            if (
method_exists($this$m))
                return 
'_gz';
        }

        
// urllist(\d+).txt
        
if (starts_with($m'urllist')) {
            
$this->fm('!^urllist(\d+)_txt$!'$m);
            if (
$this->p) {
                
$this->method "urllist_txt";
                return 
$this->_serve($this->p);
            }
        }

        if (
starts_with($m'sitemap')) {
            
$this->fm('!^sitemap(\d+)_xml$!'$m);
            if (
$this->p) {
                
$this->method "sitemap_xml";
                return 
$this->_serve($this->p);
            }
        }
        
do404();
    }

    
// serve method (normal or gzipped)
    
function _serve($m='') {
        if (
$this->gz)
            return 
"_gz";
        return 
$this->method;
    }

    function 
_gz($method='') {
        
$method $this->method;
        
ob_start();
        
$this->$method($this->p);
        
$r ob_get_clean();
        
Controller::gz_serve($r);
        return 
0;
    }

    
// ads.txt file
    /**
     * Generate file ads.txt on the fly. Uses config node "ads" to get list of allowed publishers
     * @return int 0
     */
    
function ads_txt() {
        
        
$content "";

        if (
$publishers CC("ads")) {
            
$lines = [];
            foreach (
$publishers as $publisher_id => $pc) {
                
$lines[] = "$pc[domain_name]$pc[publisher_id]$pc[type]cs(", %s", @$pc["authority_id"]);
            }
            if (
$lines) {
                
$content join("\n"$lines);
            }
        }
        
//google.com, pub-0000000000000000, DIRECT, f08c47fec0942fa0
//google.com, pub-0000000000000000, RESELLER, f08c47fec0942fa0

        
if (!$content) {
            
do404();
        } else {
            
// Check that visitor is google bot
            // Proper check with reverse DNS lookup
            
if ($tmp i("anti-spider")->isGoodSpider(ip())) {
                
header("Content-type: text/plain");
                echo 
$content;
            } else {
                
do404();
            }
        }
        return 
0;
    }
    
    
    
// http://phoneowner.us/
    
function index() {
        
// setting limit to 100 makes index page display MUCH less codes than we have
        
$prefixes KRDB_Phone::summary(1100);
        
$r = []; // p1 => p3 => data
        
foreach ($prefixes as $p3 => $d) {
            if (
RDSite::siteID() === RDSite::SITE_ID_PHONEOWNER_US) {
                
$nofollow = (RDSite::siteID() !== Phone::codeToSite($p3))?' rel="nofollow"':'';
            } else {
                if (!
$nofollow = (@$d["phones"] < 500)?' rel="nofollow"':'') {
                    
$nofollow = (RDSite::siteID() !== RDSite::SITE_ID_PHONEOWNER_COM && RDSite::siteID() !== Phone::codeToSite($p3))?' rel="nofollow"':'';
                }
            }
            
$r[substr($p301)][] = a("@phone", ["phone"=>$p3"nogoogle" => $nofollow], $p3$nofollow title='$d[phones] phones'");
        }
        
$this->count_ads 2;
        
$this->phones $r;
    }

    
// phoneowner.us/123
    // +1 (123) - 3 digit prefix within US
    // Show available US 6 digits completions
    
function prefix3($p) {
        
$this->_fixWrongURL($p);
        
$prefixes KRDB_Phone::summary3($p0);
        
$r = []; // p1 => p3 => data
        
$this->count_ads floor(count($prefixes) / 170);
        if (
$this->count_ads >= 3)
            
$this->count_ads 2;
        
        
$prefix_nofollow = (RDSite::siteID() !== RDSite::SITE_ID_PHONEOWNER_COM && RDSite::siteID() !== Phone::codeToSite($p))?' rel="nofollow"':'';

        foreach (
$prefixes as $p3 => $d) {
            if (@
$d["phones"] < 10) {
                continue;
            }
            
$f sprintf("(%s) %s-%s"substr($d['min'], 13), substr($d['min'], 43), substr($d['min'], 71))."***";
            
$t sprintf("(%s) %s-%s"substr($d['max'], 13), substr($d['max'], 43), substr($d['max'], 71))."***";
            if (
$prefix_nofollow) {
                
$nofollow $prefix_nofollow;
            } else {
                if (
RDSite::siteID() !== RDSite::SITE_ID_PHONEOWNER_US) {
                    
$nofollow = (@$d["phones"] < 50)?' rel="nofollow"':'';
                } else {
                    
$nofollow '';
                }
            }
            
$r[substr($p301)][] = a("@phone", ["phone" => $p.$p3"nogoogle" => $nofollow], "($p$p3-...."$nofollow title='". (($d["phones"]==1)?"1 phone":"$d[phones] phones") . " from $f to $t'");
        }
        
$this->phone $p;
        
$this->phones $r;


        
$this->prefix_info Phone_Prefix::info3($p);
        return 
"/prefix3";
    }

    
// phoneowner.us/123456
    // +1 (123) (456) - 6 digit prefix within US
    // Show available US 7 digits completions - their locations and summary details
    
function prefix6($p) {
        
$this->_fixWrongURL($p);
        
        
$this->teaser Phone::teaser7("1".$ptruetrue);
        
$this->phone $p;
        
$this->prefix_info Phone_Prefix::info6($p);
        if(!
$this->prefix_info){
            
$this->prefix_info Phone_Prefix::info3($p);
        }
        
$this->count_ads floor(count($this->teaser) / 15);
        if (
$this->count_ads >= 3)
            
$this->count_ads 2;
        
//if (count($this->teaser) < 5)
            //CD::set("NO_RIGHT_ADSENSE", "junk page");

        
return "/prefix6";
    }

    
// phoneowner.us/1234567
    // +1 (123) 456-7 - 7 digit prefix within US
    
function prefix7($p) {
        
$this->_fixWrongURL($p);
        
        
//18 Aug 2014 Gary asked to close whole prefix7 page.
        //   Please block this page completely as these numbers belong to the hospital and not individuals
        
if ($p == '85047484') {
            if (
Debug::is_admin()) {
                echo 
'<div class="admin">FORBIDEN PREFIX</div>';
            } else {
                
do410();
            }
        }
        
        if (
$verdict i("anti-spider")->hit()) {
            
            if (
$verdict == "captcha") {
                
header('HTTP/1.1 429 Too Many Requests');
                return 
"captcha";
            }
            
            
Profiler::disable();
            
header("HTTP/1.1 403 Request Limit Reached");
            die(
"Access Denied - Request Limit Reached");
        }
        
        
        
$K KRDB::i("phone""1".substr($p07));
        
http_last_modifiedmax((int) $K->_updatedKRDB_Phone_Admin::$MIN_LAST_MODIFIED));

        
$teaser Phone::teaser8("1".$p);
        
$teaser Phone::teaserResolveGeo($teaser);

        
$this->prefix_info $prefix_info Phone_Prefix::info7($p);
        if(!
$this->prefix_info){
            
$this->prefix_info Phone_Prefix::info3($p);
        }

        if (! 
$teaser) {
            
#Log::warn("No teaser for $p, redirecting to parent");
            
go(substr($p0, -1));
        }

        
$teaser_cnt count($teaser);

        
reset($teaser);
        
$p_start substr(key($teaser), 1);
        
end($teaser);
        
$p_end   substr(key($teaser), 1);

        
$this->phone $p;

        
$this->f_phone7s Phone::us($p_start); // sprintf("(%s) %s-%s", substr($p_start, 0, 3), substr($p_start, 3, 3), substr($p_start, 6)); // start
        
$this->f_phone7e Phone::us($p_end); // sprintf("(%s) %s-%s", substr($p_end, 0, 3), substr($p_end, 3, 3), substr($p_end, 6)); // end

        
$p_length strlen($p);
        if (
$p_length == 7) {
            
$prev_p = (int)$p 1;
            
$t7 Phone::teaser7("1".$prev_ptruetrue);
            if (
count(Phone::teaser7("1".$prev_ptruetrue)) > 0) {
                if (
AH::grep($t7"phone8""1".$prev_p)) {
                    
$this->prev_p $prev_p;
                }
            }
            
$next_p = (int)$p 1;
            
$t7 Phone::teaser7("1".$next_ptruetrue);
            if (
count($t7) > 0) {
                if (
AH::grep($t7"phone8""1".$next_p)) {
                    
$this->next_p $next_p;
                }
            }
        } elseif (
$p_length == 8) {
            
$prev_p = (int)$p 1;
            if (
count(Phone::teaser8("1".$prev_p)) > 10) {
                
$this->prev_p $prev_p;
            }
            
$next_p = (int)$p 1;
            if (
count(Phone::teaser8("1".$next_p)) > 10) {
                
$this->next_p $next_p;
            }
        }

        
// ATTENTION - DO NOT CHANGE UNLESS DISCUSSED WITH PARF
        // HAVE TO BE IN SYNC WITH SITEMAP GENERATOR IN KRDB_Phone
        // ex: /phone/6173721
        

        
if ($p_length == && $teaser_cnt 30) { // Go deeper - 8 digit US prefix
            
$this->count_ads 1;
            
$r = [];
            foreach (
$teaser as $phone => $items) {
                foreach (
$items as $id => $i) {
                    if (
$loc $i["loc"]??'') {
                        if(empty(
$loc["region"]))
                            
$loc["region"] = '';
                        if(empty(
$loc["city"]))
                            
$loc["city"] = '';

                        
$l_key $loc["region"]."-".$loc["city"];
                        if (!isset(
$prefix_info["locations"][$l_key])) {
                            if(
$loc["city_state"]??0)
                                list(
$loc["city_name"], $loc["state"]) = HB::explode(", "$loc["city_state"], 2);
                            
Geo::resolveLoc($loc);
                            
$loc["phones_cnt"] = 1;
                            
$prefix_info["locations"][$l_key] = $loc;
                        } else {
                            
$prefix_info["locations"][$l_key]["phones_cnt"] = ($prefix_info["locations"][$l_key]["phones_cnt"]??0) + 1;
                        }
                    }
                }

                
$p8 substr($phone8,1);
                
$r[$p8]['cnt'] = ($r[$p8]['cnt']??0) + 1;
                
$r[$p8]['min'] = ($r[$p8]['min']??0) ? min($phone$r[$p8]['min']) : $phone;
                
$r[$p8]['max'] = max($phone$r[$p8]['min']);
            }
            
ksort($r);
            
$this->phone $p;
            
$tr = [];
    
            switch (
RDSite::siteID()) {
                case 
RDSite::SITE_ID_PHONEOWNER_COM:
                    
$nofollow "";
                    break;
                case 
RDSite::SITE_ID_PHONEOWNER_US:
                    
$nofollow "";
                    break;
            }
            
$nofollow = (RDSite::siteID() !== RDSite::SITE_ID_PHONEOWNER_COM && RDSite::siteID() !== Phone::codeToSite($p))?' rel="nofollow"':'';
            
            foreach (
$r as $p8 => $d) {
                
$tr[] = Html::tr([a("@phone", ["phone"=>$p.$p8], Phone::us($p.$p8), $nofollow), Phone::us($d['min'])." - ".Phone::us($d['max']), $d['cnt']]);
            }
            
$this->summary_rows $tr;
            
$this->teaser $teaser;
            return 
"/prefix7summary";
        }

        
Profiler::info(" - prefix7", ["total-phones" => $teaser_cnt'phones-shown' => count($teaser)]);
        
// ex: // ex: /phone/6173722

        
$tr =[];
        
$items_cnt 0;
        foreach (
$teaser as $phone => $items) {
            
            
$forbidden_phone Phone::isForbidden($phone);
            if (
$forbidden_phone && !Debug::is_admin()) {
                continue;
            }
            
            
KRDB_Phone::_pX_dedup($items);

            
$cnt count($items);
            
$items_cnt += $cnt;

            
$phone_href Phone::phoneProfileUrl($phonefalse);
            switch (
RDSite::siteID()) {
                case 
RDSite::SITE_ID_PHONEOWNER_COM:
                    
$tr[] = '<section><h2 class="b-area-code_table-header"><a name="p'.substr($phone, -2).'" href="'.$phone_href.'">'.Phone::us($phone).'</a>'.cs(' <span class="admin">FORBIDDEN</span> '$forbidden_phone).'</h2>';
                    break;
                case 
RDSite::SITE_ID_PHONEOWNER_US:
                    
$nofollow RDSite::siteID() !== Phone::codeToSite($phone)?' rel="nofollow"':'';
                    
$tr[] = '<section><h2 class="b-area-code_table-header"><a '.$nofollow.' name="p'.substr($phone, -2).'" href="'.$phone_href.'">'.Phone::us($phone).'</a>'.cs(' <span class="admin">FORBIDDEN</span> '$forbidden_phone).'</h2>';
                    break;
                default:
                    
$tr[] = '<section><h2 class="b-area-code_table-header"><a rel="nofollow" name="p'.substr($phone, -2).'" href="'.$phone_href.'">'.Phone::us($phone).'</a>'.cs(' <span class="admin">FORBIDDEN</span> '$forbidden_phone).'</h2>';
                    break;
            }
            
            
            
$tr[] = '<div class="'.$this->cssTableParentClass.'"><table class="'.$this->cssTableClass.'"><tr><th>Owner&nbsp;Name</th><th>Address</th><th>Information</th></tr>';
            
$cnt 0;
            foreach (
$items as $id => $i) {
                
//$d = $this->_p7_item($i, $phone);

                $d Phone::p7_item($i$phone"prefix_listing");

                if (
$loc = ($i['loc']??'')) {
                    
$l_key = ($loc['region']??'').'-'.($loc['city']??'');
                    if (!isset(
$prefix_info['locations'][$l_key]) && ($loc['city_state']??0)) {
                        list(
$loc['city_name'], $loc['state']) = HB::explode(', '$loc['city_state'], 2);
                        
Geo::resolveLoc($loc);
                        
$loc['phones_cnt'] = 1;
                        
$prefix_info['locations'][$l_key] = $loc;
                    } else {
                        
$prefix_info['locations'][$l_key]['phones_cnt'] = ($prefix_info['locations'][$l_key]['phones_cnt']??0) + 1;
                    }
                }
                
$tr[] = Html::tr($d);
            
                
$cnt++;
                }
            
$tr[] = '</table></div>';
            if (
$cnt 10) {
                
$tr[] = '<p class="showMoreRows"><a href="#">More...</a></p>';
            }
            
$tr[] = '</section>';
        }
        
        if (
$items_cnt 1000) {
            
$C_INDEX 4;
        } elseif (
$items_cnt 300) {
            
$C_INDEX 3;
        } elseif (
$items_cnt 100) {
            
$C_INDEX 2;
        } elseif (
$items_cnt 5) {
            
$C_INDEX 1;
        } else {
            
$C_INDEX 0;
        }
        
        
$this->C_INDEX $C_INDEX;

        
$this->count_ads floor($items_cnt 30);
        if (
$this->count_ads >= 3)
            
$this->count_ads 2;
        
//if ($items_cnt < 2)
          //  CD::set("NO_RIGHT_ADSENSE", "junk page");

        
$this->table_rows $tr;
        
$this->teaser $teaser;

        return 
"/prefix7";
    }


    
// specific phone - show full details
    // phoneowner.us/phone/1234567890 - (123) 456-7890
    // phoneowner.us/phone/11234567890 - +1 (123) 456-7890
    // Do not allow google to spider this pages (at least for now)
    
function phone($p) {
        
$p trim(strip_tags($p));
        
$p Phone::clean($p);
        if (
11 == strlen($p) && "1" == $p[0]) {
            
$p substr($p110);
        }

        if (
strlen($p) != 10) {
            
SEO_MissingData::hit("phone");
            
do404();
        }
        
        
$this->forbidden_phone Phone::isForbidden("1".$p);
        
        
//18 Aug 2014 Gary asked to close whole prefix7 page.
        //   Please block this page completely as these numbers belong to the hospital and not individuals
        
if (starts_with($p'85047484')) {
            if (
Debug::is_admin()) {
                echo 
'<div class="admin">FORBIDEN PREFIX</div>';
            } else {
                
do410();
            }
        }
        
        if (
$verdict i("anti-spider")->hit()) {
            
            if (
$verdict == "captcha") {
                
header('HTTP/1.1 429 Too Many Requests');
                return 
"captcha";
            }
            
            
Profiler::disable();
            
header("HTTP/1.1 403 Request Limit Reached");
            die(
"Access Denied - Request Limit Reached");
        }
        
        
        
$K KRDB::i("phone""1".substr($p07));
        
http_last_modifiedmax((int) $K->_updatedKRDB_Phone_Admin::$MIN_LAST_MODIFIED));
        
        if (
$this->forbidden_phone && !Debug::is_admin()) {
            
$teaser = [];
        } else {
            
$teaser Phone::teaser8("1".$p);
            
$teaser Phone::teaserResolveGeo($teaser);

            
//08 May 2016 new logic. If we do not know phone number - pass user to reverse phone lookup report
            
if (!$teaser && !$this->forbidden_phone) {
                
SEO_MissingData::hit("phone");
                
go(Phone::reversePhoneLookupReportUrl($pfalse));
            }
            
        }

        
$this->prefix_info $prefix_info Phone_Prefix::info7($p);

        if (
$all_interlinks Phone::getInterlinks("1".$p)) {
            
$interlinks = [];
            
$cnts = [];
            foreach (
$all_interlinks as $k=>$v) {
                
$knd $v["kind"];
                @
$cnts[$knd]++;
                if (
"phone" == $knd && $cnts[$knd] > 3) {
                    continue;
                }
                if (
"address" == $knd && $cnts[$knd] > 10) {
                    continue;
                }
                
$interlinks[$k] = $v;
            }
            
$this->interlinks $interlinks;
        }

        
#if (! $teaser) {
        #    \Log::warn("No teaser for $p, redirecting to parent");
        #    go("/".substr($p, 0, 8));
        #}

        
$teaser_cnt count($teaser);

        
reset($teaser);
        
$p_start substr(key($teaser), 1);
        
end($teaser);
        
$p_end   substr(key($teaser), 1);

        
$this->phone $p;

        
$this->f_phone7s Phone::us($p_start); // sprintf("(%s) %s-%s", substr($p_start, 0, 3), substr($p_start, 3, 3), substr($p_start, 6)); // start
        
$this->f_phone7e Phone::us($p_end); // sprintf("(%s) %s-%s", substr($p_end, 0, 3), substr($p_end, 3, 3), substr($p_end, 6)); // end


        
Profiler::info(" - prefix7", ["total-phones" => $teaser_cnt'phones-shown' => count($teaser)]);
        
// ex: // ex: /phone/6173722

        
$tr =[];
        
$main_name "";
        
$main_loc = [];
        
$items_cnt 0;

        if (
$teaser) {
            foreach (
$teaser as $phone => $items) {
                
KRDB_Phone::_pX_dedup($items);

                
$cnt count($items);
                
$items_cnt += $cnt;

                
$tr[] = '<section><h2 class="b-area-code_table-header">'.Phone::us($phone);

                if (!
$this->forbidden_phone) {
                    
$tr[] = '<a rel="nofollow" href="'.Phone::reversePhoneLookupReportUrl($phonefalse).'" data-phone="'.substr($phone,1).'" class="btn btn-warning">Premium Report</a>';
                } else {
                    if (
Debug::is_admin()) {
                        
$tr[] = '<span style="font-size: 20px;" class="admin"> FORBIDDEN PHONE </span>';
                    } else {
                        
do410();
                    }
                }
                
$tr[] = '</h2>';

                if (
$items) {
                    
$tr[] = '<div class="'.$this->cssTableParentClass.'"><table class="'.$this->cssTableClass.'"><tr><th>Owner&nbsp;Name</th><th>Address</th><th>Information</th></tr>';
                    
$cnt 0;
                    foreach (
$items as $id => $i) {
                        
//$d = $this->_p7_item($i, $phone);
                        
$d Phone::p7_item($i$phone"phone_profile");
                        if (!
$main_name) {
                            
$main_name NVL($i["name"]??''$i["info"]['organization']??''$i["organization"]??'');
                        }

                        if (
$loc = ($i["loc"]??0)) {
                            if (!
$main_loc) {
                                
$main_loc $loc;
                                
$main_name NVL($i["name"]??''$i["info"]['organization']??''$i["organization"]??''); // Not "repeat". Try to keep name+location consistant
                            
}
                            if ((
$loc["region"]??0) && ($loc["city"]??0)) {
                                
$l_key $loc["region"] . "-" $loc["city"];
                                if (!isset(
$prefix_info["locations"][$l_key])) {
                                    list(
$loc["city_name"], $loc["state"]) = explode(", "$loc["city_state"], 2);
                                    
Geo::resolveLoc($loc);
                                    
$loc["phones_cnt"] = 1;
                                    
$prefix_info["locations"][$l_key] = $loc;
                                } else {
                                    
$prefix_info["locations"][$l_key]["phones_cnt"] = ($prefix_info["locations"][$l_key]["phones_cnt"]??0) + 1;
                                }
                            }
                        }
                        
$tr[] = Html::tr($d);

                        
$cnt++;
                    }
                    
$tr[] = '</table></div>';
    
#            if ($cnt > 10) {
    #                $tr[] = '<p class="showMoreRows"><a href="#">More Phones...</a></p>';
    #            }
                
}
                
$tr[] = '</section>';
            }
        }

        
$this->count_ads floor($items_cnt 30);
        if (
$this->count_ads >= 3)
            
$this->count_ads 2;
        
//if ($items_cnt < 2)
            //CD::set("NO_RIGHT_ADSENSE", "junk page");

        
$this->main_name $main_name;
        
$this->main_loc $main_loc;
        
$this->table_rows $tr;
        
$this->teaser $teaser;
        
        return 
"/phone";
    }
    
    
/************************************************
     * Pages to keep user on site
     ************************************************/
    
    
function people($fl$p$a="") {
        
        
//Phone part
        //$PHONE = KRDB::i("phone", "1".substr($p, 0, 7));

        
if (Phone::isForbidden($p)) {
            return 
$this->no_phone_info($p);
        }
        
        
$this->prefix_info Phone_Prefix::info7($p);
        
$this->phone $p;
        
       
        
//Address part
        
$loc Geo::parseLoc($a);
        
$this->loc $loc;
        
        
//Name part
        
list($fname_id$lname_id) = HB::fl($fl);
        
$PFL PFL("$fname_id-$lname_id");
        
$name $PFL->name;
        
        
$records = [];
        
$this->PFL $PFL;
        
$this->name $name;
        
$this->records $records;
        
$items $PFL["vPhoneAddress"]->items();

        
$items_cnt 0;
        
        
//Preresolve city names
        
$rcs = [];
        foreach (
$items as $iid => $item) {
            if(@
$item["loc"]) {
                
$l $item["loc"];
                if (isset(
$l[0])) {
                    
$l $l[0];
                }
                if (
$l['region'] && $l['city']){
                    
$rcs[] = Geo::rc($l['region'], $l['city']);
                }
            }
        }
        
Geo::cities($rcs);
        
$region_weights = [];
        if (@
$loc["region"]) {
            
$region_weights[$loc["region"]] = 100;
        }
        if (
$this->prefix_info && $this->prefix_info["locations"]) {
            foreach (
$this->prefix_info["locations"] as $l) {
                if (!isset(
$region_weights[$l["region"]])) {
                    
$region_weights[$l["region"]] = 50;
                }
            }
        }
        
        
CD::set("region_weights"$region_weights);

        if(
is_array($items)){
            
uasort($items, function($a$b){
                
$la $a["loc"]??''; if ($l[0]??'') { $la $la[0]; }
                
$lb $b["loc"]??''; if ($l[0]??'') { $lb $lb[0]; }
                
$w CD("region_weights");
                if(empty(
$w[$la["region"]]) || empty($w[$lb["region"]]))
                    return 
0;

                if(
$w[$la["region"]] < $w[$lb["region"]]){
                    return 
1;
                }else{
                    return 
0;
                }

             });
        }
        
        
$tr1 = [];

        foreach (
$items as $iid => $item) {
            if (!
$phones = @$item["phone"]) {
                continue;
            }
            
$items_cnt++;
            
            
$nm NVL($item["name"]??''$name??'');
            if (
is_array($nm)) {
                
$nm reset($nm);
            }
            
            
$l = @$item["loc"];
            if (isset(
$l[0])) {
                
$l $l[0];
            }
            
            if (!
is_array($phones)) {
                
$phones = [$phones];
            }
            
$ph_a = [];
            foreach (
$phones as $ph) {
                
$url Phone::phoneProfileUrl($phfalse);
                
$ph_a[] = '<a href="'.$url.'" class="ph">'.Phone::us($ph).'</a>';
            }
            
            
            if (@
$l["region"] && @$l["city"] && @$l["street"]) {
                
$address_link '<span class="addr-cont">'.HB::locToPlainText($l).'<a href="'.Phone::phoneAddressUrl(reset($phones), $fl$l).'" class="addr_link arrow" rel="nofollow">&gt;</a></span>';
            } else {
                
$address_link HB::locToPlainText($l);
            }
            
            
$d = [ 
                [
'class="nm"'$nm], 
                
join("<br/>"$ph_a), 
                
$address_link,
            ];
            
$tr1[] = Html::tr($d);

        }
        
        
$tr =[];
        if (
$tr1) {
            
//$items_cnt = 0;
//            $tr[] = '<section><h2 class="b-area-code_table-header">'.$name.'</h2>';

            
$tr[] = '<section><h2 class="b-area-code_table-header">'.$name;
            
$more_link_params = [];
            list(
$more_link_params["ff"], $m$more_link_params["fl"]) = Profile_Name::get_name($name);
            if (
$item["loc"]["region"]) {
                
$more_link_params["fs"] = Geo::region_name($item["loc"]["region"], true);
                if (
$item["loc"]["city_main"]) {
                    
$more_link_params["fc"] = Geo::city_name($item["loc"]["region"], $item["loc"]["city_main"]);
                }
            }
            
$tr[] = '<a rel="nofollow" href="' url('https://' C(".radaris") . '/search/profile'$more_link_params) .'" class="btn btn-warning">More Info</a>';
            
$tr[] = '</h2>';


            
$tr[] = '<div class="'.$this->cssTableParentClass.'"><table class="'.$this->cssTableClass.'"><tr><th>Owner&nbsp;Name</th><th>Phone</th><th>Address</th></tr>';
            
$tr[] = join("\n"$tr1);
            
$tr[] = '</table></div>';
            
$tr[] = '</section>';
        }

        
$this->count_ads floor($items_cnt 30);
        if (
$this->count_ads >= 3)
            
$this->count_ads 2;
        
//if ($items_cnt < 2)
            //CD::set("NO_RIGHT_ADSENSE", "junk page");

        
$this->table_rows $tr;

        return 
"/people";
    }

    
/**
     * @param string|null $a
     * @param string|null $p
     * @param string $fl
     * @return string
     * @throws Exception
     */
    
function address(?string $a null, ?string $p nullstring $fl ""): string
    
{
        if (
is_null($a) || is_null($p)) {
            
do404();
        }
        
ini_set("memory_limit""2G");
        
//Name part
        
if ($fl) {
            list(
$fname_id$lname_id) = HB::fl($fl);
            
$name Profile_Name::name($fname_id) . " " Profile_Name::name($lname_id);
        } else {
            
$fname_id $lname_id 0;
            
$name "";
        }
        
        if (
Phone::isForbidden($p)) {
            return 
$this->no_phone_info($p);
        }
        
        
//Phone part
        //$PHONE = KRDB::i("phone", "1".substr($p, 0, 7));

        
$this->prefix_info Phone_Prefix::info7($p);
        
$this->phone $p;
        
        
//Address part
        
$loc Geo::parseLoc($aGeo::LOC_ENRICH_ALL);
        
$this->loc $loc;
        
/////////////////////////////////////////////
        
$r = [];
        if (@
$loc["rm"] && @$loc["street_id"] && @$loc["nn"]) {
            
$K KRDB::i("address", [$loc["rm"], $loc["street_id"]]);
            
$nn $loc["nn"];
            
$u = @$loc["sec-nn"];

            
$items $K->items();
            
$cnt count($items);
            
$r = [];

            if (@
$items[$nn]) {
                
$items = [$nn => @$items[$nn]];
            } else {
                
$items = [];
            }

            
$items $K->addresses($itemsfalse$u$nn$nn); // disable people compacting when showing specific NN

            
$pcnt 0;
            
$this->units $units $K->units($nn);

            foreach (
$items as $nn => $v) {
                if (
$u) { // filter by unit if passed
                    
$r = [];
                    
//Filter by unit number only now. We can not do it later because $K->addresses(---) should analyze all records to detect most popular sec_abbr
                    
foreach ($v as $rec_id => $rec) {
                        
//26 Dec 2014 we decided to show records without sec-nn
                        
if (!@$rec["sec-nn"] || ($u == (string) @$rec["sec-nn"])) {
                            
$r[$nn][$rec_id] = $rec;
                        }
                    }
                    
$pcnt count($r[$nn]);
                } else {
                    
$pcnt += count($v);
                    
$r[$nn] = $v;
                }
            }

            
hash_unset($r"PROP_RECORDS");
            
hash_unset($r"SALE_RECORDS");
            
            
ksort($rSORT_NUMERIC);
            
            

            if (
$this->addresses) {
                
$tmp KRDB_Address_Helper::street_cities_zips($this->addresses$loc["region"]);
                
$this->city_names = [$loc["street_id"] => $tmp["city_names"]];
                
$this->addr_cities = [$loc["street_id"] => $tmp["addr_cities"]];
                
$this->addr_zips = [$loc["street_id"] => $tmp["addr_zips"]];
            }

            
$this->sec_abbr $K->sec_abbr// Street NN's secondary unit abbreviations        
        
// if (@$loc["rm"] && @$loc["street_id"])
        
        
$addresses $r;
/////////////////////////////////////////////        
        
        
        
$tr =[];
        
$items_cnt 0;
        
$tr_a = [];
        
$items_cnt 0;
        if (@
$addresses[$nn]) {
            
            
$ST Geo::region_name($loc["region"], true);
            
$cname Geo::city_name($loc["region"], $loc["city"]);
            
$street NVL($loc["street2"]??''$loc["str"]??'');

            
$loc_info = ['ST' => $ST'cname' => $cname'street' => $street'nn' => $nn"rm" => $loc["rm"], "street_id" => $loc["street_id"] ];

            foreach (
$addresses[$nn] as $item) {

                if(!
is_array($item)) {
                    continue;
                }
                
$phones = ($item["phones"]??0)?$item["phones"]:[];

                if (!
is_array($phones)) {
                    
$phones = [$phones];
                }
                if (!
$phones) {
                    continue;
                }

                
$items_cnt++;

                
$nm NVL(@$item["name"], @$item["info"]["name"], $name);
                if (
is_array($nm)) {
                    
$nm reset($nm);
                }
                
$fl HB::fl($item["fname_id"]??0$item["lname_id"]??0);

                
$ph_a = [];
                foreach (
$phones as $ph) {
                    
$url Phone::phoneProfileUrl($ph["number"], false);
                    
$ph_a[] = '<a href="'.$url.'" class="ph">'.Phone::us($ph["number"]).'</a>';
                }

                
$prepared_record AddressTool::prepareAddressesRecord($item$loc_info"phone-address");

                if (
$fl) {
                    
$people_link '<a rel="nofollow" href="'.Phone::phonePeopleUrl(reset($phones)["number"], $fl$loc).'">'.$nm.'</a>';
                } else {
                    
$people_link $nm;
                }
                
$d = [ 
                    [
'class="nm"'$people_link], 
                    
join("<br/>"$ph_a), 
                    @
$prepared_record["info"],
                ];
                
$tr_a[] = Html::tr($d);

            }
        }
        
        if (
$tr_a) {
            
$tr[] = '<section><h2 class="b-area-code_table-header">'.HB::locToPlainText($loc).'</h2>';
            
$tr[] = '<div class="'.$this->cssTableParentClass.'"><table class="'.$this->cssTableClass.'"><tr><th>Owner&nbsp;Name</th><th>Phone</th><th>Information</th></tr>';
            
$tr[] = join("\n"$tr_a);
            
$tr[] = '</table></div>';
            
$tr[] = '</section>';
        }

        
$this->count_ads floor($items_cnt 30);
        if (
$this->count_ads >= 3)
            
$this->count_ads 2;
        
//if ($items_cnt < 2)
            //CD::set("NO_RIGHT_ADSENSE", "junk page");

        
$this->table_rows $tr;
        
        return 
"/address";
    }

    
// loc - location - no site name, no "/" prefix
    // lastmod - last-modified-date
    
function _urllist($page 0) { # [ [loc:, lastmod:]]
        
ini_set('memory_limit''128M');
        
        
$p NVL($page0);
        
$uk Helper_Sitemap::sitemapCacheKey($p);

        
$sitemap i('Cache-DT''sitemap_PHONE')->get($uk);
        if(!
$sitemap){
            return [];
        }
        
//$absolute = false;
        
$absolute C("host");
        
        foreach (
$sitemap as &$u) {
            
//$u = "https://".C("host")."$u\n";
            
if (is_numeric($u)) {
                
$u url("@phone", ["phone" => $u"absolute" => $absolute]);
            } else {
                
$u "https://$absolute$u";
            }
        }
        return 
$sitemap;
    }

    function 
urllist_txt($p=0) {
        foreach (
$this->_urllist($p) as $u)
            echo 
"https://".C("host")."/".$u['loc']."\n";
        return 
0;
    }

    
// Sitemap generator: /rd/rdc/Helper/Sitemap.php
    
function sitemap_index_xml() { /* sitemap, sitemap1 .. sitemap$pages */
        
$pages i('Cache-DT''sitemap_PHONE')->get(Helper_Sitemap::sitemapIndexCacheKey());
        if(!
$pages) {
            
do404();
        }
        if (!
$this->_gz)
            
header("Content-type: text/xml");
        echo 
SEO_Sitemap::sitemap_index(count($pages), falsetrueC("host"));
        return 
0;
    }

    function 
sitemap_xml($p 0) {
        if (!
$this->_gz)
            
header("Content-type: text/xml");
        
$urls $this->_urllist($p);
        echo 
SEO_Sitemap::sitemap($urls);
        return 
0;
    }


    function 
auth_go() {
        return 
'a:/login/auth_go';
    }


    function 
_fixWrongURL($phone) {
        if (
RDSite::siteID() <> RDSite::SITE_ID_PHONEOWNER_COM) {
            if (
RDSite::siteID() != Phone::codeToSite($phone)) {
                
$url url("@phone", ["phone"=>$phone]);
                if (
$url != $_SERVER["REQUEST_URI"]) {
                    
go($url301);
                }
                
            }
        }
    }
    
    function 
no_phone_info($phone) {
        
$phone strip_tags($phone);
        
$this->forbidden_phone Phone::isForbidden($phone);
        
$this->phone $phone;
        
$this->formatted_phone Phone::us($phone);
        return 
"/report/no_phone_info";
    }
    
    
}