','<','>','&','\\','"',"'",';');
$this->self['NEW_CHARS'] = array('(_BL_)','(_BR_)','(_HR_)','(_LT_)','(_GT_)','(_AM_)','(_BS_)','(_DQ_)','(_SQ_)','(_SC_)');
$this->self['BAD_CHARS_64'] = array('',' ','','<','>','&','\\','"',"'",';','/','+');
$this->self['NEW_CHARS_64'] = array('(_BL_)','(_BR_)','(_HR_)','(_LT_)','(_GT_)','(_AM_)','(_BS_)','(_DQ_)','(_SQ_)','(_SC_)','(_FS_)','(_PL_)');
$this->self['TURNOFFS'] = array();
}
// Bridge for communication between JS and this PHP class. Only runs methods named/designated specifically for receiving these communications.
function ajax_communication(){
$command = $this->get_value($_POST,'command');
if(substr($command,0,5)=='ajax_'){
if(method_exists($this,$command)){
$this->runit($command,$_POST);
}
}
}
// Get the page URL across a variety of server types.
function current_page_url($comm='') {
$pageURL = 'http';
if( isset($_SERVER["HTTPS"]) ) {
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
if($comm=='base'){
$exp = explode('?',$pageURL);
return $exp[0];
}
return $pageURL;
}
// Add a string to a string with a delimiter if it is not blank.
function delimitit($str,$delim=',',$val=''){
if($str!=''){$str .= $delim;}
$str .= $val;
return $str;
}
// Simplify the process of adding filters by running local methods named for them.
function filter_handler($pass,$prio=10,$accs=1){add_filter($pass,array(&$this,'wp_'.$pass),$prio,$accs);}
// Call a function/method by name by first checking if it exists within the class, then if it exists in the base file... return the function's return value.
function function_call($fct,$pass=''){
if(method_exists($this,$fct)){
if($pass!=''){
return call_user_func(array($this, $fct), $pass);
}else{
return call_user_func(array($this, $fct));
}
}else if(function_exists($fct)){
if($pass!=''){
return call_user_func($fct,$pass);
}else{
return call_user_func($fct);
}
}
return $fct;
}
// First check if Yoast WPSEO is sintalled and is handling breadcrumbs, if not then we generate them using in-line markups that can be turned off per registered setting.
function generate_breadcrumbs(){
if(is_home() or is_front_page()){return '';}
if(function_exists('yoast_breadcrumb')){
$crumbs = yoast_breadcrumb('','',false);
if($crumbs!=''){
$crumbs = preg_replace('!xmlns:v="(.*?)"!s','',$crumbs);
$crumbs = preg_replace('!typeof="(.*?)"!s','',$crumbs);
$crumbs = preg_replace('!property="(.*?)"!s','',$crumbs);
$crumbs = preg_replace('!rel="(.*?)"!s','',$crumbs);
return '
';
return $RAT;
}
// Simplified form field function, what more to say?
function generate_field($data,$wrap=true){
$RAT = '';
$type = $this->get_value($data,'type');
$name = $this->get_value($data,'name');
$fid = $this->get_value($data,'id');
$val = $this->get_value($data,'value');
$filter = $this->get_value($data,'filter');
$include = $this->get_value($data,'include');
if(get_option($fid)!=''){$val = stripslashes(get_option($fid));}
// if($filter!=''){$filter = ' onkeypress="return inputfilter_'.$filter.'(event);"';}
$filter = '';// TASK - input filter not working
$filter .= $include;
if($type=='hidden'){
$RAT .= '';
}else if($type=='button'){
$RAT .= '';
}else if($type=='text'){
$RAT .= '';
}else if($type=='number'){
$RAT .= '';
}else if($type=='textarea'){
$RAT .= ' ';
}else if($type=='select'){
$opts = $this->get_value($data,'options',array());
if(count($opts)>0){
$RAT .= '';
}
}else if($type=='checkbox'){
if($val!=''){
$checked = ' checked="checked"';
}else{
$checked = "";
}
$RAT .= '';
}else if($type=='pass'){
$RAT .= $this->get_value($data,'pass');
}
return $RAT;
}
// Get attachment id from image source and return image metadata.
function get_attachment_data_by_src($src,$stat=''){
$attachment_id = attachment_url_to_postid($src);
return wp_get_attachment_metadata($attachment_id,true);
}
// Get the registered setting for the separator, then if it is a Fontawesome icon code generate it as such.
function get_breadcrumb_separator(){
$sep = $this->htmlout($this->get_customizer_setting('seo_breadcrumbsep'));
if(substr($sep,0,3)=='fa-'){return '';}
return ''.$sep.'';
}
// Retrieve the excerpt for a post and concatenate it by word count.
function get_excerpt_by_id($post_id,$excerpt_length=20){
$the_post = get_post($post_id); //Gets post ID
$the_excerpt = $the_post->post_content; //Gets post_content to be used as a basis for the excerpt
$the_excerpt = strip_tags(strip_shortcodes($the_excerpt)); //Strips tags and images
$the_excerpt = $this->string_limit_words($the_excerpt,$excerpt_length);
return $the_excerpt;
}
// Retrieve the featured thumbnail and return either the source URL or an array with width, height and url.
function get_featured_image($post_id,$how=''){
if(has_post_thumbnail($post_id)){
$imgid = get_post_thumbnail_id($post_id);
$img = wp_get_attachment_url($imgid);
$imgdata = wp_get_attachment_metadata($imgid,true);
$iwid = $this->get_value($imgdata,'width');
$ihit = $this->get_value($imgdata,'height');
if($iwid!=''){$imgwid = $iwid;}
if($ihit!=''){$imgwid = $ihit;}
if($how=='info'){return array('url'=>$img,'width'=>$iwid,'height'=>$ihit);}
return $img;
}
return '';
}
// Return a array of icons available to the current version of fontawesome.
function get_fontawesome_icons(){
if(isset($this->self['FONT_AWESOME_ICONS'])){return $this->self['FONT_AWESOME_ICONS'];}
// icon base from version 4.7.0
$raw = '500px,address-book,address-book-o,address-card,address-card-o,adjust,adn,align-center,align-justify,align-left,align-right,amazon,ambulance,american-sign-language-interpreting,anchor,android,angellist,angle-double-down,angle-double-left,angle-double-right,angle-double-up,angle-down,angle-left,angle-right,angle-up,apple,archive,area-chart,arrow-circle-down,arrow-circle-left,arrow-circle-o-down,arrow-circle-o-left,arrow-circle-o-right,arrow-circle-o-up,arrow-circle-right,arrow-circle-up,arrow-down,arrow-left,arrow-right,arrow-up,arrows,arrows-alt,arrows-h,arrows-v,asl-interpreting,assistive-listening-systems,asterisk,at,audio-description,automobile,backward,balance-scale,ban,bandcamp,bank,bar-chart,bar-chart-o,barcode,bars,bath,bathtub,battery,battery-0,battery-1,battery-2,battery-3,battery-4,battery-empty,battery-full,battery-half,battery-quarter,battery-three-quarters,bed,beer,behance,behance-square,bell,bell-o,bell-slash,bell-slash-o,bicycle,binoculars,birthday-cake,bitbucket,bitbucket-square,bitcoin,black-tie,blind,bluetooth,bluetooth-b,bold,bolt,bomb,book,bookmark,bookmark-o,braille,briefcase,btc,bug,building,building-o,bullhorn,bullseye,bus,buysellads,cab,calculator,calendar,calendar-check-o,calendar-minus-o,calendar-o,calendar-plus-o,calendar-times-o,camera,camera-retro,car,caret-down,caret-left,caret-right,caret-square-o-down,caret-square-o-left,caret-square-o-right,caret-square-o-up,caret-up,cart-arrow-down,cart-plus,cc,cc-amex,cc-diners-club,cc-discover,cc-jcb,cc-mastercard,cc-paypal,cc-stripe,cc-visa,certificate,chain,chain-broken,check,check-circle,check-circle-o,check-square,check-square-o,chevron-circle-down,chevron-circle-left,chevron-circle-right,chevron-circle-up,chevron-down,chevron-left,chevron-right,chevron-up,child,chrome,circle,circle-o,circle-o-notch,circle-thin,clipboard,clock-o,clone,close,cloud,cloud-download,cloud-upload,cny,code,code-fork,codepen,codiepie,coffee,cog,cogs,columns,comment,comment-o,commenting,commenting-o,comments,comments-o,compass,compress,connectdevelop,contao,copy,copyright,creative-commons,credit-card,credit-card-alt,crop,crosshairs,css3,cube,cubes,cut,cutlery,dashboard,dashcube,database,deaf,deafness,dedent,delicious,desktop,deviantart,diamond,digg,dollar,dot-circle-o,download,dribbble,drivers-license,drivers-license-o,dropbox,drupal,edge,edit,eercast,eject,ellipsis-h,ellipsis-v,empire,envelope,envelope-o,envelope-open,envelope-open-o,envelope-square,envira,eraser,etsy,eur,euro,exchange,exclamation,exclamation-circle,exclamation-triangle,expand,expeditedssl,external-link,external-link-square,eye,eye-slash,eyedropper,fa,facebook,facebook-f,facebook-official,facebook-square,fast-backward,fast-forward,fax,feed,female,fighter-jet,file,file-archive-o,file-audio-o,file-code-o,file-excel-o,file-image-o,file-movie-o,file-o,file-pdf-o,file-photo-o,file-picture-o,file-powerpoint-o,file-sound-o,file-text,file-text-o,file-video-o,file-word-o,file-zip-o,files-o,film,filter,fire,fire-extinguisher,firefox,first-order,flag,flag-checkered,flag-o,flash,flask,flickr,floppy-o,folder,folder-o,folder-open,folder-open-o,font,font-awesome,fonticons,fort-awesome,forumbee,forward,foursquare,free-code-camp,frown-o,futbol-o,gamepad,gavel,gbp,ge,gear,gears,genderless,get-pocket,gg,gg-circle,gift,git,git-square,github,github-alt,github-square,gitlab,gittip,glass,glide,glide-g,globe,google,google-plus,google-plus-circle,google-plus-official,google-plus-square,google-wallet,graduation-cap,gratipay,grav,group,h-square,hacker-news,hand-grab-o,hand-lizard-o,hand-o-down,hand-o-left,hand-o-right,hand-o-up,hand-paper-o,hand-peace-o,hand-pointer-o,hand-rock-o,hand-scissors-o,hand-spock-o,hand-stop-o,handshake-o,hard-of-hearing,hashtag,hdd-o,header,headphones,heart,heart-o,heartbeat,history,home,hospital-o,hotel,hourglass,hourglass-1,hourglass-2,hourglass-3,hourglass-end,hourglass-half,hourglass-o,hourglass-start,houzz,html5,i-cursor,id-badge,id-card,id-card-o,ils,image,imdb,inbox,indent,industry,info,info-circle,inr,instagram,institution,internet-explorer,intersex,ioxhost,italic,joomla,jpy,jsfiddle,key,keyboard-o,krw,language,laptop,lastfm,lastfm-square,leaf,leanpub,legal,lemon-o,level-down,level-up,life-bouy,life-buoy,life-ring,life-saver,lightbulb-o,line-chart,link,linkedin,linkedin-square,linode,linux,list,list-alt,list-ol,list-ul,location-arrow,lock,long-arrow-down,long-arrow-left,long-arrow-right,long-arrow-up,low-vision,magic,magnet,mail-forward,mail-reply,mail-reply-all,male,map,map-marker,map-o,map-pin,map-signs,mars,mars-double,mars-stroke,mars-stroke-h,mars-stroke-v,maxcdn,meanpath,medium,medkit,meetup,meh-o,mercury,microchip,microphone,microphone-slash,minus,minus-circle,minus-square,minus-square-o,mixcloud,mobile,mobile-phone,modx,money,moon-o,mortar-board,motorcycle,mouse-pointer,music,navicon,neuter,newspaper-o,object-group,object-ungroup,odnoklassniki,odnoklassniki-square,opencart,openid,opera,optin-monster,outdent,pagelines,paint-brush,paper-plane,paper-plane-o,paperclip,paragraph,paste,pause,pause-circle,pause-circle-o,paw,paypal,pencil,pencil-square,pencil-square-o,percent,phone,phone-square,photo,picture-o,pie-chart,pied-piper,pied-piper-alt,pied-piper-pp,pinterest,pinterest-p,pinterest-square,plane,play,play-circle,play-circle-o,plug,plus,plus-circle,plus-square,plus-square-o,podcast,power-off,print,product-hunt,puzzle-piece,qq,qrcode,question,question-circle,question-circle-o,quora,quote-left,quote-right,ra,random,ravelry,rebel,recycle,reddit,reddit-alien,reddit-square,refresh,registered,remove,renren,reorder,repeat,reply,reply-all,resistance,retweet,rmb,road,rocket,rotate-left,rotate-right,rouble,rss,rss-square,rub,ruble,rupee,s15,safari,save,scissors,scribd,search,search-minus,search-plus,sellsy,send,send-o,server,share,share-alt,share-alt-square,share-square,share-square-o,shekel,sheqel,shield,ship,shirtsinbulk,shopping-bag,shopping-basket,shopping-cart,shower,sign-in,sign-language,sign-out,signal,signing,simplybuilt,sitemap,skyatlas,skype,slack,sliders,slideshare,smile-o,snapchat,snapchat-ghost,snapchat-square,snowflake-o,soccer-ball-o,sort,sort-alpha-asc,sort-alpha-desc,sort-amount-asc,sort-amount-desc,sort-asc,sort-desc,sort-down,sort-numeric-asc,sort-numeric-desc,sort-up,soundcloud,space-shuttle,spinner,spoon,spotify,square,square-o,stack-exchange,stack-overflow,star,star-half,star-half-empty,star-half-full,star-half-o,star-o,steam,steam-square,step-backward,step-forward,stethoscope,sticky-note,sticky-note-o,stop,stop-circle,stop-circle-o,street-view,strikethrough,stumbleupon,stumbleupon-circle,subscript,subway,suitcase,sun-o,superpowers,superscript,support,table,tablet,tachometer,tag,tags,tasks,taxi,telegram,television,tencent-weibo,terminal,text-height,text-width,th,th-large,th-list,themeisle,thermometer,thermometer-0,thermometer-1,thermometer-2,thermometer-3,thermometer-4,thermometer-empty,thermometer-full,thermometer-half,thermometer-quarter,thermometer-three-quarters,thumb-tack,thumbs-down,thumbs-o-down,thumbs-o-up,thumbs-up,ticket,times,times-circle,times-circle-o,times-rectangle,times-rectangle-o,tint,toggle-down,toggle-left,toggle-off,toggle-on,toggle-right,toggle-up,trademark,train,transgender,transgender-alt,trash,trash-o,tree,trello,tripadvisor,trophy,truck,try,tty,tumblr,tumblr-square,turkish-lira,tv,twitch,twitter,twitter-square,umbrella,underline,undo,universal-access,university,unlink,unlock,unlock-alt,unsorted,upload,usb,usd,user,user-circle,user-circle-o,user-md,user-o,user-plus,user-secret,user-times,users,vcard,vcard-o,venus,venus-double,venus-mars,viacoin,viadeo,viadeo-square,video-camera,vimeo,vimeo-square,vine,vk,volume-control-phone,volume-down,volume-off,volume-up,warning,wechat,weibo,weixin,whatsapp,wheelchair,wheelchair-alt,wifi,wikipedia-w,window-close,window-close-o,window-maximize,window-minimize,window-restore,windows,won,wordpress,wpbeginner,wpexplorer,wpforms,wrench,xing,xing-square,y-combinator,y-combinator-square,yahoo,yc,yc-square,yelp,yen,yoast,youtube,youtube-play,youtube-square';
$icons = array();
$raws = explode(',',$raw);
foreach($raws as $icn){$icons[] = 'fa-'.$icn;}
return $icons;
}
// Return the current URL for loading the fontawesome library from the bootstrap CDN.
function get_fontawesome_url(){$ver = $this->get_fontawesome_version();return 'https://maxcdn.bootstrapcdn.com/font-awesome/'.$ver.'/css/font-awesome.min.css';}
// Return the curent version of fontawesome and initializes the data as an option that can be updated with new versions.
function get_fontawesome_version(){
if(isset($this->self['FONT_AWESOME_VERSION'])){return $this->self['FONT_AWESOME_VERSION'];}
return '4.7.0';
}
// Retrieve width, height and mime type from an image by source URL.
function get_image_info($image,$field){
if($image==''){return '';}
$imgdata = $this->get_attachment_data_by_src($image);
if($field=='width'){return $this->get_value($imgdata,'width');}
if($field=='height'){return $this->get_value($imgdata,'height');}
}
// Used to add markups to objects in the DOM after checking if they are turned off by setting.
function get_markup($mark,$how,$what=''){
if($this->inline_markup('yes')==''){return '';}
if($how=='type'){
return ' itemscope itemtype="http://schema.org/'.$mark.'"';
}else if($how=='prop'){
return ' itemprop="'.$mark.'"';
}else if($how=='rel'){
return ' rel="v:'.$mark.'"';
}
return '';
}
// Return the page title across different page/post types. This simplifies development with one centralized function call.
function get_page_title($id=NULL){
if(is_category() or is_tax()){return $this->taxes(array('com'=>'title'));}
if(is_tag()){$tag = get_tag($id);if(isset($tag->name)){return $tag->name;}else{return '';}}
return get_the_title($id);
}
// Return category data for a post in a number of ways, from full array to a particular variable/value.
function get_post_category_data($post_id=NULL,$how='',$what=''){
if($post_id==NULL){$post_id = get_the_ID();}
$cats = array();
$cat = '';
$cid = '';
$dep = 0;
$ctgy = get_the_category($post_id);
if($how=='all'){
$cats = $ctgy;
}else if($how=='base'){
$dep = 1000;
}else{
$dep = -1;
}
foreach($ctgy as $rex=>$vex){
$catid = $vex->cat_ID;
$ndep = $this->taxes(array('com'=>'depth','id'=>$catid));
if($dep!=$ndep){
if($how=='all'){
if($cat!=''){$cat .= ',';}
$cat .= $vex->cat_name;
if($cid!=''){$cid .= ',';}
$cid .= $catid;
}else{
$isdep = false;
if($how=='base'){
if($ndep<$dep){
$isdep = true;
}
}else{
if($ndep>$dep){
$isdep = true;
}
}
if($isdep==true){
$dep = $ndep;
$cat = $vex->cat_name;
$cid = $catid;
$cats = $vex;
}
}
}
}
if($what=='array'){
return $cats;
}else if($what=='id'){
return $cid;
}else{
return $cat;
}
}
// These two functions consolodate two WP steps into one.
function get_site_base_url(){return esc_url(home_url());}
function get_site_template_url(){return esc_url(get_template_directory_uri());}
// Get a value from an array or object across nested levels of depth.
function get_value($incoming,$var,$def=''){
if(is_object($incoming) and is_array($var)){$incoming = $this->object_to_array($incoming);}
if (is_object($incoming)) {
if(isset($incoming->$var)){
return $incoming->$var;
}
}else{
if(is_array($var)){
if(count($var)>0){
$tar = $incoming;
foreach($var as $far){
if(isset($tar[$far])){
$tar = $tar[$far];
}else{
return $def;
}
}
return $tar;
}
}else{
if(isset($incoming[$var])){
return $incoming[$var];
}
}
}
return $def;
}
// Simple mysql encoding of a string without using slashes. This is more reliable and works across PHP and JS.
function htmlin($nstr) {
if(is_array($nstr)){
if(count($nstr)>0){
foreach($nstr as $dex=>$data){
$nstr[$dex] = $this->htmlin($data);
}
}
}else{
for($cc=0;$ccself['BAD_CHARS']);$cc++){
$narr = explode($this->self['BAD_CHARS'][$cc],$nstr);
$nstr = implode($this->self['NEW_CHARS'][$cc],$narr);
}
}
return $nstr;
}
// Decoding of a string that was encoded with htmlin().
function htmlout($nstr) {
if(is_array($nstr)){
if(count($nstr)>0){
foreach($nstr as $dex=>$data){
$nstr[$dex] = $this->htmlout($data);
}
}
}else{
for($cc=0;$ccself['NEW_CHARS']);$cc++){
$narr = explode($this->self['NEW_CHARS'][$cc],$nstr);
$nstr = implode($this->self['BAD_CHARS'][$cc],$narr);
}
$nstr = stripslashes($nstr);
}
return $nstr;
}
// The main init() function, added as an action in the base level of the functions file.
function init(){
if(method_exists($this,'registration')){$this->registration();}
if($this->has_customizer_settings()){
add_action('customize_register',array(&$this,'init_customizer_settings'));
}
if($this->has_cron()){
add_filter( 'cron_schedules', array(&$this,'custom_cron_schedules'));
foreach($this->self['cron_list'] as $fct=>$interval){
$action = $fct.'_cron';
add_action($action, $fct);
if(!wp_next_scheduled($action)){
wp_schedule_event( time(), $interval, $action);
}
}
}
if($this->using_meta() and $this->is_editor('post')) {
add_action('edit_form_advanced',array(&$this,'add_post_editor'));
add_action('edit_page_form',array(&$this,'add_post_editor'));
add_action('edit_post',array(&$this,'update_post'),10,2);
}
$this->runit('extends_init');
}
// Verify that the current page is a specific WP-Admin page, currently used to check for post editor.
function is_editor($page){
global $pagenow;
if($pagenow==$page.'.php'){return true;}
return false;
}
// Check if linline markups are turned off, hooked by functions that utilize markups.
function inline_markup($is,$isnt=''){
$in = false;
$isinline = $this->get_customizer_setting('seo_inlinemarkup');
if($isinline!=''){$in = true;}
if($in==true){return $is;}
return $isnt;
}
// Check if the user is logged in and has Administraotor level access.
function is_user_admin(){
$user = wp_get_current_user();
if($user->exists() and current_user_can('manage_options')){return true;}
return false;
}
// Break down the URL and return the page slug found after the last / slash.
function last_page_in_url($url=NULL){
if($url==NULL){$url = $this->current_page_url();}
$drop = explode('?',$url);
$splt = explode('/',$drop[0]);
$cnt = count($splt)-1;
$last = $splt[$cnt];
if($last==''){
$last = $splt[($cnt-1)];
}
return $last;
}
// Convert a PHP object to an array.
function object_to_array($d){if(is_object($d)){$d = get_object_vars($d);}if(is_array($d)){return array_map(array($this,'object_to_array'),$d);}else{return $d;}}
// Run a function/method by name by first checking if it exists within the class, then if it exists in the base file.
function runit($fct,$pass=''){
if(method_exists($this,$fct)){
if($pass!=''){
call_user_func(array($this, $fct), $pass);
}else{
call_user_func(array($this, $fct));
}
}else if(function_exists($fct)){
if($pass!=''){
call_user_func($fct,$pass);
}else{
call_user_func($fct);
}
}
}
// Find and return a portion of a string that falls between a starting string and an ending string. Used in various places for removing HTML tags and attributes that invalidate Google AMP compliance.
function scrape_between($txt,$start,$end){
$splode = explode($start,$txt);
$part = $this->get_value($splode,1);
$parts = explode($end,$part);
return $parts[0];
}
// Check if a value exists in an array and if that value is true. No nested or object checking here, not currently in use.
function set_and_true($arr,$var){if(isset($arr[$var])){if($arr[$var]==true){return true;}}return false;}
// Concatenate a string by word count.
function string_limit_words($string, $word_limit){
$words = explode(' ', $string, ($word_limit + 1));
if(count($words) > $word_limit)
array_pop($words);
return implode(' ', $words);
}
// Return various pieces of category/taxonomy data. This centralized function makes development easier.
function taxes($params){
$id = $this->get_value($params,'id');
$com = $this->get_value($params,'com');
$cat = $this->get_value($params,'category');
if($id=='' or $id==NULL){
if($cat==''){$cat = single_term_title("", false);}
$id = get_cat_ID($cat);
}
if($com=='id'){
return $id;
}else if($com=='title'){
return get_cat_name($id);
}else if($com=='description'){
return category_description($id);
}else if($com=='depth'){
$dep = 0;
$category = get_category($id);
for($i=1;$i<=9;$i++){
if($category->category_parent){
$category = get_category($category->category_parent);
$dep = $i;
}
}
return $dep+1;
}else if($com=='data'){
$category_data = get_term_by('term_id',$id,'category');
$var = $this->get_value($params,'var');
if($var==''){return $category_data;}
if(is_object($category_data)){
return $category_data->$var;
}else{
return $this->get_value($category_data,$var);
}
}else if($com=='link'){
$catslug = $this->taxes(array('com'=>'path','id'=>$id));
return $this->get_site_base_url().'/category/'.$catslug;
}else if($com=='path'){
$data = $this->taxes(array('com'=>'data','id'=>$id));
$pslug = $this->get_value($data,'slug');
$parent = $this->get_value($data,'parent',0);
$slug = $this->get_value($params,'slug');
if($pslug!=''){
$slug = $pslug.'/'.$slug;
if($parent!=0){$slug = $this->taxes(array('com'=>'path','id'=>$parent,'slug'=>$slug));}
}
return $slug;
}else if($com=='crumbs'){
$link = $this->taxes(array('com'=>'link','id'=>$id));
$data = $this->taxes(array('com'=>'data','id'=>$id));
$slug = $this->get_value($data,'slug');
$parent = $this->get_value($data,'parent');
$name = $this->get_value($data,'name');
$count = $this->get_value($data,'count');
$strg = $this->get_value($params,'text');
$how = $this->get_value($params,'how');
$markup = $this->get_value($params,'markup',true);
if($markup==false){
$href = ''.$name.'';
$blank = ''.$name.'';
}else{
$href = ''.$name.'';
$href = ''.$name.'';
$blank = ''.$name.'';
}
if($slug!=''){
if($strg=='' and $how==''){
$strg = $blank;
}else{
$strg = $href.' '.$this->get_breadcrumb_separator().' '.$strg;
}
if($parent!=0){$strg = $this->taxes(array('com'=>'crumbs','id'=>$parent,'text'=>$strg,'how'=>$how,'markup'=>$markup));}
}
return $strg;
}
return '';
}
// Basic testing function, used to display a nested data object.
function test_array($arr=array(),$how='echo',$px=0){
if($how!='override' and $this->debugging()==false){return '';}
if(is_string($arr)){
if($how=='echo'){
echo $arr;
}
return $arr;
}
if(is_object($arr)){$arr = $this->object_to_array($arr);}
$RAT = '';
if(is_array($arr)){
if(count($arr)>0){
foreach($arr as $k=>$v){
if(is_array($v) or is_object($v)){
if($how=='echo' or $how=='override'){
if($how=='js'){
echo $k.' = ';
}else{
echo '
';
}
if($how=='echo' or $how=='override'){
echo $div;
}else{
$RAT .= $div;
}
}
}
}
}
return $RAT;
}
// Echo the page title across different page/post types. This simplifies development with one centralized function call.
function theme_page_title($post_id=NULL){
if(is_category()){single_cat_title();}
elseif(is_tag()){single_tag_title();}
elseif(is_author()){global $post;$author_id = $post->post_author;the_author_meta('display_name', $author_id);}
elseif(is_day()){the_time('l, F j, Y');}
elseif(is_month()){the_time('F Y');}
elseif(is_year()){the_time('Y');}
elseif(is_single() or is_page()){the_title();}
}
// Remove dashes from a string and return the string with each word capitalized.
function ucwords_undash($input){return ucwords(str_replace('-',' ',$input));}
// Validate a URL by checking it's headers.
function url_exists($url){
$headers=get_headers($url);
return stripos($headers[0],"200 OK")?true:false;
}
// Retrieve text/HTML from a URL. This function consolodates the two steps necessary to gather the data and return only the text. This is used to check our API for updates to the Fontawesome version/list.
function url_get_contents($url){
$response = wp_remote_get($url);
return $this->get_value($response,'body');
}
// Check if a nav menu is available, assigned, and/or empty. These checks are useful in various situations.
function use_nav_menu($location,$com=''){
$isok = false;
if(has_nav_menu($location)){
if($com=='assigned'){return true;}
if(wp_nav_menu(array('theme_location'=>$location,'echo'=>false))!==false){
$isok = true;
}else{
if($com=='empty'){return true;}
}
}
return $isok;
}
// Check if a string fits the valid URL structure.
function validate_url($string){
if(filter_var($string, FILTER_VALIDATE_URL)){return true;}
return false;
}
//***************************************
// CUSTOMIZER REGISTRATION AND HANDLING
//***************************************
// These functions simplify the registration of WP Customizer settings and make the data readily available to our framework.
// Create a section in the customizer, each setting will be assigned to it's section in the order they are registered.
function register_customizer_section($sect,$params=array()){$this->self['customizer_sections'][$sect] = $params;}
// Add a setting to the Customizer and store the data for use by the framework. Centralizing and storing the data in the class speeds up processing time.
function register_customizer_setting($setting,$params=array()){$this->self['customizer_settings'][$setting] = $params;}
// Check if any settings have been registered, used to check if handling is necessary.
function has_customizer_settings(){if(isset($this->self['customizer_settings'])){if(count($this->self['customizer_settings'])>0){return true;}}return false;}
// Pull the Customizer setting, then if blank run through default values provided by the funtion call then by registration. Registering default values makes development easier.
function get_customizer_setting($setting,$default=NULL){
$mod = get_theme_mod($setting);
if($mod==''){
if($default!=NULL){
$mod = $default;
}else{
if(isset($this->self['customizer_settings'][$setting])){
$mod = $this->get_value($this->self['customizer_settings'][$setting],'default');
}
}
}
$mod = $this->htmlout($mod);
return $mod;
}
// Return an array with registration data for a particular setting.
function get_customizer_settings($mod){return $this->get_value($this->self['customizer_settings'],$mod,array());}
// Handle the WP Customizer setup of sections and settings using the registered data. This is added as a WordPress action by the theme's init() function.
function init_customizer_settings($wp_customize){
// section priority can be set, but is built in registration order if not set
$secprio = 1;
foreach($this->self['customizer_sections'] as $section=>$data){
$title = $this->get_value($data,'title');
$prio = $this->get_value($data,'priority');
if($prio==''){$prio = $secprio;$secprio += 1;}
$wp_customize->add_section($section,array('title'=>$title,'priority'=>$prio));
}
// these default sections are not needed, the colors adn images are organized into the registered sections
$wp_customize->remove_section('colors');
$wp_customize->remove_section('header_image');
$wp_customize->remove_section('background_image');
// reorganize settings by section, it ignores setting that did not register a section
$bysect = array();
foreach($this->self['customizer_settings'] as $setting=>$data){
$sect = $this->get_value($data,'section');
if($sect!=''){
if(!isset($bysect[$sect])){$bysect[$sect] = array();}
$bysect[$sect][$setting] = $data;
}
}
// create settings while setting priority to display in order that settings were registered
if(count($bysect)>0){
foreach($bysect as $sect=>$sets){
$dex = 1;
foreach($sets as $setting=>$data){
$data['priority'] = $dex;
$dex += 1;
$this->create_customizer_setting($setting,$data);
}
}
}
}
// Add settings and controls to the Customizer from registered data.
function create_customizer_setting($id,$params){
global $wp_customize;
$type = $this->get_value($params,'type');
$sec = $this->get_value($params,'section');
$title = $this->get_value($params,'title');
$def = $this->get_value($params,'default');
$prio = $this->get_value($params,'priority');
$choices = $this->get_value($params,'choices');
$desc = $this->get_value($params,'description');
$live = $this->get_value($params,'live',false);
$theme = $this->self['prefix'];
if($id!='' and $type!='' and $sec!=''){
$transport = 'refresh';
if($live==true){$transport = 'postMessage';}
if($type=='color'){
$wp_customize->add_setting($id,array('default' => $def , 'transport' => $transport , 'sanitize_callback' => 'sanitize_hex_color'));
}else{
$wp_customize->add_setting($id,array('default' => $def , 'transport' => $transport , 'sanitize_callback' => 'sanitize_text_field'));
}
$pass = array('label'=>$title,$theme,'section'=>$sec,'settings'=>$id);
if($prio!=''){$pass['priority'] = $prio;}
if($choices!=''){$pass['choices'] = $choices;}
if($desc!=''){$pass['description'] = $desc;}
if($type=='color'){
$wp_customize->add_control(new WP_Customize_Color_Control($wp_customize,$id,$pass));
}else if($type=='image'){
$wp_customize->add_control(new WP_Customize_Image_Control($wp_customize,$id,$pass));
}else{
$pass['type'] = $type;
$wp_customize->add_control($id,$pass);
}
}
}
// AMP REQUIRED - We have to add all CSS into the header in an AMP specific style tag that is limited to 50KB and must not use certain characters. All registered settings that ustilize CSS are inserted into the AMP style tag using this function. This is called from amp_publisher('start').
function init_customizer_head($raw=''){
if($this->has_customizer_settings()){
$css = '';
$js = '';
foreach($this->self['customizer_settings'] as $setting=>$data){
$acss = $this->get_value($data,'css');
if($acss!=''){
if(strstr($acss,'[[VALUE]]')){
$val = $this->get_customizer_setting($setting);
$css .= str_replace('[[VALUE]]',$val,$acss);
}else{
$css .= $this->function_call($acss);
}
}
$ajs = $this->get_value($data,'js');
if($ajs!=''){
if(strstr($ajs,'[[VALUE]]')){
$val = $this->get_customizer_setting($setting);
$js .= str_replace('[[VALUE]]',$val,$ajs);
}else{
$js .= $this->function_call($ajs);
}
}
}
if($raw=='css'){
echo $css;
}else if($raw=='js'){
echo $js;
}else{
if($css!=''){echo '';}
if($js!=''){echo '';}
}
}
}
//*************************
// COLOR CODE PROCESSING
//*************************
// Check if a string is a hex color code.
function isHex($input){
if(substr($input,0,1)=='#'){return true;}
return false;
}
// Check if a string is a rgb color code.
function isRGB($input){
if(substr($input,0,3)=='rgb'){return true;}
return false;
}
// Convert hex to rgb color code.
function hexToRGB($hex) {
$hex = str_replace("#", "", $hex);
if(strlen($hex) == 3) {
$r = hexdec($hex[0].$hex[0]);
$g = hexdec($hex[1].$hex[1]);
$b = hexdec($hex[2].$hex[2]);
} else {
$r = hexdec($hex[0].$hex[1]);
$g = hexdec($hex[2].$hex[3]);
$b = hexdec($hex[4].$hex[5]);
}
return array('r'=>$r, 'g'=>$g, 'b'=>$b);
}
// Convert rgb to hex color code.
function rgbToHex($rgb){
$rgb = $this->rgbToArray($rgb);
return '#' . sprintf('%02x', $rgb['r']) . sprintf('%02x', $rgb['g']) . sprintf('%02x', $rgb['b']);
}
// Retrieve rbg values as an array.
function rgbToArray($rgb){
if(is_string($rgb)){
$str = str_replace(array('rgb(',')',' '),array('','',''),$rgb);
$exp = explode(',',$str);
$rgb = array('r'=>$exp[0],'g'=>$exp[1],'b'=>$exp[2]);
}
return $rgb;
}
//************************************
// CRONJOB REGISTRATION AND HANDLING
//************************************
// These functions simplify the process of setting up a conjob and utilizing a selection of alternate interval periods.
// Register a cronjob and choose an interval: minute, hour, halfday, day, week, month, 3hours, 6hours, 5minutes
function register_cron($fct,$interval){
$intervals = array('minute'=>'minutely','hour'=>'hourly','halfday'=>'twicedaily','day'=>'daily','week'=>'weekly','month'=>'monthly','3hours'=>'3hours','6hours'=>'6hours','5minutes'=>'5minutes');
$itype = '';
if(isset($intervals[$interval])){
$itype = $intervals[$interval];
}else{
foreach($intervals as $k=>$v){
if($interval==$v){
$itype = $v;
}
}
}
if($itype!=''){
$this->self['cron_list'][$fct] = $itype;
}
}
// Check if the class has any cronjobs registered. Used before initiating WP setup script.
function has_cron(){if(isset($this->self['cron_list'])){if(count($this->self['cron_list'])>0){return true;}}return false;}
// Adds several interval options that only get filtered into WP if they are registered.
function custom_cron_schedules( $schedules ) {
$arr = array();
if($this->has_cron()){
foreach($this->self['cron_list'] as $fct=>$type){
$arr[$type] = true;
}
}
if(isset($arr['minutely'])){$schedules['minutely'] = array('interval' => 60,'display' => 'Every Minute');}
if(isset($arr['weekly'])){$schedules['weekly'] = array('interval' => 60480,'display' => 'Every Week');}
if(isset($arr['monthly'])){$schedules['monthly'] = array('interval' => 259200,'display' => 'Every 30 Days');}
if(isset($arr['3hours'])){$schedules['3hours'] = array('interval' => 1080,'display' => 'Every 3 Hours');}
if(isset($arr['6hours'])){$schedules['6hours'] = array('interval' => 2160,'display' => 'Every 6 Hours');}
if(isset($arr['5minutes'])){$schedules['5minutes'] = array('interval' => 300,'display' => 'Every 5 Minutes');}
return $schedules;
}
// Retrieve next scheduled date/data for a registered cronjob.
function get_cron($fct){return wp_next_scheduled($fct.'_cron');}
// Clear the next scheduled date/data for a registered cronjob. This is useful when testing cronjobs.
function clear_cron($fct){wp_clear_scheduled_hook($fct.'_cron');}
// Remove a cronjob from the WP registry. This is useful when testing cronjobs.
function cancel_cron($fct){
$action = $fct.'_cron';
$next = wp_next_scheduled($action);
wp_unschedule_event( $next, $action);
}
// *************************************
// POST META REGISTRATION AND HANDLING
// *************************************
// These functions consolodate the extensive number of steps required to include a meta field and the ability to edit it through the post editor. Now I can just register a meta value in the functions file, and the rest is done.
// Register a meta value by sending this function a variable name and an array of parameters, including acceptable post types.
// EXAMPLE: $OBJ->register_meta('VARNAME',array('type'=>'checkbox','name'=>'VAR TITLE','desc'=>'DESCRIPTION - NOT REQUIRED','post_type'=>array('post','page')));
function register_meta($name,$data=array()){
$field = $this->get_fieldname($name,true);
$this->self['meta_list'][$field] = $data;
$this->self['meta_list'][$field]['id'] = $this->get_fieldname($name);
}
// Take registered meta fields and add a Meta Box to the WP post editor for this object and it's fields.
function add_post_editor(){
$how = '';
$screen = get_current_screen();
$type = $screen->post_type;
if($type=='post' or $type=='page'){$how = $type;}
$mtitle = $this->get_value($this->self,'Title');
if($how!=''){add_meta_box($this->self['prefix'].'_layout_box',$mtitle,array(&$this,'echo_post_editor'),$how,'advanced','core');}
}
// Second step in adding a Meta Box to the WP post editor, this step fills that box.
function echo_post_editor(){
wp_nonce_field( $this->self['prefix'].'_post_nonce', $this->self['prefix'].'_nonce_field' );
$atts = array('media_buttons'=>false);
$arr = $this->self['meta_list'];
if(count($arr)>0){
$functs = array();
foreach($arr as $name=>$data){
$type = $this->get_value($data,'type');
$title = $this->get_value($data,'name');
$desc = $this->get_value($data,'desc');
if($type=='function'){
$fct = $this->get_value($data,'function');
if($fct!=''){if(!in_array($fct,$functs)){$functs[] = $fct;}}
}else{
echo '';
}
}
if(count($functs)>0){
foreach($functs as $dex=>$fct){
$this->runit($fct);
}
}
}
}
// Meta fields are registered as a variable name with an object prefix to keep it distinct from fields registerd by other WP products.
function get_fieldname($field,$over=false){
$pref = $this->self['prefix'];
if($over==false){if(!strstr($field,$pref)){return '_'.$pref.'_'.$field;}}
return $field;
}
// Simplified meta value function that adds the object prefix and weeds out un-registered meta fields.
function get_meta($post_id,$var=''){
if($var==''){return '';}
if(!isset($this->self['meta_list'][$var])){return '';}
$field = $this->get_fieldname($var);
return get_post_meta($post_id,$field,true);
}
// Return registered data as an array or return a value for a particular registered data point.
function get_meta_data($field,$var=''){
if(isset($this->self['meta_list'][$field])){
if($var!=''){return $this->get_value($this->self['meta_list'][$field],$var);}
return $this->self['meta_list'][$field];
}
return array();
}
// Hook into the post editor update functionality to include our registered meta fields.
function update_post($post_id,$post){
$runit = false;
if(is_single($post_id)){
if ( !empty($_POST) && check_admin_referer($this->self['prefix'].'_post_nonce',$this->self['prefix'].'_nonce_field') ){
$runit = true;
}
}else{
$runit = true;
}
if($runit==true){
$arr = $this->self['meta_list'];
if(count($arr)>0){
foreach($arr as $name=>$data){
$type = $this->get_value($data,'type');
$field = $this->get_fieldname($name);
$oldval = $this->get_meta($post_id,$field);
if($type=='checkbox'){
$newval = '';if(isset($_POST[$field])){$newval = 1;}
}else{
$newval = $this->get_value($_POST,$field);
}
if($newval!=$oldval or $newval==''){$this->update_meta($post_id,$field,$newval);}
}
}
}
}
// Update post meta by adding/editing where appropriate, and deleting when empty. Updating the meta field this way minimizes database weight by not storing empty values and simplifies using meta values in this object.
function update_meta($post_id,$var,$newval,$pref=false){
$field = $this->get_fieldname($var,$pref);
$ftype = $this->get_meta_data($var,'type');
if($ftype=='checkbox'){
if($newval=='1' or $newval=='true'){
$newval = '1';
}else{
$newval = '';
}
}
if($newval===''){
delete_post_meta($post_id,$field);
}else{
add_post_meta($post_id, $field, $newval, true) or update_post_meta($post_id, $field, $newval);
}
}
// Verify that this object has meta field(s) reistered, used to check if a process is needed before running it.
function using_meta(){
if(isset($this->self['meta_list']) and count($this->self['meta_list'])>0){
foreach($this->self['meta_list'] as $var=>$arr){
if($this->get_value($arr,'type')!=''){return true;}
}
}
return false;
}
// Handle the amp_header() function from base file available to theme users/developers.
function amp_header(){$this->amp_publisher('start');}
// Handle the amp_footer() function from base file available to theme users/developers.
function amp_footer(){$this->amp_publisher('end');}
// Handle the amp_publisher() function from base file available to theme users/developers.
// Googel AMP compliance is so rigid that we must control many aspects of generating page/theme content. We tried to open up as much as possible to the theme's template files, as well as making it easy to include these parts through a centralized function.
function amp_publisher($part='',$pass=''){
global $post;
if(isset($post)){$page_id = $post->ID;}else{$page_id = 0;}
$layout = $this->get_customizer_setting('site_layout');
$url = $this->current_page_url();
$title = $this->get_page_title();
$data = $this->get_document_data();
$pagetype = $this->get_value($data,'pagetype');
$pageid = $this->get_value($data,'pageid');
$dtype = $this->get_value($data,'jsontype');
$doctype = $this->get_markup($dtype,'type');
$hline = $this->get_markup('headline','prop');
$nline = $this->get_markup('name','prop');
$meline = $this->get_markup('mainEntityOfPage','prop');
$homeurl = home_url();
$img = $this->get_customizer_setting('header_logoimage');
$blogname = get_bloginfo('name');
$slogan = get_bloginfo('description');
$data = $this->get_document_data();
$desc = $this->get_value($data,'desc');
$published = $this->get_value($data,'published');
$modified = $this->get_value($data,'modified');
$publisher = $this->get_value($data,'publisher');
$image = $this->get_value($data,'img');
$imagew = $this->get_value($data,'imgw');
$imageh = $this->get_value($data,'imgh');
$ampd = $this->is_amp();
$comm = $this->is_amp_not();
$isin = $this->is_user_admin();
$preview = $this->is_amp_preview();
$edit = false;if($isin and !$preview){$edit = true;}
if($part=='before locations'){
if($this->is_advanced()){$this->prepare_locations('before',$pageid,$pagetype);}
}else if($part=='after locations'){
if($this->is_advanced()){$this->prepare_locations('after',$pageid,$pagetype);}
}else if($part=='sidebar locations'){
if($this->is_advanced()){$this->prepare_locations('sidebar',$pageid,$pagetype);}
}else if($part=='start'){
if($edit or $comm){wp_enqueue_script('jquery');}
if($edit){wp_enqueue_script('jquery-ui-sortable');}
if($ampd){
echo '';
echo '';
echo '';
wp_head();
$metadesc = '';
if(defined('WPSEO_FILE')){
$metadesc = WPSEO_Frontend::get_instance()->metadesc(false);
}else{
echo '';
}
if($metadesc==''){
if($this->is_advanced()){$metadesc = $this->get_page_setting($pageid,$pagetype,'metadesc');}
if($metadesc==''){if(is_home() or is_front_page()){$metadesc = get_bloginfo('description');}}
if($metadesc!=''){echo '';}
}
$keywords = '';
//if(is_singular()){
$list = get_the_tag_list();
$tags = get_tags();
if($tags!='' and count($tags)>0){
foreach($tags as $tag){
$tname = $tag->name;
$keywords = $this->delimitit($keywords,', ',$tname);
}
}
//}
if($keywords!=''){echo '';}
// this is only needed in non-amp version of the page when implemented linked to amp version... the amp canonical should have link to non-amp version if available, all pages generated by this theme are either amp or non-amp
//echo '';
echo '';
echo '';
echo $this->generate_amp_markups();
echo '';
echo '';
$this->include_amp_modules();
echo '';
echo '';
if($this->is_advanced()){$this->adv_pageview($pageid,$pagetype,$ampd);}
}else{
echo '';
echo '';
echo '';
echo '';
wp_head();
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
echo '';
if($edit){
echo '';
echo '';
echo '';
if($this->is_advanced()){
global $tacgadv;
echo '';
echo '';
echo '';
}
}
echo '';
echo '';
echo '';
}
}else if($part=='end'){
if($ampd){
if($this->is_advanced()){echo $this->adv_analytics();}
}else if($edit){
echo $this->generate_live_editor();
echo '
';
// the following is probably redundant as they get reported in the byline, but only if it is displayed
if($isinline=='yes'){
if(!is_category()){
if($published!=''){echo '';}
if($modified!=''){echo '';}
echo '';
}
echo '
';
}
}
}else if($part=='password protected content'){
if($ampd or $comm){
echo __('This content is password protected, and the page is generated by Google AMP (disallows forms).','amp-publisher');
echo ' ';
echo __('Click here to enable forms and enter the password.','amp-publisher');
echo '';
}else{
the_content();
}
}else if($part=='hide comments'){
if($pagetype=='page' or $pagetype=='post'){return get_option('tacg_nocomson'.$pagetype.'s');}
return true;
}
return '';
}
function extends_init(){
$this->self['apibaseurl'] = 'https://ampwptools.com/';
$this->self['Title'] = 'AMP Publisher';
if(class_exists('wfConfig')){
$wfwall = wfConfig::get('ajaxWatcherDisabled_front');
if(!$wfwall){
$wferr = 'Wordfence Firewall is active on the "Front" end, the javascript file it loads will cause Google AMP Validation to fail. You can turn this setting off in: wp-admin ~ Wordfence ~ Firewall ~ uncheck "Front" under "Monitor Background Requests for False Positives:" AMP does not need to validate while logged in, so you may leave "Admin Panel" checked.';
$this->register_notice($wferr,'warning');
}
}
$this->filter_handler('body_class');// Add class name for the site's layout to the body tag
$this->filter_handler('comment_post_redirect');// Add variables and anchor to the comment redirect url to trigger the non-AMP version of posts for commenting.
$this->filter_handler('comment_reply_link',30,4);// Add variables and anchor to the comment reply url to trigger the non-AMP version of posts for commenting.
$this->filter_handler('get_avatar',10,5);// Filter the avatar to make the image AMP compliant.
$this->filter_handler('language_attributes',9999);// Filter out language attributes that invalidate Google AMP compliance.
$this->filter_handler('mce_buttons_2');// Remove options from the WP HTML Editor that would invalidate AMP compliance.
$this->filter_handler('post_thumbnail_html');// Filter the post thuumbnail to make it AMP compliant.
$this->filter_handler('pre_get_document_title');// Filter the document meta-title if Yoast WPSEO is not already handling it.
// We turn off the Admin bar only during AMP previews for validation purposes... otherwise it is completely unaffected.
if($this->is_user_admin() and $this->get_value($_GET,'amp')=='1'){$this->filter_handler('show_admin_bar');}
$this->filter_handler('the_content',1,1);// Filter the content for AMP compliance.
$this->filter_handler('tiny_mce_before_init',9);// Turn off options and filters used by the WP HTML Editor that could invalidate AMP compliance.
}
function is_amp_search(){return true;}
function is_advanced(){if(is_callable(array($this,'verifyaddadv'))){return $this->verifyaddadv();}return false;}
// Create a device preview window running the current page through AMP. Initiated from generate_live_editor().
function ajax_amp_preview($params){
$wid = $this->get_value($params,'width','100%');
$hit = $this->get_value($params,'height','600px');
$how = $this->get_value($params,'how');
$url = $this->get_value($params,'url');
$adds = $this->get_value($params,'adds');
$urls = explode('?',$url);
$url = $urls[0];
echo '';
$ashow = '';
if(how!=''){$ashow = 'as'.$how;}
echo '
';
echo '
';
echo '';// iframe for device preview only
echo '
';
echo '
';
}
// Create a window for choosing a Fontawesome icon.
function ajax_choose_fontawesome($params){
$where = $this->get_value($params,'where');
$jst = 'html_editor';
if($where=='buttonbar'){$jst = 'buttonbar';}
$icons = $this->get_fontawesome_icons();
echo '
';
echo '
'.__('Select an Icon','amp-publisher').'
';
echo '';
echo '';
echo '
';
echo '
';
echo '
';
if(count($icons)>0){
foreach($icons as $icon){
echo '
';
echo '';
echo '
';
}
}else{
echo __('Unable to access the Font Awesome Library at this moment.','amp-publisher');
}
echo '
'.__('The Flags you see (category/tag) in Posts "Article" Display Mode use the site link colors by default, but you may choose custom styling for them here. Clear the color assignment to again use the link colors. You must refresh the browser to view changes to the flags.','amp-publisher').'
';
if(!$this->is_advanced()){
echo $this->generate_icon_button(array('label'=>__('Restore Sitewide Defaults','amp-publisher'),'title'=>__('Restore all sitewide styles and settings to the default.','amp-publisher'),'icon'=>'recycle','click'=>'tacg_restore_defaults();','style'=>'width:100%;margin-top:5px;'));
}
echo '
'.__('When an image is needed but none is assigned, the theme uses a default image labeled "no available photo". You may assign your own default image instead.','amp-publisher').'
'.__('Title & Tagline sizes are determined by your sitewide H1 & H2 settings (respectively).The Classic Layout hides the Title Bar, the page title is inserted near the page content.','amp-publisher').'
'.__('The Mobile Menu is opened using the "Hamburger" button that appears in devices and small browser windows. The button is always visible in the Side Navigation Layout.','amp-publisher').'
'.__('Click to Browse Media Library','amp-publisher').'
';
$RAT .= '
';
$RAT .= '
';
$RAT .= '
';
return $RAT;
}
// Create the CSS included in the header for chosen layouts and post display modes.
function generate_compiled_css($ampd,$pageid,$pagetype){
$RAT = '';
if($ampd){
$layout = $this->get_customizer_setting('site_layout');
if($layout==''){$layout = 'base';}
$RAT .= $this->function_call('generate_css_layout_'.$layout);
$cssfiles = array();
$display = $this->get_customizer_setting('site_postsdisplaymode');
$cssfiles = $this->process_css_for_display($cssfiles,$display);
if($this->is_advanced()){$cssfiles = $this->adv_compiled_css($cssfiles,$ampd,$pageid,$pagetype);}
if(count($cssfiles)>0){foreach($cssfiles as $file){$RAT .= $this->function_call('generate_css_'.$file);}}
}else{
$arr = $this->get_customizer_settings('site_layout');
$layouts = $this->get_value($arr,'choices');
if($layouts!=''){foreach($layouts as $layout=>$layttl){$RAT .= $this->function_call('generate_css_layout_'.$layout);}}
$displays = array('article','image','onethree','thumbnail');
foreach($displays as $display){$RAT .= $this->function_call('generate_css_display_'.$display);}
$modules = array('social_share','accordion','carousel');
foreach($modules as $mod){$RAT .= $this->function_call('generate_css_module_'.$mod);}
}
return $RAT;
}
// Create the CSS included in the header for AMP filters, conversions and settings.
function generate_custom_css(){
$RAT = '';
// start a stack of styles to be managed - preventing redundancy
$stack = array();
if($this->is_advanced()){$RAT .= $this->generate_composer_css();}
// gather styles onto the stack for Page/Post/Category Content conversions
$content = $this->get_document_content();
$styles = $this->amp_styles_to_classes($content,'styles');
if(count($styles)>0){
foreach($styles as $style){
foreach($style as $k=>$v){
$val = $this->amp_styles_css($k,$v);
if($val!=''){if(!isset($stack[$val])){$stack[$val] = $val;}}
}
}
}
// handle maximum widths for responsive amp-img in document content
$stack = $this->gather_image_styles($stack,$content);
// check for banner logo, get width, then setup css media override to responsive when the image is wider than the viewport... only way to bypass the AMP manipulations that I've found so far
$logo = $this->get_customizer_setting('header_logoimage');
if($logo!=''){
$imgdata = $this->get_attachment_data_by_src($logo);
$wid = $this->get_value($imgdata,'width');
$hit = $this->get_value($imgdata,'height');
$stack[] = '.headerlogo{max-width:'.$wid.'px;}';
$stack[] = '.bloginfo.haslogo{padding-left:'.($wid+40).'px;}';
}
// add social network colors for use in buttons and links
$socs = $this->get_social_network_data('social');
foreach($socs as $soc=>$data){
$color = $this->get_value($data,'color');
$stack[] = '.clr-'.$soc.',a.clr-'.$soc.'{color:'.$color.';}';
$stack[] = '.bgclr-'.$soc.'{background-color:'.$color.';}';
}
// process stack into CSS
if(count($stack)>0){foreach($stack as $css){$RAT .= $css;}}
return $RAT;
}
// Create the big blue button used in the Live Editor.
function generate_icon_button($params){
$label = $this->get_value($params,'label');
$title = $this->get_value($params,'title');
$icon = $this->get_value($params,'icon');
$size = $this->get_value($params,'size');
$class = $this->get_value($params,'class');
$style = $this->get_value($params,'style');
$click = $this->get_value($params,'click');
$stize = '';if($size!=''){$stize = ' style="font-size:'.$size.'px;"';}
$cls = 'icnbtn';if($class!=''){$cls .= ' '.$class;}
$ttl = '';if($title!=''){$ttl = 'title="'.$title.'"';}
$RAT = '';
$RAT .= '';
if($icon!=''){$RAT .= '';}
if($label!=''){$RAT .= ''.$label.'';}
$RAT .= '';
return $RAT;
}
// Create the checkbox input used by the Live Editor.
function generate_live_checkbox($id,$val,$flag=''){
$chk = '';
if($val=='1' or $val=='true' or $val===true){$chk = ' checked';}
return '';
}
// Create the color picker used by the Live Editor.
function generate_live_color_picker($id,$val,$ttl=''){
$RAT = '';
$rgb = '';
$hex = '';
if($this->isRGB($val)){$hex = $this->rgbToHex($val);$rgb = $this->rgbToArray($val);}
if($this->isHex($val)){$rgb = $this->hexToRGB($val);$hex = $val;}
$RAT .= '
';
}
}
return $RAT;
}
// Create a placeholder box instead of an AMP module when required data is missing. This alerts the admin to the missing content without invalidating AMP compliance.
function generate_placeholder($mod,$pass='',$over=''){
$RAT = '';
if($mod=='ad'){$mod = 'AD';}
$RAT .= '
';
return $RAT;
}
// Create the Social Sharing Button Manager in the Live Editor. This is the only feature available to the Live Editor that is not available to WP Customizer.
function generate_social_button_manager(){
$RAT = '';
$RAT .= ''.__('Choose an Icon to Create a Button','amp-publisher').'';
$list = $this->get_customizer_setting('social_buttonlist');
$RAT .= '
'.$social.'
'; echo '