Plugin Directory

Changeset 3213836


Ignore:
Timestamp:
12/27/2024 03:11:34 PM (3 months ago)
Author:
sosidee
Message:

Update to version 1.0.0

Location:
dynamic-qr-code/trunk
Files:
75 added
12 deleted
65 edited

Legend:

Unmodified
Added
Removed
  • dynamic-qr-code/trunk/admin/logs.php

    r2753631 r3213836  
    11<?php
     2defined( 'SOSIDEE_PROLICMAN' ) or die( 'you were not supposed to be here' );
     3
    24$plugin = \SOSIDEE_DYNAMIC_QRCODE\SosPlugin::instance();
    35$form = $plugin->formSearchLog;
     6$show_lang = $form->showLang();
     7$show_geo = $form->showGeo();
     8$show_desc = $form->showDesc();
     9$show_os = $form->showOS();
     10
    411$logs = $form->logs;
    512
     
    815$mfa_enabled = $plugin->config->mfaEnabled->value;
    916
    10 echo $plugin->help('logs');
     17echo $plugin->help('scan-logs');
    1118
     19$plugin->htmlAdminPageTitle('Scan logs');
    1220?>
    13 <h1>Scan logs</h1>
    1421
    1522<div class="wrap">
     
    2027
    2128    <table class="form-table" role="presentation">
    22         <thead>
     29        <tbody>
    2330        <tr>
    24             <th scope="col" class="centered middled">QR-Code</th>
    25             <th scope="col" class="centered middled">From date<br>(h <?php echo sosidee_time_format( \DateTime::createFromFormat('YmdHis', "20000001000000") ); ?>)</th>
    26             <th scope="col" class="centered middled">To date<br>(h <?php echo sosidee_time_format( \DateTime::createFromFormat('YmdHis', "20000001235959") ); ?>)</th>
    27             <th scope="col" class="centered middled">Status</th>
    28             <th scope="col" class="centered middled"></th>
    29             <th scope="col" class="centered middled"></th>
     31            <td class="centered topped">
     32                <span class="bolded">QR-Code</span><br>
     33                <?php $form->htmlQID(); ?>
     34            </td>
     35            <td class="centered topped">
     36                <span class="bolded">From date</span><br>
     37                <?php $form->htmlFrom(); ?>
     38                <br><span class="fs90pc">(h <?php echo sosidee_time_format( \DateTime::createFromFormat('YmdHis', "20000001000000") ); ?>)</span>
     39            </td>
     40            <td class="topped" rowspan="2">
     41                <span class="bolded" style="margin-bottom: 4px; display:block;">Display</span>
     42                <?php $form->htmlShowGeo(); ?>
     43                <br>
     44                <?php $form->htmlShowLang(); ?>
     45                <br>
     46                <?php $form->htmlShowDesc(); ?>
     47                <br>
     48                <?php $form->htmlShowOS(); ?>
     49            </td>
     50            <td class="centered middled">
     51                <?php $form->htmlCancelAll(); ?>
     52            </td>
    3053        </tr>
    31         </thead>
    32         <tbody>
    33         <td class="centered middled">
    34             <?php $form->htmlQID(); ?>
    35         </td>
    36         <td class="centered middled">
    37             <?php $form->htmlFrom(); ?>
    38         </td>
    39         <td class="centered middled">
    40             <?php $form->htmlTo(); ?>
    41         </td>
    42         <td class="centered middled">
    43             <?php $form->htmlStatus(); ?>
    44         </td>
    45         <td class="centered middled">
    46             <?php $form->htmlButton( 'search', 'search' ); ?>
    47         </td>
    48         <td class="centered middled">
    49             <?php $form->htmlCancelAll(); ?>
    50         </td>
     54        <tr>
     55            <td class="centered topped">
     56                <span class="bolded">Status</span><br>
     57                <?php $form->htmlStatus(); ?>
     58            </td>
     59            <td class="centered middled">
     60                <span class="bolded">To date</span><br>
     61                <?php $form->htmlTo(); ?>
     62                <br><span class="fs90pc">(h <?php echo sosidee_time_format( \DateTime::createFromFormat('YmdHis', "20000001235959") ); ?>)</span>
     63            </td>
     64            <td class="centered middled">
     65                <?php $form->htmlButton( 'search', 'search' ); ?>
     66            </td>
     67        </tr>
    5168        </tbody>
    5269    </table>
     
    5875        echo '<p>&nbsp; Record(s) found: ' . count($logs) . '</p>';
    5976    }
    60 
     77/*
    6178        $sw_uk = '30%';
    6279        if ( $mfa_enabled ) {
     
    8198            $sw_btn = '20%';
    8299        }
    83         //
     100*/
    84101
     102    if ( is_array($logs) && count($logs)>0 ) {
    85103    ?>
    86104
     
    88106        <thead>
    89107        <tr>
    90             <th scope="col" class="bordered middled centered" style="width:<?php echo esc_attr( $sw_date ); ?>">Date</th>
    91             <th scope="col" class="bordered middled centered" style="width:<?php echo esc_attr( $sw_code ); ?>">Key</th>
    92             <th scope="col" class="bordered middled centered" style="width:<?php echo esc_attr( $sw_state ); ?>">Status</th>
     108            <th scope="col" class="bordered middled centered">Date</th>
     109            <th scope="col" class="bordered middled centered">Status</th>
     110            <th scope="col" class="bordered middled centered">Key</th>
    93111            <?php if ( $code_shared ) { ?>
    94                 <th scope="col" class="bordered middled centered" style="width:<?php echo esc_attr( $sw_qid ); ?>">Q-ID</th>
     112                <th scope="col" class="bordered middled centered">Q-ID</th>
     113            <?php } ?>
     114            <?php if ( $show_desc ) { ?>
     115                <th scope="col" class="bordered middled centered">Description</th>
     116            <?php } ?>
     117            <?php if ( $show_lang ) { ?>
     118                <th scope="col" class="bordered middled centered">Language</th>
     119            <?php } ?>
     120            <?php if ( $show_geo ) { ?>
     121                <th scope="col" class="bordered middled centered">Country</th>
     122            <?php } ?>
     123            <?php if ( $show_os ) { ?>
     124                <th scope="col" class="bordered middled centered">Op. System</th>
    95125            <?php } ?>
    96126            <?php if ( $mfa_enabled ) { ?>
    97                 <th scope="col" class="bordered middled centered" style="width:<?php echo esc_attr( $sw_uk ); ?>">My FastAPP User Key</th>
     127                <th scope="col" class="bordered middled centered">My FastAPP User Key</th>
    98128            <?php } ?>
    99             <th scope="col" class="centered middled" style="width:<?php echo esc_attr( $sw_btn ); ?>">
    100                 <?php
    101                 if ( is_array($logs) && count($logs)>0 ) {
    102                     $form->htmlDownload( $logs, $code_shared, $mfa_enabled );
    103                 }
    104                 ?>
     129            <th scope="col" class="centered middled">
     130                <?php $form->htmlDownload( $logs, $mfa_enabled ); ?>
    105131            </th>
    106132        </tr>
     
    108134        <tbody>
    109135        <?php
    110         if ( is_array($logs) && count($logs)>0 ) {
    111136            for ($n=0; $n<count($logs); $n++) {
    112137                $item = $logs[$n];
     
    118143                $status_icon = $item->status_icon;
    119144                $mfa_user_key = $item->user_key;
     145                $lang = $show_lang ? $item->lang_desc : '';
     146                $geo = $show_geo ? $item->country_desc : '';
     147                $desc = $show_desc ? $item->qrcode_desc : '';
     148                $op_sys = $show_os ? $item->os_desc : '';
    120149
    121150                ?>
    122151                <tr>
    123152                    <td class="bordered middled centered"><?php echo esc_html( $creation ); ?></td>
     153                    <td class="bordered middled centered"><?php echo sosidee_kses( $status_icon ); ?></td>
    124154                    <td class="bordered middled centered"><?php echo esc_html( $code ); ?></td>
    125                     <td class="bordered middled centered"><?php echo sosidee_kses( $status_icon ); ?></td>
    126155                    <?php if ( $code_shared ) { ?>
    127156                        <td class="bordered middled centered"><?php echo esc_html( $quid ); ?></td>
     157                    <?php } ?>
     158                    <?php if ( $show_desc ) { ?>
     159                        <td class="bordered middled centered"><?php echo esc_html( $desc ); ?></td>
     160                    <?php } ?>
     161                    <?php if ( $show_lang ) { ?>
     162                        <td class="bordered middled centered"><?php echo esc_html( $lang ); ?></td>
     163                    <?php } ?>
     164                    <?php if ( $show_geo ) { ?>
     165                        <td class="bordered middled centered"><?php echo esc_html( $geo ); ?></td>
     166                    <?php } ?>
     167                    <?php if ( $show_os ) { ?>
     168                        <td class="bordered middled centered"><?php echo esc_html( $op_sys ); ?></td>
    128169                    <?php } ?>
    129170                    <?php if ( $mfa_enabled ) { ?>
     
    132173                    <td class="bordered middled centered"><?php $form->htmlCancel( $id ); ?></td>
    133174                </tr>
    134             <?php }
    135         } ?>
     175            <?php } ?>
    136176        </tbody>
    137177    </table>
     178<?php } ?>
    138179
    139180    <?php
  • dynamic-qr-code/trunk/admin/qrcode.php

    r2815343 r3213836  
    11<?php
     2defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
     3
     4use SOSIDEE_DYNAMIC_QRCODE\SRC\FORM\CheckMode;
     5
    26$plugin = \SOSIDEE_DYNAMIC_QRCODE\SosPlugin::instance();
    37$form = $plugin->formEditQrCode;
     
    711$code_shared = $plugin->config->sharedCodeEnabled->value;
    812$mfa_enabled = $plugin->config->mfaEnabled->value;
     13$chkMode = $plugin->config->formCheckMode->value;
    914$anyQrHideEnabled = $plugin->config->anyQrHideEnabled->value;
    10 
    11 echo $plugin->help('edit');
     15//$hideContentEnabled = $anyQrHideEnabled || $form->cypher->value != '';
     16
     17echo $plugin->help('qr-code-edit');
    1218
    1319$title = 'QR-Code Edit';
     
    1521    $title .= ' (new)';
    1622}
    17 
    18 echo '<h1>'.  esc_html( $title ) . '</h1>';
    19 
     23$plugin->htmlAdminPageTitle($title);
    2024?>
    2125
     
    161165            </td>
    162166            <td style="width: 120px;">
    163                 <?php //$plugin->formSearchQrCode->htmlLinkButton(0, 'new'); ?>
    164167                <?php $plugin->formEditQrCode->htmlButtonLink(0); ?>
    165168            </td>
     
    167170                <?php $form->htmlSave('save'); ?>
    168171            </td>
     172            <td style="width: 120px;">
     173                <?php $form->htmlDuplicate(); ?>
     174            </td>
    169175        </tr>
    170176        </tbody>
    171177    </table>
    172178
     179<?php if ( $code_shared || $anyQrHideEnabled ) { ?>
    173180    <table class="form-table sqc" role="presentation">
    174181        <tbody>
     182    <?php if ( $code_shared ) { ?>
     183        <tr>
     184            <th scope="row" class="middled">Q-ID</th>
     185            <td class="middled">
     186                <?php $form->htmlQid(); ?>
     187            </td>
     188        </tr>
     189    <?php
     190    }
     191
     192    if ( $anyQrHideEnabled ) {
     193    ?>
    175194        <tr>
    176195            <th scope="row" class="middled">Shortcode for content hiding</th>
     
    179198            </td>
    180199        </tr>
    181     <?php if ( $code_shared ) { ?>
    182         <tr>
    183             <th scope="row" class="middled">Q-ID</th>
    184             <td class="middled">
    185                 <?php $form->htmlQid(); ?>
    186             </td>
    187         </tr>
    188     <?php } ?>
    189     <?php if ( $anyQrHideEnabled ) { ?>
     200    <?php if ( $chkMode == CheckMode::FIELD ) { ?>
    190201        <tr>
    191202            <th scope="row" class="middled">Form hidden field</th>
     
    194205            </td>
    195206        </tr>
    196     <?php } ?>
     207    <?php
     208        }
     209    }
     210    ?>
    197211        </tbody>
    198212    </table>
     213<?php } ?>
    199214
    200215    <p>&nbsp;</p>
     
    202217        <a id="a-std" href="javascript:void(0);" class="nav-tab<?php echo !$cypher ? ' nav-tab-active' : ''; ?>">Standard QR code</a>
    203218        <a id="a-enh" href="javascript:void(0);" class="nav-tab<?php echo $cypher ? ' nav-tab-active' : ''; ?>">Enhanced QR code</a>
    204         <?php echo $plugin->help('std-enh-img', 'vertical-align: text-bottom; margin: 4px; margin-left: 1em;'); ?>
     219        <?php echo $plugin->help('standard-enhanced-image', 'vertical-align: text-bottom; margin: 4px; margin-left: 1em;'); ?>
    205220    </nav>
    206221    <div id="div-std" style="display: <?php echo !$cypher ? 'block' : 'none'; ?>;">
     
    259274        </table>
    260275
    261         <?php if ( !$anyQrHideEnabled ) { ?>
     276    <?php if ( !$anyQrHideEnabled ) { ?>
    262277        <table class="form-table sqc" role="presentation">
    263278            <tbody>
     279            <tr>
     280                <th scope="row" class="middled">Shortcode for content hiding</th>
     281                <td class="middled">
     282                    <?php $form->htmlQRShortcode1(); ?>
     283                </td>
     284            </tr>
     285        <?php if ( $chkMode == CheckMode::FIELD ) { ?>
    264286            <tr>
    265287                <th scope="row" class="middled">Form hidden field</th>
     
    268290                </td>
    269291            </tr>
     292        <?php } ?>
    270293            </tbody>
    271294        </table>
    272         <?php } ?>
     295    <?php } ?>
    273296    </div>
    274297
     
    285308
    286309<?php
     310    $form->htmlCodeOld();
    287311    $form->htmlId();
    288312    $form->htmlCypher();
    289313    $form->htmlClose();
     314
     315    if ( !$plugin->hasDuplicate() ) {
     316        echo '<hr style="margin-left:0;width:50%;">';
     317        echo $plugin->pro() . ' available in the PRO version';
     318    }
     319
    290320?>
    291321
  • dynamic-qr-code/trunk/admin/qrcodes.php

    r2779336 r3213836  
    11<?php
     2defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
     3
     4use SOSIDEE_DYNAMIC_QRCODE\SRC\QrCode;
     5use SOSIDEE_DYNAMIC_QRCODE\SRC\QrCodeSearchStatus;
     6use SOSIDEE_DYNAMIC_QRCODE\SRC\Copy2CB;
    27
    38$plugin = \SOSIDEE_DYNAMIC_QRCODE\SosPlugin::instance();
    49$form = $plugin->formSearchQrCode;
    510$qrcodes = $form->qrcodes;
    6 $plugin->config->load(); // load current configuration
     11$plugin->config->load(); // load the current configuration
    712$code_shared = $plugin->config->sharedCodeEnabled->value;
     13
    814
    915if ( $code_shared ) {
     
    1319}
    1420
    15 echo $plugin->help('list');
     21echo $plugin->help('qr-codes-list');
     22
     23$plugin->htmlAdminPageTitle('QR-Code List');
    1624?>
    17 <h1>QR-Code List</h1>
    1825
    1926<div class="wrap">
     
    6471        $id = $item->qrcode_id;
    6572        $url = $item->url_api;
    66         $quid = \SOSIDEE_DYNAMIC_QRCODE\SRC\QrCode::getQID( $item->qrcode_id );
    67         $copy = $plugin->getCopyApiUrl2CBIcon( $id, $code );
     73        $quid = QrCode::getQID( $item->qrcode_id );
     74        //$copy = $plugin->getCopyApiUrl2CBIcon( $id, $code );
     75        $copy = Copy2CB::getApiUrlIcon( $id, $code );
    6876    ?>
    6977            <tr>
     
    9098        if ( is_array($qrcodes) && count($qrcodes) > 0 ) {
    9199            echo 'Legend<br>State:';
    92             $states = \SOSIDEE_DYNAMIC_QRCODE\SRC\QrCodeSearchStatus::getList();
     100            $states = QrCodeSearchStatus::getList();
    93101            foreach ( $states as $key => $value ) {
    94102                echo ' &nbsp; ';
    95                 $icon = \SOSIDEE_DYNAMIC_QRCODE\SRC\QrCodeSearchStatus::getStatusIcon( $key );
     103                $icon = QrCodeSearchStatus::getStatusIcon( $key );
    96104                echo sosidee_kses( $icon . ' ' . $value );
    97105            }
  • dynamic-qr-code/trunk/assets/css/admin.css

    r2684394 r3213836  
    22    border-collapse: collapse;
    33}
    4 table.bordered, th.bordered, td.bordered {
     4table.bordered th, table.bordered td {
    55    border: 1px solid gray;
    66}
     7table.topped th, table.topped td {
     8    vertical-align: top;
     9}
     10table th.bottomed, table td.bottomed {
     11    vertical-align: bottom;
     12}
     13
    714table.rounded4 {
    815    border-collapse: separate;
     
    1623    text-align: center;
    1724}
     25th.topped, td.topped {
     26    vertical-align: top;
     27}
    1828th.middled, td.middled {
    1929    vertical-align: middle;
     
    2232    text-align: center;
    2333    vertical-align: middle;
    24 }
    25 th.italiced, td.italiced {
    26     font-style: italic;
    2734}
    2835table.pad2p th, table.pad2p td {
     
    5057    margin: 0;
    5158}
     59
     60.italiced {
     61    font-style: italic;
     62}
     63.bolded {
     64    font-weight: bold;
     65}
     66.fs90pc {
     67    font-size: 90%;
     68}
     69
     70/* to avoid flickering on mouseover (google charts bug, unfixed...) */
     71.google-visualization-tooltip { pointer-events: none }
  • dynamic-qr-code/trunk/assets/css/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/assets/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/assets/js/config.js

    r2779336 r3213836  
    6060        value = jsDynCypherObj.min;
    6161    }
    62     let value64 = jsDynGetB64Len(value) + jsDynCypherObj.base; // manually inserted values can be freak
    63     if ( ctrl.value != value64 ) {
     62    let value64 = jsDynGetB64Len(value) + jsDynCypherObj.base; // manually inserted values could be odd
     63    if ( ctrl.value !== value64 ) {
    6464        ctrl.value = value64;
    6565    }
  • dynamic-qr-code/trunk/assets/js/index.html

    r2753631 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/assets/js/qrcode.js

    r2753631 r3213836  
    11(function($){
    22    'use strict';
    3     $(document).ready(function()
    4     {
    5         if (!$.ajax) { return null; }
     3    $(document).ready(function() {
    64
    75        $('#a-std').click( function() {
  • dynamic-qr-code/trunk/dynamic-qr-code.php

    r2815343 r3213836  
    22/*
    33Plugin Name: Dynamic QR Code
    4 Version: 0.9.3
     4Version: 1.0.0
    55Description: Allows you to create DYNAMIC QR CODES: you can modify what happens when scanning your QR code without actually modifying (and reprinting) the QR code.
     6Requires at least: 5.9
     7Tested up to: 6.7
     8Requires PHP: 8.0
    69Author: SOSidee.com srl
    710Author URI: https://sosidee.com
    811Text Domain: dynamic-qr-code
    912Domain Path: /languages
     13Plugin URI: https://sosplugin.com/dynamic-qr-code/
     14Contributors: sosidee
    1015*/
    1116namespace SOSIDEE_DYNAMIC_QRCODE;
     
    1520use SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA as DATA;
    1621
    17 require_once "loader.php";
     22require_once "wp-loader.php";
    1823
    1924\SOSIDEE_CLASS_LOADER::instance()->add( __NAMESPACE__, __DIR__ );
     
    2631{
    2732
    28     private static $helpUrl = 'https://redirect.soslink.net/dynamic-qr-code/help/';
     33    use SRC\TAddon;
    2934
    3035    //pages
    3136    private $pageQrCodes;
    3237    private $pageLogs;
     38
    3339    public $pageQrCode;
    34     public $pageConfig;
     40    public $pageConfigs;
     41    private $pageStats;
    3542
    3643    //database
     
    4249    public $formEditQrCode;
    4350    public $formSearchLog;
    44 
    45     //API
    46     private $apiRedirect;
     51    public $formStatLog;
     52
     53    private $apiRedirect; //API
    4754
    4855    private $mbHC; //metabox for hiding post/page content
    49 
    50     public static $FLD_HID;
    5156
    5257    protected function __construct() {
     
    5762        $this->name = 'Dynamic QR Code';
    5863
    59         self::$FLD_HID = SRC\Shortcode::TAG . '_' . SRC\Shortcode::AUTH;
     64        SRC\FORM\Base::$FLD_HID = SRC\Shortcode::TAG . '_' . SRC\Shortcode::AUTH;
    6065
    6166        //if necessary, enable localization
    6267        //$this->internationalize( 'dynamic-qr-code' ); //Text Domain
     68
     69        self::$helpUrl = 'https://support.sosidee.com/{KEY}/';
     70        $this->setHelp('dynamic-qr-code');
     71
     72        $this->checkAddon = true;
     73        $this->addonClass = 'DQC';
     74
    6375    }
    6476
     
    6880        // settings
    6981        $section = $this->addSection('config', 'Settings');
    70         //$section->validate = array($this, 'validateConfig'); //moved to form/config //function to be called on configuration data saving
    71         $this->config = new SRC\FORM\Config( $section );
     82        $this->config = new SRC\FORM\Configs( $section );
    7283
    7384        // database: custom tables for the plugin
    7485        $this->database = new SRC\Database();
    7586
    76         $this->apiRedirect = $this->addApiAny('dynamic-qr-code', [$this, 'apiRedirectByCode'], 0 );
     87        $this->apiRedirect = $this->addApiAny('dynamic-qr-code', [ $this, 'apiRedirectByCode' ], 0 );
    7788        $this->apiRedirect->nonceDisabled = true;
    7889
    79         $this->mbHC = $this->addMetaBox( 'post-content', $this->name );
    80         $this->mbHC->addField( 'qid', 0 );
    81         $this->mbHC->addField( 'form', false, true );
    82         $this->mbHC->html = [$this, 'htmlMetabox'];
    83         $this->mbHC->callback = [$this, 'saveMetabox'];
    84 
     90        $mb = $this->addMetaBox( 'post-content', $this->name );
     91        $this->mbHC = new SRC\Metabox($mb);
     92
     93        //if ( $this->hasAnyAddon() ) {
     94        //    $this->name .= ' PRO';
     95        //}
    8596    }
    8697
     
    89100        $this->pageQrCodes = $this->addPage('qrcodes' );
    90101        $this->pageQrCode = $this->addPage('qrcode' );
     102        $this->pageQrCode->menuHidden = true;
    91103        $this->pageLogs = $this->addPage('logs' );
    92         $this->pageConfig = $this->addPage('config' );
     104        $this->pageConfigs = $this->addPage('configs' );
     105        $this->pageStats = $this->addPage('stats' );
    93106
    94107        //assign data cluster to page
    95         $this->config->setPage( $this->pageConfig );
     108        $this->config->setPage( $this->pageConfigs );
    96109
    97110        //menu
     
    99112
    100113        $this->menu->add( $this->pageQrCodes, 'QR-Codes' );
    101         $this->menu->addHidden( $this->pageQrCode );
     114        $this->menu->add( $this->pageQrCode );
    102115        $this->menu->add( $this->pageLogs, 'Scan logs' );
    103         $this->menu->add( $this->pageConfig, 'Settings' );
     116        $this->menu->add( $this->pageStats, 'Scan stats' );
     117        $this->menu->add( $this->pageConfigs, 'Settings' );
    104118
    105119        $this->formSearchQrCode = new SRC\FORM\QrCodeSearch();
     
    112126        $this->formSearchLog->addToPage( $this->pageLogs );
    113127
     128        $this->formStatLog = new SRC\FORM\logStat();
     129        $this->formStatLog->addToPage( $this->pageStats );
     130
    114131        $this->qsArgs[] = SRC\FORM\QrCodeEdit::QS_ID;
    115132
    116133        $this->addScript('admin')->addToPage( $this->pageQrCodes, $this->pageQrCode );
    117134        $this->addScript('qrcode')->addToPage( $this->pageQrCode );
    118         $this->addScript('config')->addToPage( $this->pageConfig );
    119         $this->addStyle('admin')->addToPage( $this->pageQrCodes, $this->pageQrCode, $this->pageLogs );
     135        $this->addScript('config')->addToPage( $this->pageConfigs );
     136        $this->addStyle('admin')->addToPage( $this->pageQrCodes, $this->pageQrCode, $this->pageLogs, $this->pageStats );
    120137        $this->addGoogleIcons();
    121138        $this->addGoogleIconsToEditor();
     
    125142        add_action('current_screen', [$this, 'checkConfig']);
    126143
    127     }
    128 
    129     public function loadQrCodeList( $caption = '' ) {
     144        //TEST
     145        //$dw = new SOS\WP\DashboardWidget('custom_help_widget', 'Pippo');
     146        //$dw->callback = [$this, 'xxx'];
     147    }
     148
     149    /*
     150    public function loadQrCodeList( $caption = false, $include_cancelled = false ) {
    130151        $ret = [];
    131         if ( $caption != '' ) {
     152        if ( $caption !== false ) {
    132153            $ret[0] = $caption;
    133154        }
    134155
    135         $results = $this->database->loadQrCodeList();
     156        $results = $this->database->loadQrCodeList( $include_cancelled );
    136157
    137158        if ( is_array($results) ) {
     
    146167        return $ret;
    147168    }
    148 
    149     public function htmlMetabox( $metabox, $post ) {
    150 
    151         echo '<p>Prevent users to view the post/page if not accessed by scanning the image of this QR-Code: ';
    152         echo $this->help('hide-2', 'float: right;');
    153         echo '</p>';
    154         $options = $this->loadQrCodeList('- select -');
    155         $qid = $metabox->getField('qid');
    156         echo '<p>';
    157         echo $qid->getSelect( [ 'options' => $options ] );
    158         echo '</p>';
    159         $form = $metabox->getField('form');
    160         echo '<p>';
    161         echo $form->getCheckbox("allow reloading this post/page by submitting the form(s) contained in it");
    162         echo '</p>';
    163 
    164     }
    165 
    166     public function saveMetabox( $metabox, $post, $update ) {
    167         $res = $metabox->save( $post );
    168         if ( $res === false ) {
    169             $metabox->err("{$this->name}: cannot save the data.");
    170         }
    171     }
    172 
    173     private function setJsCookieEraser() {
    174         $cookie = SRC\OTKey::COOKIENAME;
    175         $js = "document.cookie = '{$cookie} =; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';";
     169    */
     170
     171    public function addDeleteCookieScript( $js ) {
    176172        $this->addInlineScript( $js, 'cookie-delete' );
    177173    }
    178174
    179     private function getJsRedirect( $url ) {
     175    public function getJsRedirect( $url ) {
    180176        $ret = '<p style="font-style: italic;">';
    181         $ret .= SOS\WP\DATA\FormTag::get( 'img', [
    182             'alt' => 'waiting...'
     177        $ret .= DATA\FormTag::get( 'img', [
     178             'alt' => 'waiting...'
    183179            ,'src' => $this->getLoaderSrc(24)
    184180            ,'width' => '12px'
     
    190186            self.window.location.replace('{$url}');
    191187EOD;
    192         $ret .= SOS\WP\DATA\FormTag::get( 'script', [
    193             'type' => 'application/javascript'
     188        $ret .= DATA\FormTag::get( 'script', [
     189             'type' => 'application/javascript'
    194190            ,'content' => $js
    195191        ]);
     
    198194    }
    199195
    200     private function isFormPosted() {
    201         return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) == 'POST';
    202     }
    203 
    204     private function checkPostedForm( $value ) {
    205         $ret = false;
    206         if ( $this->isFormPosted() ) {
    207             switch ( $this->config->formCheckMode->value ) {
    208                 case SRC\FORM\CheckMode::METHOD:
    209                     $ret = true;
    210                     break;
    211                 case SRC\FORM\CheckMode::REFERER:
    212                     $ref = wp_get_raw_referer();
    213                     $pid = url_to_postid($ref);
    214                     if ( $pid == get_the_ID() ) {
    215                         $ret = true;
    216                     } else {
    217                         sosidee_log("Hiding content: data posted from an invalid URL. Referer=$ref");
    218                     }
    219                     break;
    220                 case SRC\FORM\CheckMode::FIELD:
    221                     if ( isset($_POST[self::$FLD_HID]) ) {
    222                         $hid = trim( $_POST[self::$FLD_HID] );
    223                         if ( strcasecmp( $hid, $value) == 0 ) {
    224                             $ret = true;
    225                         } else {
    226                             sosidee_log("Hiding content: hidden field value is {$hid} while {$value} was expected.");
    227                         }
    228                     } else {
    229                         sosidee_log("Hiding content: hidden field not found.");
    230                     }
    231                     break;
    232             }
    233         } else {
    234             sosidee_log("Hiding content: invalid REQUEST_METHOD value.");
    235         }
    236         return $ret;
    237     }
    238 
    239     public function checkMetaboxPost( $content ) {
    240         $this->mbHC->load();
    241         $qid = $this->mbHC->getField('qid');
    242 
    243         if ( $qid->value > 0 ) {
    244             $show = false;
    245             $id = $qid->value;
    246             $form = $this->mbHC->getField('qid');
    247             $hasForm = boolval( $form->value );
    248             $delete_cookie = true;
    249 
    250             $isMobileBrowser = SRC\Mobile::is() && SRC\Mobile::isBrowser();
    251             $this->config->load(); // load current configuration
    252             $isDeviceEnabled = $isMobileBrowser || $this->config->anyDeviceEnabled->value; //it's a mobile browser OR any device
    253 
    254             if ( $isDeviceEnabled ) {
    255                 //controllare il valore del cookie, e poi ...
    256                 $key = SRC\OTKey::getCookie();
    257                 if ( $key != '' ) {
    258                     $otkey = $this->database->loadOTKey( $key, $id );
    259                     if ( $otkey !== false && $otkey->otk_id > 0 ) {
    260                         $tally = intval( $otkey->tally );
    261                         $tally++;
    262                         if ( $this->database->updateOTKey( $otkey->otk_id, $tally ) == false ) {
    263                             sosidee_log("database.updateOTKey({$tally}) failed for key.id={$otkey->otk_id}");
    264                         }
    265                         if ( $tally == 1 ) {
    266                             if ( $hasForm ) {
    267                                 $delete_cookie = false;
    268                             }
    269                             $show = true;
    270                         } else {
    271                             if ( $hasForm && $this->checkPostedForm( $id ) ) {
    272                                 $show = true;
    273                                 $delete_cookie = false;
    274                             } else {
    275                                 sosidee_log("Hiding content: cookie already used.");
    276                             }
    277                         }
    278                     } else {
    279                         if ( $otkey !== false ) {
    280                             sosidee_log("Hiding content: cookie key not found in the database.");
    281                         } else {
    282                             sosidee_log("Hiding content: a problem occurred while reading the cookie key in the database.");
    283                         }
    284                     }
    285                 } else {
    286                     sosidee_log("Hiding content: cookie not found.");
    287                 }
    288             } else {
    289                 sosidee_log("Hiding content: device not enabled.");
    290             }
    291 
    292             if ( $delete_cookie ) {
    293                 $this->setJsCookieEraser();
    294             }
    295 
    296             if ( $show ) {
    297                 $ret = $content;
    298             } else {
    299                 $qrcode = $this->database->loadQrCode( $id );
    300                 if ( $qrcode !== false ) {
    301                     $url = $qrcode->url_cypher;
    302                 } else {
    303                     $url = '';
    304                     sosidee_log("database.loadQrCode({$qid->value}) returned false.");
    305                 }
    306                 if ( $url == '') {
    307                     $url = $this->config->urlError->value;
    308                 }
    309                 $ret = $this->getJsRedirect( $url );
    310             }
    311 
    312         } else {
    313             $ret = $content;
    314         }
    315 
    316         return $ret;
    317     }
    318 
    319196    protected function initializeFrontend() {
    320         add_filter( 'the_content', [ $this, 'checkMetaboxPost' ] );
     197        //add_filter( 'the_content', [ $this, 'checkMetaboxPost' ] );
     198        add_filter( 'the_content', [ $this->mbHC, 'checkPost' ] );
    321199        $this->addShortCode( SRC\Shortcode::TAG, array($this, 'dynqrcode_handle_shortcode') );
    322200    }
    323201
    324202    public function checkConfig() {
     203        if ( !function_exists('ImageCreate') ) {
     204            $msg = "<span class=\"dashicons dashicons-admin-generic\"></span> GD library (PHP) not found: please contact your server administrator.";
     205            self::msgErr( $msg );
     206        }
    325207
    326208        if ( $this->pageQrCodes->isCurrent() || $this->pageQrCode->isCurrent() ) {
    327209            if ( !$this->config->check() ) {
    328                 $msg = "<span class=\"dashicons dashicons-admin-generic\"></span> Configuration is not valid: please check <a href=\"{$this->pageConfig->url}\">{$this->pageConfig->title}</a>";
     210                $msg = "<span class=\"dashicons dashicons-admin-generic\"></span> Configuration is not valid: please check <a href=\"{$this->pageConfigs->url}\">{$this->pageConfigs->title}</a>";
    329211                $this::msgErr($msg);
    330212            }
     
    333215                $this->config->logDisabled->load();
    334216                if ( $this->config->logDisabled->value == true ) {
    335                     $msg = "<span class=\"dashicons dashicons-admin-generic\"></span> Logs are currently disabled: please check <a href=\"{$this->pageConfig->url}\">{$this->pageConfig->title}</a>";
     217                    $msg = "<span class=\"dashicons dashicons-admin-generic\"></span> Logs are currently disabled: please check <a href=\"{$this->pageConfigs->url}\">{$this->pageConfigs->title}</a>";
    336218                    self::msgWarn( $msg );
    337219                }
     
    429311        }
    430312
    431         if ( $msg != '') {
     313        if ( $msg != '' ) {
    432314            $ret .= DATA\FormTag::get( 'pre', [
    433315                'content' => "{$this->name}: " . $msg
     
    466348
    467349                    $this->config->load(); // load current configuration
    468                     $isMobileBrowser = SRC\Mobile::is() && SRC\Mobile::isBrowser();
     350                    $isMobileBrowser = SOS\Mobile::is() && SOS\Mobile::isBrowser();
    469351                    $isDeviceEnabled = $isMobileBrowser || $this->config->anyDeviceEnabled->value; //it's a mobile browser OR any device
    470352
     
    486368                                    }
    487369                                } else {
    488                                     if ( $sc->hasForm && $this->checkPostedForm( $sc->id ) ) {
     370                                    if ( $sc->hasForm && SRC\FORM\Base::checkPosted( $sc->id ) ) {
    489371                                        $show = true;
    490372                                        $delete_cookie = false;
     
    528410
    529411        if ( $delete_cookie ) {
    530             $this->setJsCookieEraser();
     412            SRC\OTKey::setJsCookieEraser();
    531413        }
    532414
     
    543425        }
    544426    }
     427
    545428    public function getApiUrlLength( $code_length = 0 ) {
    546429        if ( $code_length > 0 ) {
     
    548431        }
    549432        return strlen( $this->getApiUrl() ) + 4 + $code_length;
    550     }
    551 
    552     private function getCopy2CBIcon( $text, $title ) {
    553         return '<a href="javascript:void(0);" onclick="jsSosCopy2Clipboard(\'' . esc_js($text) . '\')" title="' . esc_attr($title) . '" style="width: inherit;"><i class="material-icons" style="vertical-align: bottom; max-width: 1em; font-size: inherit; line-height: inherit;">content_copy</i></a>';
    554     }
    555 
    556     private function getCopy2CBAlert( $text, $title ) {
    557         return '<a href="javascript:void(0);" onclick="alert(\'' . esc_js($text) . '\')" title="' . esc_attr($title) . '" style="width: inherit;"><i class="material-icons" style="vertical-align: bottom; max-width: 1em; font-size: inherit; line-height: inherit;">content_copy</i></a>';
    558     }
    559 
    560     public function getShortcode1Template( $id ) {
    561         $ret = '[' . SRC\Shortcode::TAG . ' ' . SRC\Shortcode::AUTH . "={$id}]";
    562         $ret .= 'content displayed to QR code scanners';
    563         $ret .= '[/' . SRC\Shortcode::TAG . ']';
    564         return $ret;
    565     }
    566 
    567     public function getShortcode2Template( $id, $standard ) {
    568         $ret = '[' . SRC\Shortcode::TAG . ' ' . SRC\Shortcode::DISPLAY . "={$id}";
    569         if ( $standard ) {
    570             $ret .= ' ' . SRC\Shortcode::IMAGE . '="standard"';
    571         }
    572         $ret .= ']';
    573         return $ret;
    574     }
    575 
    576     public function getHiddenFieldTemplate( $id ) {
    577         return DATA\FormTag::get( 'input', [
    578              'type' => 'hidden'
    579             ,'name' => self::$FLD_HID
    580             ,'value' => $id
    581         ]);
    582     }
    583 
    584     public function getCopyApiUrl2CBIcon( $id, $code, $cypher = false ) {
    585         $title = "copy QR-Code URL to clipboard";
    586         if ( $id > 0 && $code != '' ) {
    587             return $this->getCopy2CBIcon(  $this->getApiUrl($code, $cypher), $title );
    588         } else {
    589             if ( $id <= 0 ) {
    590                 return $this->getCopy2CBAlert( "Please save the QR-Code before copying the URL to clipboard.", $title );
    591             } else {
    592                 if ( !$cypher ) {
    593                     return $this->getCopy2CBAlert( "Attention: key is empty.", $title );
    594                 } else {
    595                     return $this->getCopy2CBAlert( "Please generate the enhanced QR-Code image before copying the URL to clipboard.", $title );
    596                 }
    597             }
    598         }
    599     }
    600 
    601     public function getCopyShortcode2CBIcon( $id, $index = 1, $standard = false ) {
    602         $title = "copy shortcode to clipboard";
    603         if ( $id > 0 ) {
    604             if ( $index == 1 ) {
    605                 $text = $this->getShortcode1Template( $id );
    606             } else if ( $index == 2 ) {
    607                 $text = $this->getShortcode2Template( $id, $standard );
    608             } else {
    609                 $text = 'a problem occurred';
    610             }
    611             return $this->getCopy2CBIcon( $text , $title );
    612         } else {
    613             return $this->getCopy2CBAlert( "Please save the QR-Code before copying the shortcode to clipboard.", $title );
    614         }
    615     }
    616 
    617     public function getCopyHiddenField2CBIcon( $id ) {
    618         $title = "copy hidden field to clipboard";
    619 
    620         if ( $id > 0 ) {
    621             $text = $this->getHiddenFieldTemplate( $id );
    622             return $this->getCopy2CBIcon(  $text , $title );
    623         } else {
    624             return $this->getCopy2CBAlert( "Please generate the enhanced QR-Code image before copying the hidden field to clipboard.", $title );
    625         }
    626     }
    627 
    628     public function getCopyApiRoot2CBIcon() {
    629         $title = "copy URL for MyFast App to clipboard";
    630         return $this->getCopy2CBIcon(  $this->getApiUrl(), $title );
    631433    }
    632434
     
    654456        $anyDevice = $this->config->anyDeviceEnabled->value;
    655457
    656         $isMobile = SRC\Mobile::is();
     458        $isMobile = SOS\Mobile::is();
    657459        $deviceEnabled = $isMobile || $anyDevice; //it's mobile OR any device
    658460
    659         $isMobileBrowser = SRC\Mobile::isBrowser();
     461        $isMobileBrowser = SOS\Mobile::isBrowser();
    660462        if ( $isMFApp ) {
    661463            $insertLog = !$this->config->logDisabled->value;
     
    664466        }
    665467
     468        if ( $insertLog ) {
     469            $log['dev_type'] = $isMobile ? SRC\DeviceType::MOBILE : SRC\DeviceType::NOT_MOBILE;
     470            if ( $this->config->geoEnabled->value && $this->hasGeo() ) {
     471                $key = $this->config->geoKey->value;
     472                $geo = $this->addon::getGeo($key);
     473                if ( is_array($geo) ) {
     474                    $log['country'] = $geo['country'];
     475                    $log['region'] = $geo['region'];
     476                    $log['city'] = $geo['city'];
     477                }
     478            }
     479            $langs = SRC\HTTP::getLanguages();
     480            if ( is_array($langs) && count($langs) > 0 ) {
     481                $log['lang'] = $langs[0];
     482            }
     483            if ( !$this->isPro ) {
     484                $log['op_sys'] = SRC\OS::UNKNOWN;
     485            } else {
     486                $log['op_sys'] = $this->addon::getOS();
     487            }
     488        }
     489
    666490        $isCypher = false;
    667491        $otkey = false;
    668492
    669493        $method = $request->get_method();
    670         if ( $method == 'GET' && $deviceEnabled ) {
     494        if ( $method == 'GET' ) { // && $deviceEnabled
    671495            $qs = $request->get_query_params();
    672496            if ( array_key_exists('qr', $qs) ) {
     
    722546                for ( $n=0; $n<count($items); $n++ ) {
    723547                    $item = &$items[$n];
     548                    $item->browser = $isMobileBrowser || !$isMobile; //dynamically added
    724549                    if ( $item->only_mfa && !$isMFApp ) {
    725550                        $status = SRC\QrCodeStatus::DISABLED;
     
    727552                        $status = SRC\QrCode::getStatus( $item );
    728553                    }
    729                     $item->status = $status;
     554                    $item->status = $status; //dynamically added
    730555                    if ( $status == SRC\QrCodeStatus::ACTIVE ) {
    731556                        if ( $item->priority ) {
     
    772597                $log['qrcode_id'] = $qrcode->qrcode_id;
    773598
     599                if ( !$deviceEnabled ) {
     600                    $qrcode->status = SRC\QrCodeStatus::DISABLED;
     601                }
     602
    774603                $log['status'] = $qrcode->status;
    775604
    776                 if ( $isCypher || $this->config->anyQrHideEnabled->value ) {
     605                if ( $deviceEnabled && ( $isCypher || $this->config->anyQrHideEnabled->value ) ) {
    777606                    $otkey = SRC\OTKey::getNew();
    778607                    $otdata = [
     
    812641                ,'Event-Id' => $qr_event_id
    813642                ,'User-Key' => $log['user_key'] ?? ''
    814                 ,'cookie' => $otkey !== false ? $otkey : 'false'
    815             ], "API Redirect Parameters: " ); // note: it works if WP_DEBUG_LOG is true
    816 
     643                ,'Cookie' => $otkey !== false ? $otkey : 'false'
     644            ], "API Redirect Parameters: " ); // note: it works if WP_DEBUG_LOG constant is true
     645
     646        $url = $this->getRedirectUrl($url);
    817647        if ( $url != '' ) {
    818             $url = $this->getRedirectUrl( $url );
    819648
    820649            if ( $insertLog ) {
     
    824653            }
    825654
    826             wp_redirect( $url, 302, 'Dynamic QR Code by SOSidee.com' );
    827 
    828         } else {
    829             return new \WP_REST_Response( "Server response: a problem occurred. Please check the Smart QR Code plugin configuration.", 500);
     655            wp_redirect( $url, 302, 'Dynamic QR Code plugin' );
     656
     657        } else {
     658            sosidee_log('Plugin.apiRedirectByCode(): redirect URL is empty.');
     659            return new \WP_REST_Response( "Server response: a problem occurred. Please check the Dynamic QR Code plugin configuration.", 500);
    830660        }
    831661        exit();
     
    833663
    834664    private function getRedirectUrl( $path ) {
    835         $ret = $path;
    836         if ( !sosidee_str_starts_with($ret, ['https://', 'http://', '//']) ) {
    837             if ( !sosidee_str_starts_with($ret, '/') ) {
    838                 $ret = '/' . $ret;
    839             }
    840             $ret = get_site_url() . $ret;
    841         }
    842         if ( $this->config->randQsEnabled->value ) {
    843             $key = 'sos' . strval( random_int(6, 666) );
    844             $value = base64_encode( bin2hex( random_bytes(12) ) );
    845             $ret = add_query_arg( $key, $value, $ret );
     665        $ret = '';
     666        /** @noinspection HttpUrlsUsage */
     667        if ( $path != '' && !sosidee_str_starts_with($path, ['https://', 'http://', '//']) ) {
     668
     669            if ( $this->hasSocial() ) {
     670                if ( $this->hasFacebook() && $this->addon->facebook::is( $path ) ) {
     671                    $url = $this->addon->facebook::getUrl($path);
     672                    if ($url !== false) {
     673                        $ret = $url;
     674                    } else {
     675                        sosidee_log("Addon\Facebook.getUrl() returned false for path: $path");
     676                    }
     677                } else if ( $this->hasInstagram() && $this->addon->instagram::is( $path ) ) {
     678                    $url = $this->addon->instagram::getUrl($path);
     679                    if ($url !== false) {
     680                        $ret = $url;
     681                    } else {
     682                        sosidee_log("Addon\Instagram.getUrl() returned false for path: $path");
     683                    }
     684                } else if ( $this->hasLinkedIn() && $this->addon->linkedin::is( $path ) ) {
     685                    $url = $this->addon->linkedin::getUrl($path);
     686                    if ($url !== false) {
     687                        $ret = $url;
     688                    } else {
     689                        sosidee_log("Addon\LinkedIn.getUrl() returned false for path: $path");
     690                    }
     691                } else if ( $this->hasWhatsApp() && $this->addon->whatsapp::is( $path ) ) {
     692                    $url = $this->addon->whatsapp::getUrl($path);
     693                    if ($url !== false) {
     694                        $ret = $url;
     695                    } else {
     696                        sosidee_log("Addon\WhatsApp.getUrl() returned false for path: $path");
     697                    }
     698                } else if ( $this->hasYouTube() && $this->addon->youtube::is( $path ) ) {
     699                    $url = $this->addon->youtube::getUrl($path);
     700                    if ($url !== false) {
     701                        $ret = $url;
     702                    } else {
     703                        sosidee_log("Addon\YouTube.getUrl() returned false for path: $path");
     704                    }
     705                } else {
     706                    $ret = $path;
     707                }
     708            } else {
     709                if ( !sosidee_str_starts_with($path, '/') ) {
     710                    $path = '/' . $path;
     711                }
     712                $ret = get_site_url() . $path;
     713            }
     714        } else {
     715            $ret = $path;
     716        }
     717
     718        if ( sosidee_str_starts_with($ret, ['https://', 'http://', '//']) ) {
     719            $this->config->randQsEnabled->load();
     720            if ( $this->config->randQsEnabled->value ) {
     721                $key = 'sos' . strval( random_int(6, 666) );
     722                $value = base64_encode( bin2hex( random_bytes(12) ) );
     723                $ret = add_query_arg( $key, $value, $ret );
     724            }
    846725        }
    847726        return $ret;
     
    849728
    850729    private function deleteFiles( $folder ) {
    851         foreach ( glob($folder) as $file ) {
    852             if ( is_file($file) ) {
    853                 unlink($file);
    854             }
    855         }
    856     }
     730        try {
     731            foreach ( glob($folder) as $file ) {
     732                if ( is_file($file) ) {
     733                    unlink($file);
     734                }
     735            }
     736        } catch ( \Exception $ex ) {
     737            sosidee_log( $ex->getMessage() );
     738        }
     739    }
     740
    857741    public function onDeactivate() {
    858742        $tmp = $this->getTempFolder();
    859         if ( is_array($tmp) && key_exists('basedir', $tmp) ) {
    860             $this->deleteFiles( $tmp['basedir'] . '/*.png' );
    861             $this->deleteFiles( $tmp['basedir'] . '/*.csv' );
    862         }
    863     }
    864 
    865     public function help( $path = '', $style = 'margin: 0.5em; float: right;' ) {
    866         $url = self::$helpUrl . $path;
    867         $ret = '<a href="' . esc_url($url) . '" onclick="this.blur();" target="_blank" title="help"><i class="material-icons"';
     743        if ( $tmp !== false ) {
     744            $this->deleteFiles( $tmp['path'] . '*.png' );
     745            $this->deleteFiles( $tmp['path'] . '*.csv' );
     746        }
     747    }
     748
     749    public function pro( $style = null, $title = 'PRO version' ) {
     750        $url = self::$helpUrl . 'pro-version';
     751        $ret = '<a href="' . esc_url($url) . '" onclick="this.blur();" target="_blank" title="' . esc_attr($title) . '"><i class="dashicons-before dashicons-awards"';
     752        $style = SOS\WP\HtmlTag::getStyle($style, 'color: #ff0000;');
    868753        if ( !is_null($style) ) {
    869             $color = 'color: #ffcc00;';
    870             if ( $style != '' ) {
    871                 $style = $color . ' ' . $style;
    872             } else {
    873                 $style = $color;
    874             }
    875754            $ret .= ' style="' . esc_attr($style) . '"';
    876755        }
    877         $ret .= '>help</i></a>';
     756        $ret .= '></i></a>';
    878757        return $ret;
     758    }
     759
     760    public function htmlAdminPageTitle( $title ) {
     761        echo '<h1>' . esc_html( $title );
     762        if ( $this->hasAnyAddon() ) {
     763            echo ' <sup><i class="dashicons-before dashicons-awards" style="font-size: 100%;" title="pro version"></i></sup>';
     764        }
     765        echo '</h1>';
    879766    }
    880767
     
    887774$plugin = SosPlugin::instance(); //the class must be the one defined in this file
    888775$plugin->run();
    889 
    890 
    891 // this is the end (A B C)
  • dynamic-qr-code/trunk/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/readme.txt

    r3075156 r3213836  
    22Plugin Name: Dynamic QR Code
    33Contributors: sosidee
    4 Tags: qr code, dynamic qr code, dynamic qr code generator
    5 Requires at least: 5.3.0
    6 Tested up to: 6.5.2
     4Tags: qr code, qr code generator, dynamic qr code, dynamic qr code generator
     5Requires at least: 5.9.0
     6Tested up to: 6.7
    77Stable tag: 0.9.3
    8 Requires PHP: 7.4
     8Requires PHP: 8.0
    99License: GPLv3
    1010License URI: https://www.gnu.org/licenses/gpl-3.0.html
     
    1717
    1818A *dynamic* QR code?
    19 Yes, the core idea is that *information* associated with the QR code is handled by the plugin and not encoded inside the QR code itself: that's, in short, the essence of *dynamic* QR codes.
    20 
    21 In other words, **Dynamic QR Code** permits to change the information encoded in a QR code **without having to modify** the QR code itself.
    22 Furthermore, the QR code scans are tracked and available for statistical analysis.
    23 
    24 Let's be plain with few simple examples:
    25 > SCENARIO: you want to store in a QR code the web page of the pharmacy in duty.
    26 > PROBLEM: the pharmacy changes at every shift, and you can't (or don't want to) rebuild and reprint the QR code every time.
    27 > SOLUTION: Dynamic QR Code lets you change the pharmacy web page URL without modifying the QR code.
     19Yes, the core idea is that *information* associated with the QR code is managed by the plugin rather than being encoded directly within the QR code itself: this is, in essence, the definition of a *dynamic* QR code.
     20
     21In other words, **Dynamic QR Code** allows you to change the information linked to a QR code **without having to alter** the QR code itself.
     22Additionally, scans of the QR codes are tracked and available for statistical analysis.
     23
     24Let's be straightforward with a few simple examples:
     25> SCENARIO: you want to store the web page of the pharmacy in duty in a QR code.
     26> PROBLEM: the pharmacy changes with each shift, and you can't (or don't want to) rebuild and reprint the QR code every time.
     27> SOLUTION: Dynamic QR Code allows you to change the pharmacy webpage URL without modifying the QR code itself.
    2828>
    29 > SCENARIO: you want people will be redirected to your current promotion web page after scanning the QR codes that you distributed to your resellers.
    30 > PROBLEM: the page URL changes quite often for some reason (e.g. you want to promote different products without having to modify the very same web page continuously) but you don't want to waist your time in rebuilding, reprinting and resending QR codes to your resellers.
    31 > SOLUTION: Dynamic QR Code lets you change the redirect URL to your current promotion page without modifying the QR code.
     29> SCENARIO: you want customers to be redirected to your current promotion webpage after scanning the QR codes you distributed to your resellers.
     30> PROBLEM: the page URL changes frequently for various reason (e.g. you want to promote different products without continuously modifying the same webpage) but you don't want to waste time rebuilding, reprinting and resending QR codes to your resellers.
     31> SOLUTION: Dynamic QR Code permits you to change the redirect URL to your current promotion page without modifying the QR code image.
    3232>
    33 > SCENARIO: you want to track the scans of your QR code to analyze data and get statistical information.
     33> SCENARIO: you want to track the scans of your QR code to analyze data and gather statistical information.
    3434> PROBLEM: there's no easy way to track the activity of people who scan static QR codes.
    35 > SOLUTION: Dynamic QR Code automatically tracks the scans and let you download the data for statistical analysis.
     35> SOLUTION: Dynamic QR Code automatically tracks the scans and lets you download the data for statistical analysis.
    3636>
    37 > SCENARIO: you want your customers to scan a QR code to view the menu of your restaurant.
    38 > PROBLEM: the menu changes every day of the week, so 7 different QR codes would be necessary to cover the week.
    39 > SOLUTION: Dynamic QR Code generates a single QR code that redirects your customers depending on the day of the week.
    40 
    41 ### Kinds of scenario for dynamic QR codes ###
    42 
    43 * You need a QR code with a link that can be modified without having to change the QR code.
    44 * You need to know how many times your QR code has been scanned.
     37> SCENARIO: you want your customers to scan a QR code to view your restaurant's menu.
     38> PROBLEM: the menu changes every day of the week, so you would need 7 different QR codes would to cover the entire week.
     39> SOLUTION: Dynamic QR Code generates a single QR code that redirects your customers to the appropriate menu depending on the day of the week.
     40
     41### Types of scenarios for dynamic QR codes ###
     42
     43* You need a QR code with a link that can be modified without changing the QR code image.
     44* You need to track how many times your QR code has been scanned.
    4545* You need a QR code that redirects users to different URLs depending on the date or on the day of the week.
    46 * You need a web page that can be viewed only by scanning a QR code.
     46* You need a webpage that can only be accessed by scanning a QR code.
    4747* You need a QR code that can be scanned a limited number of times.
     48* You need a QR code that opens a Facebook/Instagram/LinkedIn profile directly in the Facebook/Instagram/LinkedIn app (PRO feature).
    4849
    4950Examples:
    5051
    51 * You want to track when customers open your products: *print on them a dynamic QR code for something appealing for the customers (e.g. a giveaway lottery, a discount coupon, etc.) and get the statistics.*
    52 * You want to provide additional product information through videos that can change from time to time: *use a dynamic QR code that redirects to the current video.*
    53 * You want to measure your customers' engagement in your physical stores: *with dynamic QR codes you can track the users' activity.*
    54 * You want to measure your marketing campaigns in the physical world: *dynamic QR codes make you be able to perform it.*
    55 * You want to give information on your weekly program: *use a dynamic QR code to show the program of the current day.*
     52* You want to track when customers open your products: *print on them a dynamic QR code for something appealing for to customers (e.g. a giveaway lottery, a discount coupon, etc.) and gather the statistics.*
     53* You want to provide additional product information through videos that can change over time: *use a dynamic QR code that redirects to the current video.*
     54* You want to measure customer engagement in your physical stores: *dynamic QR codes allow you to track the user activity.*
     55* You want to measure  the effectiveness of your marketing campaigns in the physical world: *dynamic QR codes enable you be able to do so.*
     56* You want to provide information about your weekly program: *use a dynamic QR code to show the schedule for the current day.*
    5657* You want to display a prize voucher only to people that enter in your shop(s) and scan a QR code.
    57 
    58 See the <a href="https://redirect.soslink.net/dynamic-qr-code/help/scenarios" target="_blank" title="tutorial">online manual</a> for details.
     58* You want to open a YouTube video directly in the YouTube app (PRO feature).
     59
     60See the <a href="https://support.sosidee.com/dynamic-qr-code/general-concepts/" target="_blank" title="tutorial">online manual</a> for details.
    5961
    6062### GETTING STARTED ###
     
    7173Then use the *QR-URL* generated by the plugin to create the image of your QR code, or just download the image generated in the plugin page.
    7274
    73 &raquo; Check the <a href="https://redirect.soslink.net/dynamic-qr-code/help/" target="_blank" title="tutorial">online manual</a> for details &laquo;
     75&raquo; Check the <a href="https://support.sosidee.com/dynamic-qr-code/" target="_blank" title="tutorial">online manual</a> for details &laquo;
    7476
    7577**Note**
    76 If you need to create QR-Codes with the same key, you have to activate the 'Disable unique keys' check box in the Settings page: in this case, identical keys will generate identical qr code images and the redirect URL will be chosen randomly or on the base of the conditions set in the QR-Code.
     78If you need to create QR-Codes with the same key, you have to activate the 'Disable unique keys' option on the Settings page: in this case, identical keys will generate identical qr code images and the redirect URL will be chosen either randomly or based on the conditions set in the QR-Code.
    7779
    7880**RANDOM REDIRECT**
    79 If you want users randomly redirected to a URL chosen among some:
    80 
    81 - activate the 'Disable unique keys' check box in the Settings page
    82 - create two or more QR-Codes with the same key and different URLs
    83 
    84 Users will be redirected to a URL randomly drawn among the available ones (i.e. among the URLs of the valid QR-Codes with the same key of the scanned one).
    85 
    86 *Please note that the drawn procedure of URLs uses a pseudo-random generation of numbers. Therefore, do not use this feature to create true lotteries or gambling games.*
    87 
    88 **DATE DEPENDENT REDIRECT**
    89 If you want users redirected to different URLs depending on the date:
    90 
    91 - activate the 'Disable unique keys' check box in the Settings page
     81If you want users to be randomly redirected to a URL chosen from several options:
     82
     83- activate the 'Disable unique keys' checkbox in the Settings page
     84- create two or more QR-Codes with the same key but different URLs
     85
     86Users will be redirected to a URL randomly selected from the available ones (i.e. among the URLs of the valid QR-Codes that share the same key as the one scanned).
     87
     88*Please note that the URL selection process uses a pseudo-random number generation. Therefore, do not use this feature for true lotteries or gambling games.*
     89
     90**DATE-DEPENDENT REDIRECT**
     91If you want users to be redirected to different URLs depending on the date:
     92
     93- activate the 'Disable unique keys' checkbox on the Settings page
    9294- create two or more QR-Codes with
    9395    - the same key
    94     - different date interval of validity
    95     - different URL
    96 
    97 The URL users will be redirected to will depend on which QR-Code will be valid at the scan date.
    98 
    99 **DAY OF THE WEEK DEPENDENT REDIRECT**
    100 If you want users redirected to different URLs depending on the day of the week:
    101 
    102 - activate the 'Disable unique keys' check box in the Settings page
     96    - different date intervals of validity
     97    - different URLs
     98
     99The URL users are redirected to will depend on which QR-Code is valid on the scan date.
     100
     101**DAY-OF-THE-WEEK DEPENDENT REDIRECT**
     102If you want users to be redirected to different URLs depending on the day of the week:
     103
     104- activate the 'Disable unique keys' checkbox on the Settings page
    103105- create 7 QR-Codes with
    104106    - the same key
    105107    - different redirect URLs
    106 - assign each QR-Code to a different day of the week
    107 
    108 **EXCEPTION DATE FOR A DAY OF THE WEEK DEPENDENT REDIRECT**
    109 Let's say you want your users redirected on Easter differently respect on the usual URL for Sunday:
    110 
    111 - activate the 'Disable unique keys' check box in the Settings page
    112 - create a QR-Code that redirects to URL1 and assign it to Sunday (this will be the usual redirect)
     108- assign each QR-Code to a specific day of the week
     109
     110**EXCEPTION DATE FOR A DAY-OF-THE-WEEK DEPENDENT REDIRECT**
     111Let's say you want your users to be redirected on Easter differently compared to the usual Sunday URL:
     112
     113- follow the DAY-OF-THE-WEEK DEPENDENT REDIRECT instructions to create 7 QR-Codes
    113114- then create another QR-Code with
    114115    - the same key
    115     - redirect set to URL2 (i.e. different from URL1)
    116     - activation date set on the date of Easter
    117     - priority checkbox activated
    118 
    119 Users will be redirected to URL1 on every Sunday but on Easter, when they'll be redirected to URL2.
    120 
    121 &raquo; Check the <a href="https://redirect.soslink.net/dynamic-qr-code/help/" target="_blank" title="tutorial">online manual</a> for more scenarios &laquo;
     116    - the redirect URL set to the URL for Easter
     117    - the activation date set to the date of Easter
     118    - the priority checkbox activated
     119
     120If *https://mydomain.com/sunday* is the URL for Sunday and *https://mydomain.com/easter* is the URL for Easter, users will be redirected to *https://mydomain.com/sunday* on every Sunday except on Easter, when they'll be redirected to *https://mydomain.com/easter*.
     121
     122&raquo; Check the <a href="https://support.sosidee.com/dynamic-qr-code/" target="_blank" title="tutorial">online manual</a> for more scenarios &laquo;
    122123
    123124**My FastAPP**
     
    129130
    130131- encoded information cannot be modified
    131 - scans track procedures are all but straightforward
     132- tracking scan activity is complicated and often not straightforward
    132133
    133134DYNAMIC QR CODE
    134135
    135136- embedded information can be changed
    136 - scans can be easily tracked
     137- scans can be easily tracked and then analyzed
    137138
    138139### Statistics ###
    139140
    140141QR code scans are logged and available for statistical analysis.
    141 
    142 Enabling the *My FastAPP options* (from the *Settings* menu item), it's possible to distinguish the activity of the various users by the *User Key* values.
     142Some basic statistics, available as PRO add-ons, include scan distributions grouped by date, day, device type, country, and more.
     143
     144By enabling the *My FastAPP options* (available under the *Settings* menu), you can differentiate user activity using *User Key* values.
    143145
    144146== Screenshots ==
     
    152154
    153155Yes, Dynamic QR Code generates the image of your QR code.
    154 Nevertheless, you can use an equivalent image created by any third party tool.
     156However, you can also use an equivalent image created by any third-party tool.
     157
     158= How many dynamic QR codes can I generate ? =
     159
     160As many as you wish (and as many as your WordPress site can handle).
     161
     162= What is a dynamic QR code ? =
     163
     164In short, it's a simple QR code with a redirection URL encoded in it.
     165This means that the information (the data read scanning the QR code) is stored outside the QR code.
     166With Dynamic QR Code this information is stored in your WordPress website, allowing you to change it whenever you wish.
     167
     168= What is a static QR code ? =
     169
     170A QR code is defined as *static* when the information associated with it is embedded directly in its code. Most QR codes are static.
     171
     172= Do QR codes expire ? =
     173
     174A *static* QR code can expire if the information encoded in it's' no longer valid, requiring you to rebuild and reprint it.
     175A *dynamic* QR code can expire in the same way, but (and that's the significant difference) it can be brought back to life simply updating the information stored online.
     176
     177= Can I use a QR code image generated by another tool? =
     178
     179Yes, as long as the image encodes the correct QR-URL.
    155180
    156181= Is this plugin a free QR code generator ? =
     
    158183Yes, Dynamic QR Code is free.
    159184
    160 = How many dynamic QR codes can I generate ? =
    161 
    162 As many as you wish (and your WP site handles).
    163 
    164 = What is a dynamic QR code ? =
    165 
    166 Shortly, it's a simple QR code with a redirection URL encoded in it.
    167 That means that the information (the data read scanning the QR code) is located outside the QR code.
    168 With Dynamic QR Code this information is memorized in your WordPress website, with the huge advantage that you can change it whenever you wish.
    169 
    170 = What is a static QR code ? =
    171 
    172 A QR code is defined *static* when the information associated with it is embedded in its code. Most QR codes are static.
    173 
    174 = Do dynamic QR codes expire ? =
    175 
    176 A *static* QR code can expire because the information you encoded in it may no longer be valid, so you need to rebuild and reprint it.
    177 A *dynamic* QR code can expire in the same way, but (and that's the huge difference) it can be brought back to life simply updating the information stored online.
    178 
    179 = Can I use a QR code image generated by another tool? =
    180 
    181 Yes, as long as you encode in the image the correct QR-URL.
     185= Is there a PRO version? =
     186
     187Yes, absolutely! You can find all the information about the PRO version and how to purchase it at this URL: [https://sosplugin.com/dynamic-qr-code/](https://sosplugin.com/dynamic-qr-code/)
    182188
    183189== Upgrade Notice ==
    184 It seems this section is not used anymore.
     190This is a major upgrade. Please ensure you back up your site before updating.
    185191
    186192== Changelog ==
     193
     194= 1.0.0 =
     195* Code refactored to ensure compatibility with add-ons provided by the Pro License Manager plugin.
     196* Improved integration with Pro License Manager to support additional features.
     197* Minor bug fixes and performance improvements.
    187198
    188199= 0.9.3 =
  • dynamic-qr-code/trunk/sos/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/api/endpoint.php

    r2815343 r3213836  
    1515    private $route;
    1616
    17     public $localized;
    1817    private $configName;
    1918    private $configData;
    2019
     20    public $localized;
    2121    public $nonceDisabled;
    2222
  • dynamic-qr-code/trunk/sos/wp/api/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/assets/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/assets/sosApi.js

    r2815343 r3213836  
    1 function sosAjaxReqConf(config)
    2 {
     1function sosAjaxReqConf(config) {
    32    let ret = {
    43         url: config.url
  • dynamic-qr-code/trunk/sos/wp/be/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/be/menu.php

    r2779336 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\BE;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    99class Menu
    1010{
    11     use SOS_WP\Property {
    12         SOS_WP\Property::__set as __setProp;
     11    use SOS_WP\TProperty {
     12        SOS_WP\TProperty::__set as __setProp;
    1313    }
    14     use SOS_WP\Translation;
     14    use SOS_WP\TTranslation;
     15    use SOS_WP\TBase;
    1516
    1617    public $name;
     
    2425        $this->_addProperty('icon', '');
    2526
    26         $this->name = '';
     27        $this->name = $name;
    2728        $this->slug = '';
    2829        $this->color = false;
    2930
    3031        $this->pages = array();
    31         $this->name = $name;
    3232    }
    3333
    34     public function __set($name, $value) {
    35         switch ($name) {
     34    public function __set( $name, $value ) {
     35        switch ( $name ) {
    3636            case 'icon':
    37                 if ( sosidee_str_starts_with($value, '-') == true ) {
     37                if ( sosidee_str_starts_with($value, '-') === true ) {
    3838                    $value = 'dashicons' . $value;
    3939                }
     
    5252     * @return Menu object
    5353     */
    54     public function add($page, $title = '', $role = null) {
     54    public function add( $page, $title = '', $role = null ) {
    5555        if (count($this->pages) == 0) {
    5656            $this->slug = $page->key; //set the menu base slug
    5757        }
    58         if ($page->title == '') {
     58        if ( $page->title == '' ) {
    5959            $page->title = $title;
    6060        }
     
    7070     * Adds a menu item without displaying it
    7171     */
    72     public function addHidden($page, $title = '', $role = null) {
     72    /*
     73    public function addHidden( $page, $title = '', $role = null ) {
    7374        $page->menuType = MenuType::HIDDEN;
    7475        return $this->add($page, $title, $role);
    7576    }
     77    */
    7678
    7779    /**
    7880     * Adds an item to the 'Tools' menu
    7981     */
    80     public function addTool($page, $title = '', $role = null) {
     82    public function addTool( $page, $title = '', $role = null ) {
    8183        $page->menuType = MenuType::TOOLS;
    8284        return $this->add($page, $title, $role);
     
    8688     * Adds an item to the 'Settings' menu
    8789     */
    88     public function addSetting($page, $title = '', $role = null) {
     90    public function addSetting( $page, $title = '', $role = null ) {
    8991        $page->menuType = MenuType::SETTINGS;
    9092        return $this->add($page, $title, $role);
     
    9395    public function initialize() {
    9496
    95         for ($n=0; $n<count($this->pages); $n++) {
     97        if ( self::plugin()->isPro ) {
     98            $this->name .= ' PRO';
     99            $this->icon = '-awards';
     100        }
     101
     102        for ( $n=0; $n<count($this->pages); $n++ ) {
    96103            $page = $this->pages[$n];
    97104            $file = $page->path;
     
    105112                $title = $page->key;
    106113            }
    107             if ( $page->menuColor !== false) {
     114            if ( $page->menuColor !== false ) {
    108115                $title = "<span style='color:{$page->menuColor};'>" . $title . '</span>';
    109116            }
    110117
    111             if ($page->menuType == MenuType::TOOLS) {
     118            if ( $page->menuHidden ) {
     119                $title = '';
     120            }
     121
     122            if ( $page->menuType == MenuType::TOOLS ) {
    112123                $page->hook = add_management_page( $this->name, $title, $page->role, $page->key, $callback );
    113             }
    114             else if ($page->menuType == MenuType::SETTINGS) {
     124            } else if ( $page->menuType == MenuType::SETTINGS ) {
    115125                $page->hook = add_options_page( $this->name, $title, $page->role, $page->key, $callback );
    116126            } else {
    117                 $root = ($page->menuType != MenuType::HIDDEN) ? $this->slug : null;
    118                 if ($n == 0) {
     127                if ( $n == 0 ) {
    119128                    $item = $this->name;
    120129                    if ($this->color !== false) {
     
    122131                    }
    123132                    add_menu_page( $this->name, $item, $page->role, $this->slug, $callback , $this->icon);
    124                     $page->hook = add_submenu_page( $root, $this->name, $title, $page->role, $this->slug, $callback );
     133                    $page->hook = add_submenu_page( $this->slug, $this->name, $title, $page->role, $this->slug, $callback );
    125134                } else {
    126                     $page->hook = add_submenu_page( $root, $this->name, $title, $page->role, $page->key, $callback );
     135                    $page->hook = add_submenu_page( $this->slug, $this->name, $title, $page->role, $page->key, $callback );
    127136                }
    128137            }
    129138        }
    130139    }
    131    
     140
    132141}
  • dynamic-qr-code/trunk/sos/wp/be/menutype.php

    r2684394 r3213836  
    55class MenuType
    66{
    7     const HIDDEN = -1;
     7    //const HIDDEN = -1;
    88    const CUSTOM = 0;
    99    const TOOLS = 1;
  • dynamic-qr-code/trunk/sos/wp/be/page.php

    r2779336 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\BE;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    1717class Page
    1818{
    19     use SOS_WP\Property {
    20         SOS_WP\Property::__set as __setProp;
     19    use SOS_WP\TProperty {
     20        SOS_WP\TProperty::__set as __setProp;
    2121    }
    22     use SOS_WP\Translation;
     22    use SOS_WP\TTranslation;
    2323
    2424    private static $screen = null;
     
    3232    public $menuColor;
    3333    public $hook;
     34    public $menuHidden;
    3435
    3536    public function __construct($path, $name) {
     
    3940        $this->key = '';
    4041        $this->url = '';
    41         $this->name = '';
    4242        $this->role = 'manage_options';
    4343        $this->title = '';
    4444        $this->menuType = MenuType::CUSTOM;
    4545        $this->menuColor = false;
     46        $this->menuHidden = false;
    4647        $this->hook = false;
    4748
    48         if ($name == '') {
     49        if ( $name == '' ) {
    4950            $name = sosidee_str_remove('.php', basename( $path) );
    5051        }
  • dynamic-qr-code/trunk/sos/wp/cookie.php

    r2815343 r3213836  
    3535    private static $DOMAINS = [];
    3636
     37    /** @noinspection HttpUrlsUsage */
    3738    public static function getDomain() {
    3839        if ( empty(self::$domain) ) {
    39             self::$domain = strrev( strtolower( esc_url_raw($_SERVER['HTTP_HOST'])) );
     40            $url = isset($_SERVER['HTTP_HOST']) ? strtolower( esc_url_raw($_SERVER['HTTP_HOST']) ) : '';
     41            if ( sosidee_str_starts_with($url, 'https://') ) {
     42                $url = substr($url, strlen('https://'));
     43            } else if ( sosidee_str_starts_with($url, 'http://') ) {
     44                $url = substr($url, strlen('http://'));
     45            }
     46            self::$domain = strrev( $url );
    4047            if ( count(self::$DOMAINS) == 0 ) {
    4148                self::loadDomains();
  • dynamic-qr-code/trunk/sos/wp/data/cluster.php

    r2779336 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    1010class Cluster
    1111{
    12     use SOS_WP\Property {
    13         SOS_WP\Property::__set as __setProp;
     12    use SOS_WP\TProperty {
     13        SOS_WP\TProperty::__set as __setProp;
    1414    }
    15     use SOS_WP\Translation;
     15    use SOS_WP\TTranslation;
    1616
    1717    protected static $plugin = null;
     
    112112     * Assignes an admin page to the data cluster (or, if you prefer, assignes a data cluster to an admin page)
    113113     *
    114      * @param string | BE\Page $page : ID of the page or the page itself
     114     * @param string | SOS_WP\BE\Page $page : ID of the page or the page itself
    115115     *
    116116     */
  • dynamic-qr-code/trunk/sos/wp/data/field.php

    r2815343 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    1010class Field
    1111{
    12     use SOS_WP\Property
     12    use SOS_WP\TProperty
    1313    {
    14         SOS_WP\Property::__get as __getProp;
    15         SOS_WP\Property::__set as __setProp;
    16     }
    17     use SOS_WP\Translation;
    18     use Encryption;
    19 
    20     private $loaded;
     14        SOS_WP\TProperty::__get as __getProp;
     15        SOS_WP\TProperty::__set as __setProp;
     16    }
     17    use SOS_WP\TTranslation;
     18    use TEncryption;
     19
     20    public $loaded;
    2121    public $encrypted;
    2222
     
    393393     */
    394394    public function callback( $input ) {
     395        $ret = $input;
    395396        if ( !is_null($this->validate) ) {
    396397            if ( !$this->handled ) {
     
    398399                $result = call_user_func( $this->validate, $this->parent->key, array($this->key => $input) );
    399400                if ( is_array($result) ) {
    400                     $ret = array_values($result)[0];
     401                    if ( !empty($result) ) {
     402                        $values = array_values($result);
     403                        if ( isset($values[0]) ) {
     404                            $ret = $values[0];
     405                        } else {
     406                            $ret = null;
     407                        }
     408                    } else {
     409                        $ret = null;
     410                    }
    401411                } else {
    402412                    $ret = $result;
    403413                }
    404                 if ( !$this->encrypted ) {
    405                     return $ret;
    406                 } else {
    407                     return $this->encrypt( $ret );
    408                 }
    409             } else {
    410                 return $input;
    411             }
    412         }
     414                if ( $this->encrypted && !is_null($ret) ) {
     415                    $ret = $this->encrypt( $ret );
     416                }
     417            }
     418        }
     419        return $ret;
    413420    }
    414421   
  • dynamic-qr-code/trunk/sos/wp/data/form.php

    r2815343 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
    44
    55defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
     
    77class Form
    88{
    9     use SOS_WP\Message;
    10     use SOS_WP\Translation;
     9    use SOS_WP\TBase;
     10    use SOS_WP\TMessage;
     11    use SOS_WP\TTranslation;
    1112
    1213    private $_nonce_name;
    1314    private $_nonce_action;
    1415    private $_actions;
    15 
    16     protected $_plugin;
    1716
    1817    public $_name;
     
    5049        }
    5150
    52         $this->_plugin = \SOSIDEE_DYNAMIC_QRCODE\SosPlugin::instance();
    53 
    5451    }
    5552
     
    5855        $ret = new FormField( $type, $id, $value );
    5956        $ret->name = $name;
    60         //$this->{$name} = $ret; not necessary (why?)
     57        //$this->{$name} = $ret; not necessary (but don't remember why)
    6158        $this->_fields[] = $ret;
    6259        return $ret;
     
    9188        return $this->addField( FormFieldType::CHECK, $name, $value );
    9289    }
     90    public function addRadio( $name, $value = false ) {
     91        return $this->addField( FormFieldType::RADIO, $name, $value );
     92    }
    9393    public function addSelect( $name, $value = 0 ) {
    9494        return $this->addField( FormFieldType::SELECT, $name, $value );
     
    100100        $this->_encType = 'multipart/form-data';
    101101        return $this->addField( FormFieldType::FILE, $name, null );
     102    }
     103    public function addCheckList( $name, $value = [] ) {
     104        return $this->addField( FormFieldType::CHECKLIST, $name, $value );
    102105    }
    103106
     
    161164    protected function isCached() {
    162165        $ret = false;
    163         for ($n=0; $n<count($this->_fields); $n++) {
     166        for ( $n=0; $n<count($this->_fields); $n++ ) {
    164167            if ($this->_fields[$n]->cached) {
    165168                $ret = true;
     
    187190        if ( !$continue ) {
    188191            for ( $n=0; $n<count($this->_pages); $n++ ) {
    189                 if ( $this->_pages[$n]->isCurrent() ) {
    190                     $continue = true;
    191                     break;
     192                $page = $this->_pages[$n];
     193                if ( $page instanceof \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\BE\Page ) {
     194                    if ( $this->_pages[$n]->isCurrent() ) {
     195                        $continue = true;
     196                        break;
     197                    }
     198                } else {
     199                    if ( !is_string($page) ) {
     200                        $page = print_r($page, true);
     201                    }
     202                    sosidee_log("Form.sanitize(): uninstantiated page ('{$page}'). Maybe it was not added to menu.");
    192203                }
    193204            }
     
    222233                        case FormFieldType::CHECK:
    223234                            $field->value = isset( $_POST[$field->name] );
     235                            break;
     236                        case FormFieldType::CHECKLIST:
     237                            $values = sanitize_text_field( $_POST[$field->name] );
     238                            if ( !empty($values) ) {
     239                                $field->value = explode(';', $values);
     240                            } else {
     241                                $field->value = [];
     242                            }
    224243                            break;
    225244                        default:
     
    276295    public function htmlClose() {
    277296        echo sosidee_kses( $this->getClose() );
    278 ;    }
     297    }
    279298
    280299    public function addToPage() {
     
    290309
    291310    private function getCacheKey() {
    292         return strtolower( str_replace("-", "_", "{$this->_plugin->key}_{$this->_name}_cache") );
     311        $key = self::plugin()->key . "_{$this->_name}_cache";
     312        return strtolower( str_replace("-", "_", $key) );
    293313    }
    294314
  • dynamic-qr-code/trunk/sos/wp/data/formbutton.php

    r2779336 r3213836  
    77    const STYLE_SUCCESS = 'color: #ffffff; background-color: #5cb85c; border-color: #4cae4c;';
    88    const STYLE_DANGER = 'color: #ffffff; background-color: #d9534f; border-color: #d43f3a;';
     9    const STYLE_WARNING = 'color: #ffffff; background-color: #f0ad4e; border-color: #f0ad4e;';
     10    const STYLE_SECONDARY = 'color: #ffffff; background-color: #6c757d; border-color: #6c757d';
    911
    1012    private static function get( $type, $name, $value, $style, $class, $onclick ) {
    1113        return FormTag::get( 'input', [
    12                 'type' => $type
     14                 'type' => $type
    1315                ,'id' => $name
    1416                ,'name' => $name
     
    2123        );
    2224    }
    23 
    2425
    2526    public static function getSubmit( $name, $value = 'ok', $style = '', $class = '', $onclick = null ) {
     
    4041
    4142    public static function htmlLink( $value = 'ok', $style = '', $class = '', $onclick = null ) {
    42         echo sosidee_kses( self::getButton( null, $value, $style, $class, $onclick ) );
     43        echo sosidee_kses( self::get( 'button', null, $value, $style, $class, $onclick ) );
    4344    }
    4445
  • dynamic-qr-code/trunk/sos/wp/data/formfield.php

    r2779336 r3213836  
    3737            ,'cols' => null
    3838            ,'rows' => null
     39            ,'size' => null
    3940
    4041            ,'onclick' => null
     
    6768                    ,'value' => $this->value
    6869                    ,'maxlength' => $keys['maxlength']
     70                    ,'size' => $keys['size']
    6971                    ,'onclick' => $keys['onclick']
    7072                    ,'onchange' => $keys['onchange']
     
    7880
    7981            $html = FormTag::get( 'input', [
    80                 'type' => 'checkbox'
     82                 'type' => 'checkbox'
    8183                ,'id' => $this->id
    8284                ,'name' => $this->name
     
    105107            ]);
    106108
     109        } else if ( $this->type == FormFieldType::RADIO ) {
     110
     111            $options = $keys['options'];
     112            if ( !is_null($options) ) {
     113                $counter = 0;
     114                foreach ( $options as $_value => $_text ) {
     115                    if ( $ret != '' ) {
     116                        $ret .= '<br>';
     117                    }
     118                    $item_id = "{$this->id}_$counter";
     119                    $ret .= FormTag::get('input',[
     120                         'type' => 'radio'
     121                        ,'id' => $item_id
     122                        ,'name' => $this->name
     123                        ,'value' => $_value
     124                        ,'checked' => strcasecmp($_value, $this->value) == 0
     125                        ,'onclick' => $keys['onclick']
     126                    ]);
     127                    $ret .= FormTag::get( 'label', [
     128                        'for' => $item_id
     129                        ,'content' => $_text
     130                    ]);
     131                    $counter++;
     132                }
     133            }
     134
    107135        } else if ( $this->type == FormFieldType::SELECT ) {
    108136
     
    114142                    if ( !is_array($_text) ) {
    115143                        $html .= FormTag::get('option',[
    116                             'id' => "{$this->id}_$counter"
     144                             'id' => "{$this->id}_$counter"
    117145                            ,'name' => "{$this->name}_$counter"
    118146                            ,'value' => $_value
     
    125153                        foreach ($_text as $gr_value => $gr_text) {
    126154                            $gr_html .= FormTag::get('option',[
    127                                 'id' => "{$this->id}_$counter"
     155                                 'id' => "{$this->id}_$counter"
    128156                                ,'name' => "{$this->name}_$counter"
    129157                                ,'value' => $gr_value
     
    144172
    145173            $ret .= FormTag::get( 'select', [
    146                 'id' => $this->id
     174                 'id' => $this->id
    147175                ,'name' => $this->name
    148176                ,'html' => $html
    149177                ,'onchange' => $keys['onchange']
     178                ,'style' => $keys['style']
    150179            ]);
    151180
     
    153182
    154183            $ret .= FormTag::get( 'input', [
    155                     'type' => 'number'
     184                     'type' => 'number'
    156185                    ,'id' => $this->id
    157186                    ,'name' => $this->name
     
    160189                    ,'max' => $keys['max']
    161190                    ,'step' => $keys['step']
     191                    ,'style' => $keys['style']
     192                    ,'class' => $keys['class']
    162193                    ,'onclick' => $keys['onclick']
    163194                    ,'onchange' => $keys['onchange']
     
    168199
    169200            $ret .= FormTag::get( 'input', [
    170                     'type' => 'color'
     201                     'type' => 'color'
    171202                    ,'id' => $this->id
    172203                    ,'name' => $this->name
     
    181212
    182213            $ret .= FormTag::get( 'input', [
    183                     'type' => 'date'
     214                     'type' => 'date'
    184215                    ,'id' => $this->id
    185216                    ,'name' => $this->name
     
    197228
    198229            $ret .= FormTag::get( 'input', [
    199                     'type' => 'time'
     230                     'type' => 'time'
    200231                    ,'id' => $this->id
    201232                    ,'name' => $this->name
     
    213244
    214245            $ret .= FormTag::get( 'input', [
    215                     'type' => 'hidden'
     246                     'type' => 'hidden'
    216247                    ,'id' => $this->id
    217248                    ,'name' => $this->name
     
    223254
    224255            $ret .= FormTag::get( 'input', [
    225                     'type' => 'file'
     256                     'type' => 'file'
    226257                    ,'id' => $this->id
    227258                    ,'name' => $this->name
     
    267298            ]);
    268299
     300        } else if ( $this->type == FormFieldType::CHECKLIST ) {
     301
     302            $jsFunc = $this->getJsFuncName( $this->id );
     303            $options = $keys['options'];
     304            $count = 0;
     305            foreach ($options as $value => $text) {
     306                $id = "{$this->id}_{$count}";
     307                if ( $ret != '') {
     308                    $ret .= '<br>';
     309                }
     310                $ret .= FormTag::get( 'input', [
     311                    'type' => 'checkbox'
     312                    ,'id' => $id
     313                    ,'name' => "{$this->name}_{$count}"
     314                    ,'value' => $value
     315                    ,'checked' => in_array($value, $this->value)
     316                    ,'onclick' => "{$jsFunc}(this.value,this.checked);"
     317                ]);
     318                $ret .= FormTag::get( 'label', [
     319                    'for' => $id
     320                    ,'content' => $text
     321                ]);
     322                $count++;
     323            }
     324
     325            $ret .= FormTag::get( 'input', [
     326                'type' => 'hidden'
     327                ,'id' => $this->id
     328                ,'name' => $this->name
     329                ,'value' => implode(';', $this->value)
     330            ] );
     331
     332            $js = <<<EOD
     333function {$jsFunc}( v, m ) {
     334    let field = self.document.getElementById( '{$this->id}' );
     335    let values = field.value.split( ';' ).filter(element => element);
     336    if ( m && !values.includes(v) ) {
     337        values.push(v);
     338    } else if ( !m && values.includes(v) ) {
     339        values = values.filter( function(e, i, a) { return e != v; }, v );
     340    }
     341    field.value = values.join( ';' );
     342}
     343EOD;
     344            $ret .= FormTag::get( 'script', [
     345                'type' => 'application/javascript'
     346                ,'content' => $js
     347            ]);
    269348        }
    270349
     
    272351        if ( $description != '' ) {
    273352            if ( $description == strip_tags($description) ) {
    274                 $html = HtmlTag::get( 'span', [ 'content' => $description, 'style' => 'font-style:italic;' ]);
    275                 $ret .= HtmlTag::get( 'p', [ 'html' => $html ]);
     353                $html = FormTag::get( 'span', [ 'content' => $description, 'style' => 'font-style:italic;' ]);
     354                $ret .= FormTag::get( 'p', [ 'html' => $html ]);
    276355            } else {
    277356                $ret .= $description;
     
    300379    }
    301380
    302 
    303381    public function getValueAsDate( $end_of_day = false ) {
    304382        if ( is_null( $this->value ) ) {
  • dynamic-qr-code/trunk/sos/wp/data/formfieldtype.php

    r2779336 r3213836  
    1616    const COMBOBOX = 10;
    1717    const FILE = 11;
     18    const CHECKLIST = 12;
     19    const RADIO = 13;
    1820}
  • dynamic-qr-code/trunk/sos/wp/data/formtag.php

    r2779336 r3213836  
    66{
    77
    8     public static function getStyle( $parameter, $default = null ) {
    9         if ( !is_null($default) ) {
    10             if ( !is_null($parameter) ) {
    11                 $results = [];
    12                 $defs = explode(';', $default);
    13                 for ($n=0; $n<count($defs); $n++) {
    14                     $kvs = explode(':', $defs[$n]);
    15                     if (count($kvs) == 2) {
    16                         $results[$kvs[0]] = rtrim( $kvs[1], ';');
    17                     }
    18                 }
    19                 $pars = explode(';', $parameter);
    20                 for ($n=0; $n<count($pars); $n++) {
    21                     $kvs = explode(':', $pars[$n]);
    22                     if (count($kvs) == 2) {
    23                         $results[$kvs[0]] = rtrim( $kvs[1], ';');
    24                     }
    25                 }
    26                 $ret = "";
    27                 foreach ($results as $key => $value ) {
    28                     $ret .= "$key:$value;";
    29                 }
    30                 return $ret;
    31             } else {
    32                 return $default;
    33             }
    34         } else {
    35             return $parameter;
    36         }
    37     }
    38 
    398}
  • dynamic-qr-code/trunk/sos/wp/data/group.php

    r2779336 r3213836  
    4848                        $value = $this->values[$field->key];
    4949                        $field->setValue( $value );
     50                        $field->loaded = true;
    5051                    }
    5152                }
     
    5960     */
    6061    public function callback( $inputs ) {
    61         if ( !is_null($this->validate) ) {
    62             if ( !$this->handled ) {
     62        if ( !is_null($this->validate) && !$this->handled ) {
    6363                $results = call_user_func( $this->validate, $this->key, $inputs );
    6464
    65                 if ( $this->encrypted ) { //at least one field is encrypted
     65                if ( $this->encrypted && is_array($results) ) { //at least one field is encrypted
    6666                    foreach ( $results as $key => $value ) {
    6767                        $field = $this->getField($key);
     
    7474                $this->handled = true; // so it won't be handled anymore
    7575                return $results;
    76             } else {
    77                 return $inputs;
    78             }
    7976        }
     77        return $inputs;
    8078    }
    8179
  • dynamic-qr-code/trunk/sos/wp/data/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/data/mbfield.php

    r2753631 r3213836  
    7878    }
    7979
    80     public function getCheckbox( $label = '' ) {
     80    public function getCheckbox( $data = [] ) {
    8181        $ret = FormTag::get( 'input', [
    8282            'type' => 'checkbox'
     
    8686        ]);
    8787
    88         if ( $label != '' ) {
     88        if ( isset($data['label']) ) {
    8989            $ret .= FormTag::get( 'label', [
    90                 'for' => $this->id
    91                 ,'content' => $label
     90                 'for' => $this->id
     91                ,'content' => $data['label']
    9292            ]);
    9393        }
  • dynamic-qr-code/trunk/sos/wp/data/wpcolumn.php

    r2815343 r3213836  
    99class WpColumn
    1010{
     11
     12    use TDateTime;
     13
    1114    protected $parent; //name
    1215
     
    6265            return null;
    6366        } else {
    64             return Db::getDatetimeAsString( $value, $quoted );
     67            return self::getDatetimeAsString( $value, $quoted );
    6568        }
    6669    }
     
    7073            return null;
    7174        } else {
    72             return Db::getDatetimeFromString( $value );
     75            return self::getDatetimeFromString( $value );
    7376        }
    7477    }
     
    7881            return null;
    7982        } else {
    80             return Db::getTimeAsString( $value, $quoted );
     83            return self::getTimeAsString( $value, $quoted );
    8184        }
    8285    }
     
    8689            return null;
    8790        } else {
    88             return Db::getTimeFromString( $value );
     91            return self::getTimeFromString( $value );
    8992        }
    9093    }
     
    9295    public function setDefaultValue( $value ) {
    9396        $this->defaultValue = $value;
     97        return $this;
     98    }
     99
     100    public function setNullable( $value ) {
     101        $this->nullable = $value;
    94102        return $this;
    95103    }
  • dynamic-qr-code/trunk/sos/wp/data/wpdatabase.php

    r2779336 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP_ROOT;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP_ROOT;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    77class WpDatabase
    88{
    9     use SOS_WP_ROOT\Property;
     9    use SOS_WP_ROOT\TProperty;
     10    use SOS_WP_ROOT\TBase;
    1011
    1112    protected $prefix; //tables prefix
     
    1415    public $lastErrors;
    1516
    16     public function __construct( $prefix = null ) {
     17    public function __construct( $prefix ) {
    1718        global $wpdb;
    18         if ( is_null($prefix) ) {
    19             $prefix = 'sos_';
     19        if ( !sosidee_str_starts_with($prefix, 'sos') && !sosidee_str_starts_with($prefix, '_sos') ) {
     20            if ( !sosidee_str_starts_with($prefix, '_') ) {
     21                $prefix = '_' . $prefix;
     22            }
     23            $prefix = 'sos' . $prefix;
    2024        }
    2125        if ( !sosidee_str_ends_with($wpdb->prefix, '_') && !sosidee_str_starts_with($prefix, '_') ) {
     
    4448        $count = count($this->tables);
    4549        if ( $count > 0 ) {
    46             require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
     50            require_once( ABSPATH . str_replace('/', DIRECTORY_SEPARATOR, 'wp-admin/includes/upgrade.php') );
    4751            if ( function_exists('dbDelta') ) {
    4852                $ret = true;
     
    7781    }
    7882
    79     public function create()
    80     {
     83    public function create() {
    8184        add_action( 'plugins_loaded', function() {
    82             $plugin = \SOSIDEE_DYNAMIC_QRCODE\SosPlugin::instance();
    83             $key = $plugin->key . '_db-version';
     85            $current = $this->plugin()->version;
     86            if ( empty($current) ) {
     87                $msg = "Plugin version is empty. Check if initialize() function contains the line 'parent::initialize();'";
     88                if ( is_admin() ) {
     89                    $this->plugin()::msgErr($msg, true);
     90                }
     91                sosidee_log("WpDatabase.create(): " . $msg);
     92            }
     93            $key = $this->plugin()->key . '_db-version';
    8494            $installed = get_option($key, '0' );
    85             $current = $plugin->version;
    8695            if ( version_compare($installed, $current) < 0 ) {
    8796                if ( $this->createTables() ) {
    8897                    update_option($key, $current );
     98                    $this->plugin()->onDatabaseUpdate($installed, $current);
    8999                } else {
    90100                    if ( is_admin() ) {
    91101                        for ( $n=0; $n<count($this->lastErrors); $n++ ) {
    92                             $plugin::msgErr( $this->lastErrors[$n] );
     102                            $this->plugin()::msgErr( $this->lastErrors[$n], true );
    93103                        }
    94104                    }
     
    124134
    125135    /**
    126      * @param string $formatted_sql sql query with formats (%d, %s, %f)
    127      * @param array $values values associated with the formats --> look out: order is important!
    128      * @return wpdb object|false
     136     * @param \string $formatted_sql sql query with formats (%d, %s, %f)
     137     * @param \array $values values associated with the formats --> look out: order is important!
     138     * @return \wpdb object|false
    129139     *
    130140     * Example: obj->query( "INSERT INTO <table> (foo, bar, baz) VALUES (%s, %d, %f)", 'pippo', 123, 1.23 );
  • dynamic-qr-code/trunk/sos/wp/data/wptable.php

    r2779336 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA;
    3 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP_ROOT;
     3use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP_ROOT;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
    66class WpTable
    77{
    8     use SOS_WP_ROOT\Property;
     8    use SOS_WP_ROOT\TProperty;
    99
    1010    protected $columns;
     
    6464        return $this->addColumn($name, WpColumnType::TIME);
    6565    }
     66
    6667
    6768    protected function getColumnByName($name) {
     
    152153        $clauses = array();
    153154        $values = array();
     155        $filter_in = false;
    154156        foreach ( $filters as $key => $value ) {
    155157            $clauses[] = array();
     
    158160
    159161            $name = $key;
    160             $operator = '=';
     162            $operator = !is_array($value) ? '=' : ' IN ';
    161163            $p1 = strrpos($key, '[');
    162164            if ( $p1 !== false ) {
     
    175177                        $values[$index] = $column->getTimeValueAsString( $value );
    176178                } else {
    177                     $values[$index] = $value;
    178                 }
    179                 $clauses[$index]['format'] = $column->getQueryFormat();
     179                    if ( !is_array($value) ) {
     180                        $values[$index] = $value;
     181                    } else {
     182                        $values[$index] = '{_(' . implode(',', $value) . ')_}';
     183                        $filter_in = true;
     184                    }
     185                }
     186                if ( !is_array($value) ) {
     187                    $clauses[$index]['format'] = $column->getQueryFormat();
     188                } else {
     189                    $clauses[$index]['format'] = '%s';
     190                }
    180191            } else {
    181192                $error = true;
     
    214225            if ( count($values) > 0) {
    215226                $query = $wpdb->prepare($sql, $values);
     227                if ( $filter_in ) {
     228                    $query = str_replace([" IN '{_(", ")_}'"], [" IN (", ")"], $query);
     229                }
    216230            } else {
    217231                $query = $sql;
     
    230244                                    $values[$name] = $wpColumn->getNativeValueFromString( $value );
    231245                                } else {
    232                                     sosidee_log( "WpTable.querySelect() :: {$this->name}.getColumnByName({$name}) returned false." );
     246                                    sosidee_log( "WpTable.querySelect(): returned column {$name} not found in the definition of table {$this->name}." );
    233247                                }
    234248                            }
  • dynamic-qr-code/trunk/sos/wp/elementor/control.php

    r2714714 r3213836  
    2020    public $options;
    2121    public $text;
     22    public $multiple;
    2223
    2324    public function __construct( $key, $type ) {
     
    3031        $this->options = array();
    3132        $this->text = '';
     33        $this->multiple = false;
    3234    }
    3335
     
    5557            $ret['options'] = $this->options;
    5658        }
     59        if ( $this->multiple != false ) {
     60            $ret['multiple'] = true;
     61        }
    5762        return $ret;
    5863    }
  • dynamic-qr-code/trunk/sos/wp/elementor/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/elementor/section.php

    r2684394 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\Elementor;
    3 use \Elementor as NativeElementor;
     3use Elementor as NativeElementor;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
  • dynamic-qr-code/trunk/sos/wp/elementor/widget.php

    r2714714 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP\Elementor;
    3 use \Elementor as NativeElementor;
     3use Elementor as NativeElementor;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    2626        public $icon;
    2727        public $category;
     28        public $keyword;
    2829    //
    2930
     
    3738
    3839     * Example:
    39         public function setKey()
    40         {
     40        public function setKey() {
    4141            $this->key = self::plugin()->key . '_unique_key';
    4242        }
     
    5656        $this->icon = 'eicon-star-o';
    5757        $this->category = 'general';
     58        $this->keyword = [];
    5859    }
    5960
     
    7273    public function get_categories() {
    7374        return is_array($this->category) ? $this->category : [ $this->category ];
     75    }
     76
     77    public function get_keywords() {
     78        return is_array($this->keyword) ? $this->keyword : [ $this->keyword ];
    7479    }
    7580
  • dynamic-qr-code/trunk/sos/wp/functions.php

    r2815343 r3213836  
    7171if ( !function_exists('sosidee_str_remove') ) {
    7272    function sosidee_str_remove( $search, $subject ) {
    73         return str_replace($search, '', $subject);
     73        if ( is_array($search) ) {
     74            $blank = array_fill(0, count($search), '');
     75        } else {
     76            $blank = '';
     77        }
     78        return str_replace($search, $blank, $subject);
     79    }
     80}
     81
     82if ( ! function_exists( 'sosidee_check_path_separator' ) ) {
     83    function sosidee_check_path_separator( $path ) {
     84        return str_replace('/', DIRECTORY_SEPARATOR, $path);
     85    }
     86}
     87
     88if ( ! function_exists( 'sosidee_check_folder_separator' ) ) {
     89    function sosidee_check_folder_separator( $path ) {
     90        return rtrim( sosidee_check_path_separator($path) , DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
     91    }
     92}
     93
     94if ( ! function_exists( 'sosidee_append_url_separator' ) ) {
     95    function sosidee_append_url_separator( $url ) {
     96        return rtrim( $url , '/') . '/';
     97    }
     98}
     99
     100if ( ! function_exists( 'sosidee_upload_dir' ) ) {
     101    function sosidee_upload_dir() {
     102        $ret = false;
     103        $root = wp_upload_dir();
     104        if ( $root['error'] === false && isset($root['baseurl']) && isset($root['basedir']) ) {
     105            $ret = [
     106                 'path' => sosidee_check_folder_separator( $root['basedir'] )
     107                ,'url' => sosidee_append_url_separator( $root['baseurl'] )
     108            ];
     109        }
     110        return $ret;
    74111    }
    75112}
     
    86123
    87124if ( ! function_exists( 'sosidee_get_query_var' ) ) {
    88     function sosidee_get_query_var($var, $mixed = null) {
     125    function sosidee_get_query_var($var, $def_value = null) {
    89126        $ret = get_query_var($var, null);
    90127        if ( is_null($ret) && isset( $_GET[$var] ) ) {
    91128            $ret = sanitize_text_field( $_GET[$var] );
    92129        } else {
    93             $ret = $mixed;
     130            $ret = $def_value;
    94131        }
    95132        return $ret;
     
    106143if ( ! function_exists( 'sosidee_is_base64' ) ) {
    107144    function sosidee_is_base64($data) {
    108         return base64_encode(base64_decode($data, true)) === $data;
     145        if ( ( $str = base64_decode($data, true) ) === false) {
     146            return false;
     147        }
     148        if ( in_array(mb_detect_encoding($str), ['UTF-8', 'ASCII']) ) {
     149            return true;
     150        } else {
     151            return false;
     152        }
    109153    }
    110154}
     
    112156if ( ! function_exists( 'sosidee_dirname' ) ) {
    113157    function sosidee_dirname( $path, $levels = 1 ) {
     158        $ret = '';
    114159        if ( version_compare( phpversion(), '7.0.0') >= 0 ) {
    115             return dirname($path, $levels);
     160            $ret = dirname($path, $levels);
    116161        } else {
    117162            if ($levels > 1){
    118                 return dirname( sosidee_dirname( $path, --$levels ) );
     163                $ret = dirname( sosidee_dirname( $path, --$levels ) );
    119164            }else{
    120                 return dirname( $path );
    121             }
    122         }
     165                $ret = dirname( $path );
     166            }
     167        }
     168        return $ret; //str_replace('/', DIRECTORY_SEPARATOR, $ret);
    123169    }
    124170}
     
    149195                    }
    150196                    $plug = substr($path, $k);
    151                     $m = strpos($plug, '/') + $k;
     197                    $m = strpos($plug, '/');
    152198                    if ( $m !== false ) {
     199                        $plug = substr($path, $k, $m);
     200                        /*
     201                        $m += $k;
    153202                        $plug = substr($path, $k, $m - $k);
     203                        */
    154204                    }
    155205                }
     
    173223        }
    174224        return strpos( $_SERVER['REQUEST_URI'], trailingslashit( rest_get_url_prefix() ) ) !== false;
     225    }
     226}
     227
     228if ( ! function_exists( 'sosidee_is_local' ) ) {
     229    function sosidee_is_local() {
     230        $ret = false;
     231        if (substr($_SERVER['REMOTE_ADDR'], 0, 4) == '127.' || $_SERVER['REMOTE_ADDR'] == '::1') {
     232            $ret = true;
     233        }
     234        return $ret;
     235    }
     236}
     237
     238if ( ! function_exists( 'sosidee_is_dev' ) ) {
     239    function sosidee_is_dev() {
     240        $file = realpath(ABSPATH) . DIRECTORY_SEPARATOR . 'sos_identifier.txt';
     241        return file_exists($file) && trim(file_get_contents($file)) === 'SOS-DEV';
    175242    }
    176243}
     
    247314
    248315        $tags = [
    249               'a', 'b', 'br', 'button', 'caption', 'code', 'col', 'colgroup'
    250             , 'data', 'div', 'em', 'form'
     316              'a', 'audio', 'b', 'br', 'button', 'caption', 'code', 'col', 'colgroup'
     317            , 'data', 'datalist', 'div', 'em', 'form'
    251318            , 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
    252             , 'hr', 'i', 'img', 'input'
     319            , 'hr', 'i', 'iframe', 'img', 'input'
    253320            , 'label', 'legend', 'li', 'nav'
    254321            , 'ol', 'optgroup', 'option'
    255             , 'p', 'pre', 'script', 'select', 'span', 'strong'
     322            , 'p', 'pre', 'script', 'section', 'select', 'span', 'strong', 'style'
    256323            , 'table', 'tbody', 'td', 'textarea', 'th', 'thead', 'title', 'tr'
    257             , 'ul'
     324            , 'ul', 'video'
    258325        ];
    259326
     
    262329            , 'disabled', 'download', 'enctype'
    263330            , 'for', 'form', 'height', 'href', 'id'
    264             , 'label', 'max', 'maxlength', 'method', 'min', 'name'
     331            , 'label', 'lang', 'max', 'maxlength', 'method', 'min', 'name'
    265332            , 'onblur', 'onchange', 'onclick', 'onfocus', 'onload', 'onsubmit'
    266             , 'readonly', 'rows', 'rowspan', 'scope', 'selected', 'size', 'span', 'src', 'step', 'style'
    267             , 'target', 'title', 'type', 'value', 'width', 'wrap'
     333            , 'readonly', 'rel', 'rows', 'rowspan'
     334            , 'scope', 'selected', 'size', 'span', 'src', 'step', 'style'
     335            , 'usemap', 'target', 'title', 'type', 'value', 'width', 'wrap'
    268336        ];
    269337
  • dynamic-qr-code/trunk/sos/wp/htmltag.php

    r2779336 r3213836  
    7575    }
    7676
     77    public static function getStyle( $parameter, $default = null ) {
     78        if ( !is_null($default) ) {
     79            if ( !is_null($parameter) ) {
     80                $results = [];
     81                $defs = explode(';', $default);
     82                for ($n=0; $n<count($defs); $n++) {
     83                    $kvs = explode(':', $defs[$n]);
     84                    if (count($kvs) == 2) {
     85                        $results[$kvs[0]] = rtrim( $kvs[1], ';');
     86                    }
     87                }
     88                $pars = explode(';', $parameter);
     89                for ($n=0; $n<count($pars); $n++) {
     90                    $kvs = explode(':', $pars[$n]);
     91                    if (count($kvs) == 2) {
     92                        $results[$kvs[0]] = rtrim( $kvs[1], ';');
     93                    }
     94                }
     95                $ret = "";
     96                foreach ($results as $key => $value ) {
     97                    $ret .= "$key:$value;";
     98                }
     99                return $ret;
     100            } else {
     101                return $default;
     102            }
     103        } else {
     104            return $parameter;
     105        }
     106    }
    77107
    78108}
  • dynamic-qr-code/trunk/sos/wp/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/sos/wp/metabox.php

    r2815343 r3213836  
    1818class MetaBox
    1919{
    20     use Property, Message, Translation;
     20    use TProperty, TMessage, TTranslation;
    2121
    2222    public $fields;
     
    186186                    }
    187187                }
    188                 sosidee_log( 'Metabox.callbackSave(): empty or invalid nonce (' . esc_attr($_POST[$nonce_name]) . ')' );
     188                sosidee_log( 'Metabox.callbackSave(): empty or invalid nonce' );
    189189            }
    190190        } else {
     
    207207            $this->err($msg);
    208208        }
     209        return $post_ID;
    209210    }
    210211
     
    270271     * Save data in the 'postmeta' table
    271272     *
    272      * @param WP_Post $post : the post related to the metabox
     273     * @param \WP_Post $post : the post related to the metabox
    273274     * @return mixed:
    274275     *                  (bool) true: success
     
    284285            $key = $field->key;
    285286            $values[$key] = $field->value;
    286             if ( !is_array($prev_values) || $prev_values[$key] != $field->value ) {
     287            if ( !is_array($prev_values) || !array_key_exists($key, $prev_values) || $prev_values[$key] != $field->value ) {
    287288                $ret = false;
    288289            }
     
    350351     * Template for the displaying function
    351352     *
    352      * @param Metabox $metabox : a metabox
    353      * @param WP_Post $post : the post
     353     * @param \Metabox $metabox : a metabox
     354     * @param \WP_Post $post : the post
    354355     *
    355356    public function html( $metabox, $post ) {
  • dynamic-qr-code/trunk/sos/wp/plugin.php

    r2815343 r3213836  
    11<?php
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP;
    3 use \Elementor as NativeElementor;
     3use Elementor as NativeElementor;
    44defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    55
     
    1212class Plugin
    1313{
    14     use Property
    15     {
    16         Property::__get as __getProp;
    17         Property::__set as __setProp;
    18     }
    19     use Message, Asset, Translation;
     14    use TProperty
     15    {
     16        TProperty::__get as __getProp;
     17        TProperty::__set as __setProp;
     18    }
     19    use TTransient, TMessage, TAsset, TTranslation, TAddon;
     20
     21    protected static $helpUrl = 'https://redirect.soslink.net/{KEY}/help/';
    2022
    2123    private $localizedScriptHandles;
     
    3335
    3436    protected $dashLinks;
     37    protected $customUpdate;
    3538
    3639    protected $file;
     
    4649    public static $path = '';
    4750    public static $url = '';
     51
     52    public $isPro;
    4853   
    4954    protected function __construct() {
     55        $this->isPro = false;
    5056
    5157        $this->_addProperty('key', 'sos-plugin');
     
    7177
    7278        $this->dashLinks = array();
    73 
    74         self::$path = sosidee_dirname( plugin_dir_path( __FILE__ ) , 2);
     79        $this->customUpdate = false;
     80
     81        $this->resetAddons();
     82        $this->plmVersionMin = '1.0.0';
     83
     84        self::$path = sosidee_check_path_separator( sosidee_dirname( plugin_dir_path( __FILE__ ) , 2) );
    7585        $this->folder = basename(self::$path);
    7686        self::$url = sosidee_dirname( plugin_dir_url( __FILE__ ) , 2);
     
    8595            self::$_instances[$calledClass] = new $calledClass();
    8696        }
    87 
    8897        return self::$_instances[$calledClass];
    8998    }
    9099
    91100    public function __get( $name ) {
    92         $ret = null;
    93101        switch($name) {
    94102            default:
     
    113121        return $ret;
    114122    }
    115    
     123
    116124    /**
    117125     * Creates and adds a backend page located in the 'admin' folder
     
    201209    }
    202210
     211    protected function addStyleInline( $code ) {
     212        $key = $this->key . '-' . time();
     213        wp_register_style( $key, false );
     214        wp_enqueue_style( $key );
     215        wp_add_inline_style( $key, $code );
     216    }
     217
    203218    protected function addScript( $file, $jquery_dependency = true, $in_body = false ) {
    204219        $key = $this->key . '-' . count($this->scripts);
     
    224239        $action = !is_admin() ? 'wp_enqueue_scripts' : 'admin_enqueue_scripts';
    225240        add_action( $action, function() use ( $code, $pages, $handle ) {
    226             if (!is_array($pages)) {
     241            if ( !is_array($pages) ) {
    227242                $pages = [$pages];
    228243            }
     
    238253            if ( $add ) {
    239254                $this->addInlineScript( $code, $handle );
    240             } else {
    241                 return false;
    242255            }
    243256        } );
     
    272285                $data = $callback();
    273286                $this->addLocalizedScript( $name, $data, $handle );
    274             } else {
    275                 return false;
    276287            }
    277288        } );
     
    294305        $ret = new API\EndPoint($method, $route, $callback, $version );
    295306        $this->endpoints[] = $ret;
    296         $this->addApiAjax();
     307        //$this->addApiAjax(); //va aggiunta solo se serve
    297308        return $ret;
    298309    }
     
    311322    protected function addApiAny( $route, $callback = null, $version = 1 ) {
    312323        return $this->_addApiEndPoint( ['GET','POST'], $route, $callback, $version);
    313         //return $this->_addApiEndPoint( \WP_REST_Server::ALLMETHODS, $route, $callback, $version);
    314324    }
    315325
     
    376386        if ( $this->version == '' ) {
    377387            $this->getInfo();
    378             if ($this->version == '') {
     388            if ( $this->version == '' ) {
    379389                add_action('plugins_loaded', function() {
    380390                    if ( $this->version == '' ) {
     
    384394            }
    385395        }
     396
     397        add_action('plugin_loaded', [$this, '_onLoad']);
     398
     399        if ( !has_action('plugins_loaded', [$this, 'initializeAddons']) ) {
     400            add_action('plugins_loaded', [$this, 'initializeAddons']);
     401        }
     402
    386403    }
    387404
     
    429446
    430447    public function initializePage() {
     448        $data = array();
    431449        for ( $n=0; $n<count($this->pages); $n++ ) {
    432             $this->pages[$n]->translate();
    433             $this->pages[$n]->url = admin_url('admin.php?page=' . $this->pages[$n]->key);
     450            $page = &$this->pages[$n];
     451            $page->translate();
     452            if ( $page->menuType == BE\MenuType::TOOLS ) {
     453                $page->url = add_query_arg('page', $page->key, admin_url('tools.php'));
     454            } else if ( $page->menuType == BE\MenuType::SETTINGS ) {
     455                $page->url = add_query_arg('page', $page->key, admin_url('options-general.php'));
     456            } else {
     457                $page->url = add_query_arg('page', $page->key, admin_url('admin.php'));
     458            }
     459            if ( $page->menuHidden === true ) {
     460                $last_slash_pos = strrpos($page->url, '/');
     461                if ( $last_slash_pos !== false ) {
     462                    $href = substr($page->url, $last_slash_pos + 1);
     463                    $data[] = $href;
     464                }
     465            }
     466            unset($page);
     467        }
     468        if ( count($data) > 0 ) {
     469            $js = "jQuery(document).ready(function($) { ";
     470            foreach ($data as $item) {
     471                $js .= "$('a[href=\"$item\"]').closest('li').remove(); ";
     472            }
     473            $js .= " });";
     474            $this->registerInlineScript($js);
    434475        }
    435476    }
     
    446487                add_action('elementor/widgets/widgets_registered', [$this, 'initializeElementor']);
    447488            } else {
    448                 //self::msgWarn('The minimum version of Elementor is 2.0.0.', true);
     489                // self::msgWarn('The minimum version of Elementor is 2.0.0.', true);
    449490            }
    450491        } else {
    451             //self::msgWarn('Elementor is not loaded.', true);
     492            // self::msgWarn('Elementor is not loaded.', true);
    452493        }
    453494    }
     
    476517                    $title = $link['title'];
    477518                    $target = $link['target'];
    478                     if (self::$internationalized) {
     519                    if ( self::$internationalized ) {
    479520                        $text = $this::t_($text);
    480521                    }
     
    521562                    if ( $after_title && $metabox->context == 'after_title' ) {
    522563                        add_action('edit_form_after_title',  function() {
    523                             if ($this->gutenbergEnabled) { return false;}
     564                            if ($this->gutenbergEnabled) { return; }
    524565                            global $post, $wp_meta_boxes;
    525566                            do_meta_boxes( get_current_screen(), 'after_title', $post ); // Output the "after_title" meta boxes
     
    531572                }
    532573            }
    533             if ( count($this->pages) > 0 ) {
    534                 add_action( 'admin_menu', array($this, 'initializePage') );
    535             }
    536             if ( count($this->menu->pages) > 0 ) {
    537                 add_action( 'admin_menu', array($this, 'initializeMenu') );
    538             }
     574
    539575            if ( count($this->scripts) > 0 ) {
    540576                for ($n=0; $n<count($this->scripts); $n++) {
     
    552588            }
    553589
    554             $file = "{$this->folder}/{$this->folder}.php";
    555             if ( !is_multisite() ) {
    556                 add_action( "in_plugin_update_message-$file", [$this, 'displayUpdateNotice'], 10, 2 );
    557             } else {
    558                   add_action( "after_plugin_row_wp-{$file}", [$this, 'displayUpdateNoticeMS'], 10, 2 );
     590            if ( $this->customUpdate == false ) {
     591                $file = "{$this->folder}/{$this->folder}.php";
     592                if ( !is_multisite() ) {
     593                    add_action( "in_plugin_update_message-$file", [$this, 'displayUpdateNotice'], 10, 2 );
     594                } else {
     595                    add_action( "after_plugin_row_wp-{$file}", [$this, 'displayUpdateNoticeMS'], 10, 2 );
     596                }
     597            }
     598
     599            if ( count($this->pages) > 0 ) {
     600                add_action( 'admin_menu', array($this, 'initializePage') );
     601            }
     602            if ( count($this->menu->pages) > 0 ) {
     603                add_action( 'admin_menu', array($this, 'initializeMenu') );
    559604            }
    560605
     
    571616        }
    572617
    573         register_deactivation_hook($this->file, array($this, 'onDeactivate'));
     618        if ( !is_null($this->file) ) {
     619            register_activation_hook($this->file, array($this, 'onActivate'));
     620            register_deactivation_hook($this->file, array($this, 'onDeactivate'));
     621        }
     622
     623    }
     624
     625    public function onDatabaseUpdate($old_version, $new_version) {
     626        //to be overridden, if needed
     627    }
     628
     629    public function onActivate() {
     630        //to be overridden, if needed
    574631    }
    575632
     
    578635    }
    579636
     637    public function onLoad() {
     638        //to be overridden, if needed
     639    }
     640
     641    public function _onLoad($file) {
     642        $folder = sosidee_check_path_separator( sosidee_dirname($file) );
     643        if ( $folder == $this::$path ) {
     644            $this->onLoad();
     645        }
     646    }
    580647
    581648    /**
     
    628695    * @return integer : index of the group in the $clusters array
    629696     *
    630      * @TODO: move to DATA\Db or DATA\Group
     697     * @TODO: move to DATA\Group
    631698    **/
    632699    protected function getGroupIndexById( $id ) {
     
    634701
    635702        $ret = false;
    636         $sql = "SELECT option_name, option_value FROM $wpdb->options WHERE option_id=%d";
     703        $sql = "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_id=%d";
    637704        $query = $wpdb->prepare( $sql, $id);
    638705        $results = $wpdb->get_row($query, ARRAY_A);
    639         if ($results) {
     706        if ( $results ) {
    640707            $key = sanitize_key( $results["option_name"] );
    641708            $ret = $this->getClusterIndex($key);
    642             if ($ret !== false) {
     709            if ( $ret !== false ) {
    643710                $cluster = $this->clusters[$ret];
    644711                if ( $cluster instanceof Data\Group ) {
     
    656723
    657724    protected function isEncryptionPossible() {
    658         return extension_loaded( 'openssl' )
    659             && defined('SECURE_AUTH_KEY') && SECURE_AUTH_KEY != ''
    660                && defined('SECURE_AUTH_SALT') && SECURE_AUTH_SALT != '';
     725        return extension_loaded( 'openssl' )
     726            && defined('SECURE_AUTH_KEY') && SECURE_AUTH_KEY != ''
     727            && defined('SECURE_AUTH_SALT') && SECURE_AUTH_SALT != '';
    661728    }
    662729
    663730    public function getTempFolder() {
    664731        $ret = false;
    665         $root = wp_upload_dir();
    666         if ( $root['error'] === false ) {
    667             $url = $root['baseurl'] . '/' .  $this->key;
    668             $folder = $root['basedir'] . '/' .  $this->key;
     732        $root = sosidee_upload_dir();
     733        if ( $root !== false ) {
     734            $url = $root['url'] . $this->key . '/';
     735            $folder = $root['path'] . $this->key . DIRECTORY_SEPARATOR;
    669736            $ok = is_dir($folder);
    670737            if ( !$ok ) {
     
    672739            }
    673740            if ( $ok ) {
    674                 $file = $folder . DIRECTORY_SEPARATOR .  'index.html';
     741                $file = $folder . 'index.html';
    675742                if ( !is_file($file) ) {
    676                     $content = "<!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>";
     743                    $content = "<!DOCTYPE html><html lang=\"en\"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>";
    677744                    file_put_contents( $file, $content );
    678745                }
    679746
    680747                $ret = array();
    681                 $ret['basedir'] = $folder;
    682                 $ret['baseurl'] = $url;
     748                $ret['path'] = $folder;
     749                $ret['url'] = $url;
    683750            }
    684751        }
     
    779846    }
    780847
     848    protected function setHelp( $key ) {
     849        self::$helpUrl = str_replace( '{KEY}', $key, self::$helpUrl );
     850    }
     851
     852    public function help( $path = '', $style = 'margin: 0.75em; float: right;' ) {
     853        $url = self::$helpUrl . $path;
     854        $ret = '<a href="' . esc_url($url) . '" onclick="this.blur();" target="_blank" title="help"><i class="dashicons dashicons-editor-help"';
     855        $style = HtmlTag::getStyle($style, 'color: #ffcc00; font-size: 1.5em; text-decoration: none;');
     856        if ( !is_null($style) ) {
     857            $ret .= ' style="' . esc_attr($style) . '"';
     858        }
     859        $ret .= '></i></a>';
     860        return $ret;
     861    }
     862
    781863}
  • dynamic-qr-code/trunk/sos/wp/script.php

    r2753631 r3213836  
    1313class Script
    1414{
    15     use Property
    16     {
    17         Property::__get as __getProp;
    18         Property::__set as __setProp;
    19     }
     15    use TProperty
     16    {
     17        TProperty::__get as __getProp;
     18        TProperty::__set as __setProp;
     19    }
    2020
    2121    private $dependency;
  • dynamic-qr-code/trunk/sos/wp/shortcode.php

    r2779336 r3213836  
    2525        if ( sosidee_is_rest() ) {
    2626            // do not sanitize if it's a block editor api call (in this case is_admin() always returns false and can't be used)
    27             return;
     27            return null;
    2828        }
    2929
     
    3131            // prevent other plugins to call the $callback function
    3232            //@TODO: unless the call comes from Elementor (otherwise its display doesn't work...)
    33             return;
     33            return null;
    3434        }
    3535
  • dynamic-qr-code/trunk/sos/wp/style.php

    r2753631 r3213836  
    1212class Style
    1313{
    14     use Property {
    15         Property::__get as __getProp;
    16         Property::__set as __setProp;
     14    use TProperty {
     15        TProperty::__get as __getProp;
     16        TProperty::__set as __setProp;
    1717    }
    1818
  • dynamic-qr-code/trunk/sos/wp/user.php

    r2779336 r3213836  
    22namespace SOSIDEE_DYNAMIC_QRCODE\SOS\WP;
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
     4
     5//TEMPORARY: cache_users() not loaded with WP 6.1
     6if ( ! function_exists( 'cache_users' ) ) {
     7    require_once realpath(ABSPATH . WPINC . DIRECTORY_SEPARATOR . 'pluggable.php');
     8}
    49
    510class User
  • dynamic-qr-code/trunk/src/api.php

    r2684394 r3213836  
    55class Api
    66{
     7    use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\TBase;
     8
    79    const IMG_LOGO = 'data:image/png;base64,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';
    8 
    9     private static function plugin() {
    10         return \SOSIDEE_DYNAMIC_QRCODE\SosPlugin::instance();
    11     }
    1210
    1311    private static function getLogo() {
  • dynamic-qr-code/trunk/src/database.php

    r2779336 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
    5 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA as DATA;
     5use SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA as DATA;
    66
    77class Database
     
    1414
    1515        // TABLE QR-CODES
    16         $tab1 = $this->native->addTable("qrcodes");
    17         $tab1->addID("qrcode_id");
    18         $tab1->addBoolean("disabled")->setDefaultValue(false);
    19         $tab1->addVarChar("code", 255);
    20         $tab1->addVarChar("description", 255);
    21         $tab1->addVarChar("url_redirect", 255);
    22         $tab1->addVarChar("url_inactive", 255);
    23         $tab1->addVarChar("url_expired", 255);
    24         $fldDateFrom = $tab1->addDateTime("date_from");
     16        $tabQC = $this->native->addTable("qrcodes");
     17        $tabQC->addID("qrcode_id");
     18        $tabQC->addBoolean("disabled")->setDefaultValue(false);
     19        $tabQC->addVarChar("code", 255);
     20        $tabQC->addVarChar("description", 255);
     21        $tabQC->addVarChar("url_redirect", 255);
     22        $tabQC->addVarChar("url_inactive", 255);
     23        $tabQC->addVarChar("url_expired", 255);
     24        $fldDateFrom = $tabQC->addDateTime("date_from");
    2525        $fldDateFrom->nullable = true;
    26         $fldDateUpto = $tab1->addDateTime("date_to");
     26        $fldDateUpto = $tabQC->addDateTime("date_to");
    2727        $fldDateUpto->nullable = true;
    28         $fldTimeFrom = $tab1->addTime("time_from");
     28        $fldTimeFrom = $tabQC->addTime("time_from");
    2929        $fldTimeFrom->nullable = true;
    30         $fldTimeUpto = $tab1->addTime("time_to");
     30        $fldTimeUpto = $tabQC->addTime("time_to");
    3131        $fldTimeUpto->nullable = true;
    32         $tab1->addTinyInteger("dotw");
    33         $tab1->addBoolean("priority")->setDefaultValue(false);
    34         $tab1->addInteger("max_scan_tot");
    35         $tab1->addVarChar("url_finished", 255);
    36         $tab1->addVarChar("cypher", 255);
    37         $tab1->addVarChar("url_cypher", 255);
    38         $tab1->addBoolean("only_mfa")->setDefaultValue(false);
    39         $tab1->addTinyInteger("device_os")->setDefaultValue(0);
    40         $tab1->addVarChar("device_lang", 2)->setDefaultValue('');
    41         $tab1->addVarChar("img_forecolor", 16)->setDefaultValue(QRcode::IMAGE_FOREGROUND);
    42         $tab1->addVarChar("img_backcolor", 16)->setDefaultValue(QRcode::IMAGE_BACKGROUND);
    43         $tab1->addDateTime("creation")->setDefaultValueAsCurrentDateTime();
    44         $tab1->addBoolean("cancelled")->setDefaultValue(false);
     32        $tabQC->addTinyInteger("dotw");
     33        $tabQC->addBoolean("priority")->setDefaultValue(false);
     34        $tabQC->addInteger("max_scan_tot");
     35        $tabQC->addVarChar("url_finished", 255);
     36        $tabQC->addVarChar("cypher", 255);
     37        $tabQC->addVarChar("url_cypher", 255);
     38        $tabQC->addBoolean("only_mfa")->setDefaultValue(false);
     39        $tabQC->addTinyInteger("device_os")->setDefaultValue(0);
     40        $tabQC->addVarChar("device_lang", 2)->setDefaultValue('');
     41        $tabQC->addVarChar("img_forecolor", 16)->setDefaultValue(QRcode::IMAGE_FOREGROUND);
     42        $tabQC->addVarChar("img_backcolor", 16)->setDefaultValue(QRcode::IMAGE_BACKGROUND);
     43        $tabQC->addDateTime("creation")->setDefaultValueAsCurrentDateTime();
     44        $tabQC->addBoolean("cancelled")->setDefaultValue(false);
    4545
    4646        // TABLE LOGS
    47         $tab2 = $this->native->addTable("logs");
    48         $tab2->addID("log_id");
    49         $tab2->addTinyInteger("status");
    50         $tab2->addVarChar("code", 255);
    51         $tab2->addInteger("qrcode_id");
    52         $tab2->addVarChar("user_key", 255)->setDefaultValue('');
    53         $tab2->addVarChar("event_id", 255)->setDefaultValue('');
    54         $tab2->addDateTime("creation")->setDefaultValueAsCurrentDateTime();
    55         $tab2->addBoolean("cancelled")->setDefaultValue(false);
     47        $tabLog = $this->native->addTable("logs");
     48        $tabLog->addID("log_id");
     49        $tabLog->addTinyInteger("status");
     50        $tabLog->addVarChar("code", 255);
     51        $tabLog->addInteger("qrcode_id");
     52        $tabLog->addVarChar("user_key", 255)->setDefaultValue('');
     53        $tabLog->addVarChar("event_id", 255)->setDefaultValue('');
     54        $tabLog->addTinyInteger("op_sys")->setDefaultValue(OS::UNKNOWN); //operative system
     55        $tabLog->addTinyInteger("dev_type")->setDefaultValue(DeviceType::UNKNOWN);
     56        $tabLog->addVarChar("lang", 2)->setDefaultValue('');
     57        $tabLog->addVarChar("country", 2)->setDefaultValue('');
     58        $tabLog->addVarChar("region", 255)->setDefaultValue('');
     59        $tabLog->addVarChar("city", 255)->setDefaultValue('');
     60        $tabLog->addDateTime("creation")->setDefaultValueAsCurrentDateTime();
     61        $tabLog->addBoolean("cancelled")->setDefaultValue(false);
    5662
    5763        // TABLE ONE-TIME KEYS
    58         $tab3 = $this->native->addTable("otkeys");
    59         $tab3->addID("otk_id");
    60         $tab3->addInteger("qrcode_id");
    61         $tab3->addVarChar("code", 255);
    62         $tab3->addInteger("tally")->setDefaultValue(0);
    63         $tab3->addDateTime("creation")->setDefaultValueAsCurrentDateTime();
     64        $tabOtk = $this->native->addTable("otkeys");
     65        $tabOtk->addID("otk_id");
     66        $tabOtk->addInteger("qrcode_id");
     67        $tabOtk->addVarChar("code", 255);
     68        $tabOtk->addInteger("tally")->setDefaultValue(0);
     69        $tabOtk->addDateTime("creation")->setDefaultValueAsCurrentDateTime();
    6470
    6571        $this->native->create();
     
    102108    }
    103109
    104     private function loadQrCodeByCode( $field, $value ) {
     110    private function loadQrCodeByField($field, $value ) {
    105111        $table = $this->native->qrcodes;
    106112
    107113        $results = $table->select( [
    108             $field => $value
     114             $field => $value
    109115            ,'cancelled' => false
    110116        ] );
     
    121127        $field = $table->code->name;
    122128
    123         return $this->loadQrCodeByCode( $field, $code );
     129        return $this->loadQrCodeByField( $field, $code );
    124130    }
    125131
     
    128134        $field = $table->cypher->name;
    129135
    130         $results = $this->loadQrCodeByCode( $field, $code );
     136        $results = $this->loadQrCodeByField( $field, $code );
    131137        if ( is_array($results) && count($results) == 1 ) {
    132138            return $results[0];
     
    150156    }
    151157
    152     public function loadQrCodeList() {
    153         $table = $this->native->qrcodes;
    154 
    155         $filters = [ $table->cancelled->name => false ];
     158    public function loadQrCodeList( $include_cancelled = false ) {
     159        $table = $this->native->qrcodes;
     160
     161        if ( !$include_cancelled ) {
     162            $filters = [ $table->cancelled->name => false ];
     163        } else {
     164            $filters = [];
     165        }
    156166        $orders = ['description'];
    157167
    158         return $table->distinct( ['qrcode_id', 'description'], $filters, $orders );
     168        return $table->select( $filters, $orders );
     169    }
     170
     171    public function loadQrKeyList() {
     172        $table = $this->native->qrcodes;
     173
     174        $filters = [
     175            $table->cancelled->name => false
     176        ];
     177        $orders = ['code'];
     178
     179        return $table->distinct( ['code'], $filters, $orders );
    159180    }
    160181
     
    190211    }
    191212
    192     public function countActiveLogs( $code ) {
     213    public function countActiveLogsById( $qrcode_id ) {
    193214        $table = $this->native->logs;
    194215        $filters = [
    195              'code' => $code
     216             'qrcode_id' => $qrcode_id
     217            ,$table->cancelled->name => false
     218        ];
     219        return $table->count( $filters );
     220    }
     221
     222    public function countActiveLogsByCode( $qrcode_code ) {
     223        $table = $this->native->logs;
     224        $filters = [
     225             'code' => $qrcode_code
    196226            ,$table->cancelled->name => false
    197227        ];
     
    213243
    214244        if ( array_key_exists('status', $filters) && $filters['status'] != LogStatus::NONE ) {
    215             $where[ $table->status->name ] = $filters['status'];
     245            if ( !is_array($filters['status']) || count($filters['status']) > 0) {
     246                $where[ $table->status->name ] = $filters['status'];
     247            }
     248        }
     249
     250        if ( array_key_exists('op_sys', $filters) && $filters['op_sys'] != OS::UNKNOWN ) {
     251            if ( !is_array($filters['op_sys']) || count($filters['op_sys']) > 0) {
     252                $where[ $table->op_sys->name ] = $filters['op_sys'];
     253            }
     254        }
     255
     256        if ( array_key_exists('dev_type', $filters) && $filters['dev_type'] != DeviceType::UNKNOWN ) {
     257            $where[ $table->dev_type->name ] = $filters['dev_type'];
    216258        }
    217259
  • dynamic-qr-code/trunk/src/dotw.php

    r2714714 r3213836  
    1717    }
    1818
    19     public static function getList($caption = false) {
     19    public static function getList( $caption = false ) {
    2020        $ret = array();
    2121
  • dynamic-qr-code/trunk/src/form/base.php

    r2763042 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
    5 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
     5use SOSIDEE_DYNAMIC_QRCODE\SRC as SRC;
     6use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOS_WP;
    67
    78class Base extends \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA\Form
    89{
     10    public static $FLD_HID;
     11
    912    private static $root = null;
    1013    private static $options = null;
    1114
    12     protected $_database;
     15    //protected $_database;
    1316
    1417    public function __construct($name, $callback = null) {
    1518        parent::__construct( $name, $callback );
    16 
    17         $this->_database = $this->_plugin->database;
    18 
    1919    }
    2020
     
    5858    }
    5959
    60     public static function getOptions() {
     60    public static function getUrlList() {
    6161        if ( is_null(self::$options) ) {
    62             self::$options = [
    63                 '' => 'custom URL'
    64                 ,'Pages' => self::getPageList()
    65                 ,'Posts' => self::getPostList()
    66             ];
     62            self::$options = [ '' => 'custom URL' ];
     63            if ( self::plugin()->hasFacebook() ) {
     64                self::$options['Facebook&nbsp;'] = self::plugin()->addon->facebook::getOptions();
     65            }
     66            if ( self::plugin()->hasInstagram() ) {
     67                self::$options['Instagram&nbsp;'] = self::plugin()->addon->instagram::getOptions();
     68            }
     69            if ( self::plugin()->hasLinkedIn() ) {
     70                self::$options['LinkedIn&nbsp;'] = self::plugin()->addon->linkedin::getOptions();
     71            }
     72            if ( self::plugin()->hasWhatsApp() ) {
     73                self::$options['WhatsApp&nbsp;'] = self::plugin()->addon->whatsapp::getOptions();
     74            }
     75            if ( self::plugin()->hasYouTube() ) {
     76                self::$options['YouTube&nbsp;'] = self::plugin()->addon->youtube::getOptions();
     77            }
     78            self::$options['Pages&nbsp;'] = self::getPageList();
     79            self::$options['Posts&nbsp;'] = self::getPostList();
    6780        }
    6881        return self::$options;
     
    7083
    7184    public static function getDescription( $text, $paragraph = false ) {
    72         $ret = SOS_WP\HtmlTag::get( 'span', [ 'html' => $text, 'style' => 'font-style:italic;' ]);
     85        $ret = SOS_WP\HtmlTag::get( 'span', [ 'html' => $text, 'style' => 'font-style:italic;' ] );
    7386        if ( $paragraph ) {
    74             $ret = SOS_WP\HtmlTag::get( 'p', [ 'html' => $ret ]);
     87            $ret = SOS_WP\HtmlTag::get( 'p', [ 'html' => $ret ] );
    7588        }
    7689        return $ret;
    7790    }
    7891
    79     private static $langs = null;
    80     public function getLanguageList( $caption = '' ) {
    81         if ( is_null(self::$langs) ) {
    82             $items = $this->_plugin->loadAsset('language-codes.json');
    83             if ( is_array($items) ) {
    84                 for ( $n=0; $n<count($items); $n++ ) {
    85                     self::$langs[$items[$n]->alpha2] = $items[$n]->English;
    86                 }
    87             } else {
    88                 sosidee_log('Json languages file could not be successfully loaded.');
    89                 return ['' => '- sorry, cannot load language list -'];
    90             }
    91         }
    92         if ( $caption != '' ) {
    93             return ['' => $caption] + self::$langs;
    94         } else {
    95             return self::$langs;
    96         }
     92    private static function isPosted() {
     93        return isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) == 'POST';
    9794    }
    9895
     96    public static function checkPosted( $value ) {
     97        $ret = false;
     98        if ( self::isPosted() ) {
     99            $config = self::plugin()->config;
     100            //$config->formCheckMode->load();
     101            switch ( $config->formCheckMode->getValue() ) {
     102                case CheckMode::METHOD:
     103                    $ret = true;
     104                    break;
     105                case CheckMode::REFERER:
     106                    $ref = wp_get_raw_referer();
     107                    $pid = url_to_postid($ref);
     108                    if ( $pid == get_the_ID() ) {
     109                        $ret = true;
     110                    } else {
     111                        sosidee_log("Hiding content: data posted from an invalid URL. Referer=$ref");
     112                    }
     113                    break;
     114                case CheckMode::FIELD:
     115                    if ( isset($_POST[self::$FLD_HID]) ) {
     116                        $hid = trim( $_POST[self::$FLD_HID] );
     117                        if ( strcasecmp( $hid, $value ) == 0 ) {
     118                            $ret = true;
     119                        } else {
     120                            sosidee_log("Hiding content: hidden field value is {$hid} while {$value} was expected.");
     121                        }
     122                    } else {
     123                        sosidee_log("Hiding content: hidden field not found.");
     124                    }
     125                    break;
     126            }
     127        } else {
     128            sosidee_log("Hiding content: invalid REQUEST_METHOD value.");
     129        }
     130        return $ret;
     131    }
     132
     133    protected function getProMsg( $msg ) {
     134        return $msg . ' ' . self::plugin()->pro();
     135    }
     136
     137    public static function getHiddenFieldTemplate( $id ) {
     138        return SOS_WP\DATA\FormTag::get( 'input', [
     139             'type' => 'hidden'
     140            ,'name' => self::$FLD_HID
     141            ,'value' => $id
     142        ]);
     143    }
     144
     145
    99146}
  • dynamic-qr-code/trunk/src/form/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/src/form/logsearch.php

    r2779336 r3213836  
    55use SOSIDEE_DYNAMIC_QRCODE\SRC as SRC;
    66use SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA as DATA;
    7 
    8 class LogSearch extends Base
     7use SOSIDEE_DYNAMIC_QRCODE\SRC\QrCode;
     8
     9class LogSearch extends Log
    910{
     11
     12    private $status;
     13
    1014    private $qid;
    11     private $status;
    12     private $dtFrom;
    13     private $dtTo;
    14 
    15     public $logs;
    16 
    1715    private $log_id;
    1816
     17    protected $chkLang;
     18    protected $chkGeo;
     19    protected $chkDesc;
     20
     21    protected $chkOS;
     22
    1923    public function __construct() {
    20         parent::__construct( 'logSearch', [$this, 'onSubmit'] );
     24        parent::__construct( 'logSearch' );
    2125
    2226        $this->qid = $this->addSelect('qid', '' );
     
    2428        $this->status = $this->addSelect('status', SRC\LogStatus::NONE );
    2529        $this->status->cached = true;
    26         $this->dtFrom = $this->addDatePicker('from', 'now');
    27         $this->dtFrom->cached = true;
    28         $this->dtTo = $this->addDatePicker('up_to', 'now');
    29         $this->dtTo->cached = true;
    3030
    3131        $this->log_id = $this->addHidden('delete_log_id', 0);
    3232
    33         $this->logs = [];
     33        $this->chkLang = $this->addCheckBox('show_lang');
     34        $this->chkGeo = $this->addCheckBox('show_geo');
     35        $this->chkDesc = $this->addCheckBox('show_desc');
     36        $this->chkOS = $this->addCheckBox('show_os');
     37
     38    }
     39
     40    public function showLang() {
     41        return self::plugin()->isPro && $this->chkLang->value;
     42    }
     43    public function showGeo() {
     44        return self::plugin()->isPro && $this->chkGeo->value;
     45    }
     46    public function showDesc() {
     47        return self::plugin()->isPro && $this->chkDesc->value;
     48    }
     49    public function showOS() {
     50        return self::plugin()->isPro && $this->chkOS->value;
    3451    }
    3552
    3653    public function htmlQID() {
    37         $options = $this->_plugin->loadQrCodeList('- any -');
     54        //$options = $this->loadQrCodeList();
     55        $options = QrCode::loadQrCodeList();
    3856        $this->qid->html( ['options' => $options] );
    3957    }
     
    4462    }
    4563
    46     public function htmlFrom() {
    47         $this->dtFrom->html();
    48     }
    49     public function htmlTo() {
    50         $this->dtTo->html();
    51     }
    52 
    5364    public function htmlLogId() {
    5465        $this->log_id->html();
     66    }
     67
     68    public function htmlShowLang() {
     69        $this->chkLang->html( ['label' => 'Language'] );
     70    }
     71    public function htmlShowGeo() {
     72        $this->chkGeo->html( ['label' => 'Country'] );
     73    }
     74    public function htmlShowDesc() {
     75        $this->chkDesc->html( ['label' => 'Description'] );
     76    }
     77    public function htmlShowOS() {
     78        $this->chkOS->html( ['label' => 'Operative System'] );
    5579    }
    5680
     
    7397
    7498    public function htmlCancelAll() {
    75 
    76         parent::htmlButton( 'clear', 'delete all logs', DATA\FormButton::STYLE_DANGER, null, "return self.confirm('Do you confirm to delete ALL the logs?');" );
    77     }
    78 
    79     public function htmlDownload($logs, $code_shared, $mfa_enabled) {
    80 
     99        parent::htmlButton( 'clear', 'delete ALL logs', DATA\FormButton::STYLE_DANGER, null, "return self.confirm('Do you confirm to delete ALL the logs present in the database?');" );
     100    }
     101
     102    public function htmlDownload( $logs, $mfa_enabled ) {
    81103        if ( count($logs) > 0 ) {
    82             $folder = $this->_plugin->getTempFolder();
     104            $folder = self::plugin()->getTempFolder();
    83105            if ($folder !== false) {
    84106                $lines = array();
    85                 $headers =[
    86                      'Date'
    87                     ,'Code'
    88                     ,'Status'
    89                 ];
    90                 if ($code_shared) {
    91                     $headers[] = 'Qid';
    92                 }
    93                 if ($mfa_enabled) {
     107                $headers = $this->getCsvHeader( $logs[0] );
     108                if ( $mfa_enabled ) {
    94109                    $headers[] = 'My FastAPP User Key';
    95110                }
    96111                $lines[] = $headers;
    97                 for ($n=0; $n<count($logs); $n++) {
     112                for ( $n=0; $n<count($logs); $n++ ) {
    98113                    $log = $logs[$n];
    99114                    $row = [
    100115                         $log->creation_string
     116                        ,SRC\LogStatus::getDescription( $log->status )
    101117                        ,$log->code
    102                         ,SRC\LogStatus::getDescription( $log->status )
     118                        ,QrCode::getQID( $log->qrcode_id )
    103119                    ];
    104                     if ($code_shared) {
    105                         $row[] = $log->qrcode_id;
    106                     }
    107                     if ($mfa_enabled) {
     120                    if ( isset($log->lang_desc) ) {
     121                        $row[] = $log->lang_desc;
     122                    }
     123                    if ( isset($log->country_desc) ) {
     124                        $row[] = $log->country_desc;
     125                    }
     126                    if ( isset($log->qrcode_desc) ) {
     127                        $row[] = $log->qrcode_desc;
     128                    }
     129                    if ( isset($log->os_desc) ) {
     130                        $row[] = $log->os_desc;
     131                    }
     132                    if ( $mfa_enabled ) {
    108133                        $row[] = $log->user_key;
    109134                    }
     
    111136                }
    112137                $file = 'log_' . uniqid() . '.csv';
    113                 $path = $folder['basedir'] . "/{$file}";
     138                $path = $folder['path'] . "/{$file}";
    114139                if ( $this->saveCSV($path, $lines) ) {
    115                     $url = $folder['baseurl'] . "/{$file}";
     140                    $url = $folder['url'] . "/{$file}";
    116141                    $onclick = "javascript:window.open('{$url}', 'sosidee', 'popup=1');";
    117142                } else {
     
    120145
    121146            } else {
    122                 $onclick = "alert('" . htmlentities( addslashes('A problem occurred.'), ENT_NOQUOTES ) . "')";
     147                $onclick = "alert('" . htmlentities( addslashes("A problem occurred."), ENT_NOQUOTES ) . "')";
    123148            }
    124149
     
    135160    }
    136161
    137     /*
    138     private function loadQrCodeList() {
    139         $ret = [ 0 => '- any -' ];
    140 
    141         $results = $this->_database->loadQrCodeList();
    142 
    143         if ( is_array($results) ) {
    144             if ( count($results) > 0 ) {
    145                 for ( $n=0; $n<count($results); $n++ ) {
    146                     $ret[ $results[$n]->qrcode_id ] = $results[$n]->description;
    147                 }
    148             }
    149         } else {
    150             self::msgErr( 'A problem occurred while reading the qr code list from the database.' );
    151         }
    152         return $ret;
    153     }
    154     */
    155 
    156     protected function initialize() {
    157         if ( !$this->_posted ) {
    158             if ( $this->_cache_timestamp instanceof \DateTime ) {
    159                 $now = sosidee_current_datetime();
    160                 if ( $this->_cache_timestamp->format('Ymd') != $now->format('Ymd') ) {
    161                     $this->dtFrom->value = $now->format('Y-m-d');
    162                     $this->dtTo->value = $now->format('Y-m-d');
    163                 }
    164             }
    165         }
    166     }
    167 
    168162    public function onSubmit() {
    169163
     
    175169
    176170            if ( $id > 0 ) {
    177                 $result = $this->_database->deleteLog( $id );
     171                $result = self::database()->deleteLog( $id );
    178172                if ( $result !== false ) {
    179                     self::msgOk( 'Log data have been deleted.' );
     173                    self::msgOk( "Log data have been deleted." );
    180174                    $this->loadLogs();
    181175                } else {
    182                     self::msgErr( 'A problem occurred.' );
     176                    self::msgErr( "A problem occurred." );
    183177                }
    184178            } else {
     
    186180            }
    187181
    188 
    189182        } else if ( $this->_action == 'clear' ) {
    190183
    191             $result = $this->_database->clearLog();
     184            $result = self::database()->clearLog();
    192185            if ( $result !== false ) {
    193                 self::msgOk( 'All logs have been deleted.' );
     186                self::msgOk( "All logs have been deleted." );
    194187                $this->loadLogs();
    195188            } else {
    196                 self::msgErr( 'A problem occurred.' );
     189                self::msgErr( "A problem occurred." );
    197190            }
    198191
     
    201194
    202195    public function loadLogs() {
    203         $this->logs = [];
    204 
    205         $qid = intval( $this->qid->value );
    206196
    207197        $filters = [
    208              'qrcode_id' => $qid
     198             'qrcode_id' => intval( $this->qid->value )
    209199            ,'status' => $this->status->value
    210             ,'from' => $this->dtFrom->getValueAsDate()
    211             ,'to' => $this->dtTo->getValueAsDate( true )
    212200        ];
    213201
    214         $orders = [ 'creation' => 'DESC' ];
    215 
    216         $results = $this->_database->loadLogs( $filters, $orders );
    217 
    218         if ( is_array($results) ) {
    219             if ( count($results) > 0 ) {
    220                 for ( $n=0; $n<count($results); $n++ ) {
    221                     $results[$n]->creation_string = sosidee_datetime_format( $results[$n]->creation );
    222                     $results[$n]->status_icon = SRC\LogStatus::getStatusIcon( $results[$n]->status );
    223                 }
    224                 if ( $this->_posted ) {
    225                     $this->saveCache();
    226                 }
    227             } else {
    228                 if ( $this->_posted ) {
    229                     self::msgInfo( 'No results match the search.' );
    230                 } else {
    231                     self::msgInfo( "There's no data in the database." );
    232                 }
    233             }
    234             $this->logs = $results;
    235         } else {
    236             self::msgErr( 'A problem occurred.' );
    237         }
    238     }
    239 
    240 
    241 
    242     public function saveCSV($path, $lines, $parameters = array()) {
    243         $ret = false;
    244 
    245         $delimiter = ',';
    246         $enclosure = '"';
    247         $escape = "\\";
    248         $out_charset = 'Windows-1252';
    249         $in_charset = 'UTF-8';
    250 
    251         extract($parameters, EXTR_IF_EXISTS);
    252 
    253         if ( ($handle = fopen($path, "w")) !== false ) {
    254             $ret = true;
    255             for ($i=0; $i<count($lines); $i++) {
    256                 $data = $lines[$i];
    257                 for ($j=0; $j<count($data); $j++) {
    258                     $data[$j] = iconv( $in_charset, "$out_charset//TRANSLIT", $data[$j] );
    259                 }
    260                 $ret = (fputcsv($handle, $data, $delimiter, $enclosure, $escape) !== false) && $ret;
    261             }
    262             fclose($handle);
    263         }
    264 
    265         return $ret;
    266     }
    267 
     202        parent::load( $filters );
     203
     204        for ( $n=0; $n<count($this->logs); $n++ ) {
     205            $this->logs[$n]->creation_string = sosidee_datetime_format( $this->logs[$n]->creation );
     206            $this->logs[$n]->status_icon = SRC\LogStatus::getStatusIcon( $this->logs[$n]->status );
     207        }
     208
     209        if ( count($this->logs)>0 ) {
     210            if ( !self::plugin()->isPro ) {
     211                $features = [];
     212                if ( $this->chkGeo->value ) {
     213                    $features[] = 'Country';
     214                }
     215                if ( $this->chkLang->value ) {
     216                    $features[] = 'Language';
     217                }
     218                if ( $this->chkDesc->value ) {
     219                    $features[] = 'QR-Code Description';
     220                }
     221                if ( $this->chkOS->value ) {
     222                    $features[] = 'Operative System';
     223                }
     224                $count = count($features);
     225                if ( $count > 0 ) {
     226                    $list = $features[0];
     227                    if ( $count > 1 ) {
     228                        $allButLast = array_slice($features, 0, -1);
     229                        $list = implode(', ', $allButLast) . ' and ' .  $features[$count - 1];
     230                    }
     231                    $msg = $this->getProMsg($list . ' logs are available on');
     232                    self::msgWarn($msg);
     233                }
     234            }
     235        }
     236
     237    }
    268238
    269239}
  • dynamic-qr-code/trunk/src/form/qrcodeedit.php

    r2815343 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
    5 use \SOSIDEE_DYNAMIC_QRCODE\SRC as SRC;
    6 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA as DATA;
     5use SOSIDEE_DYNAMIC_QRCODE\SRC as SRC;
     6use SOSIDEE_DYNAMIC_QRCODE\SOS\WP\DATA as DATA;
     7use SOSIDEE_DYNAMIC_QRCODE\SOS\Locale;
    78
    89class QrCodeEdit extends Base
     
    3132    private $img_backcolor;
    3233
     34    private $code_old;
    3335    public $code;
    3436
     
    5658        $this->max_scan_tot = $this->addNumericBox('max_scan_tot');
    5759        $this->url_finished = $this->addComboBox('url_finished', '');
    58         $description = self::getDescription("mandatory field", true);
     60        $description = self::getDescription('mandatory field', true);
    5961        $this->description->description = $description;
    6062        $this->code->description = $description;
     
    6365        $this->url_cypher = $this->addComboBox('url_cypher', '');
    6466        $this->only_mfa = $this->addCheckBox('only_mfa', false);
    65         $this->device_os = $this->addSelect('device_os', SRC\OS::NONE);
     67        $this->device_os = $this->addSelect('device_os', SRC\OS::UNKNOWN);
    6668        $this->device_lang = $this->addSelect('device_lang', '');
    6769
    68         $this->img_forecolor = $this->addColorPicker('img_forecolor', $this->_plugin->config->imgForeColor->getValue() );
    69         $this->img_backcolor = $this->addColorPicker('img_backcolor', $this->_plugin->config->imgBackColor->getValue() );
     70        $this->img_forecolor = $this->addColorPicker('img_forecolor', self::plugin()->config->imgForeColor->getValue() );
     71        $this->img_backcolor = $this->addColorPicker('img_backcolor', self::plugin()->config->imgBackColor->getValue() );
     72
     73        $this->code_old = $this->addHidden('code_old', '');
    7074
    7175        $this->showCypher = false;
     
    9296        $this->url_cypher->value = '';
    9397        $this->only_mfa->value = false;
    94         $this->device_os->value = SRC\OS::NONE;
     98        $this->device_os->value = SRC\OS::UNKNOWN;
    9599        $this->device_lang->value = '';
    96         $this->img_forecolor->value = $this->_plugin->config->imgForeColor->value;
    97         $this->img_backcolor->value = $this->_plugin->config->imgBackColor->value;
     100        $this->img_forecolor->value = self::plugin()->config->imgForeColor->value;
     101        $this->img_backcolor->value = self::plugin()->config->imgBackColor->value;
    98102
    99103        $this->showCypher = false;
     
    109113        $this->code->html( ['maxlength' => 255] );
    110114    }
     115    public function htmlCodeOld() {
     116        $this->code_old->value = $this->code->value;
     117        $this->code_old->html();
     118    }
    111119    public function htmlDescription() {
    112120        $this->description->html( ['maxlength' => 255] );
    113121    }
    114122    public function htmlUrlRedirect() {
    115         $options = Base::getOptions();
     123        $options = self::getUrlList();
    116124        $this->url_redirect->html( [ 'options' => $options ] );
    117125    }
    118126    public function htmlUrlInactive() {
    119         $options = Base::getOptions();
     127        $options = self::getUrlList();
    120128        $this->url_inactive->html( [ 'options' => $options ] );
    121129    }
    122130    public function htmlUrlExpired() {
    123         $options = Base::getOptions();
     131        $options = self::getUrlList();
    124132        $this->url_expired->html( [ 'options' => $options ] );
    125133    }
     
    153161    }
    154162    public function htmlUrlFinished() {
    155         $options = Base::getOptions();
     163        $options = $this->getUrlList();
    156164        $this->url_finished->html( [ 'options' => $options ] );
    157165    }
    158166    public function htmlCurrentScan() {
    159167        if ( $this->id->value > 0 && $this->code->value != '' ) {
    160             $current = $this->_database->countActiveLogs( $this->code->value );
     168            $current = self::database()->countActiveLogs( $this->code->value );
    161169            if ( $current !== false ) {
    162170                DATA\FormTag::html( 'span', [
     
    173181    }
    174182    public function htmlDeviceLang() {
    175         $options = $this->getlanguageList('- any -');
     183        $options = Locale::getLanguages('- any -');
    176184        $this->device_lang->html( [ 'options' => $options ] );
    177185    }
     
    188196    public function htmlUrlCypher() {
    189197        if ( $this->cypher->value != '' ) {
    190             $options = Base::getOptions();
     198            $options = $this->getUrlList();
    191199            $this->url_cypher->html( [ 'options' => $options ] );
    192200        } else {
    193201            DATA\FormTag::html( 'label', [
    194                 'html' => ' &nbsp; - - - '
     202                 'html' => ' &nbsp; - - - '
    195203                ,'style' => 'padding:2px 4px 2px 4px;margin-left:1em;'
    196204            ]);
     
    202210        if ( $id > 0 ) {
    203211            DATA\FormTag::html( 'span', [
    204                 'content' => "Q-{$id}"
     212                 'content' => "Q-{$id}"
    205213                ,'style' => 'cursor:text;background-color:white;padding:2px 4px 2px 4px;'
    206214            ]);
     
    211219        $id = $this->id->value;
    212220        $code = !$cypher ? $this->code->value : base64_encode($this->cypher->value);
    213         $content = $code != '' ? $this->_plugin->getApiUrl( $code, $cypher ) : ' - - - ';
     221        $content = $code != '' ? self::plugin()->getApiUrl( $code, $cypher ) : ' - - - ';
    214222        if ( $code != '' && $cypher ) {
    215223            $content = substr($content, 0, 80) .  " ...";
    216224        }
    217         echo $this->_plugin->getCopyApiUrl2CBIcon( $id, $code, $cypher );
     225        echo SRC\Copy2CB::getApiUrlIcon( $id, $code, $cypher );
    218226        echo '&nbsp; ';
    219227        DATA\FormTag::html( 'label', [
     
    226234        $id = $this->id->value;
    227235        if ( $id > 0 ) {
    228             $text = $this->_plugin->getShortcode1Template( $id );
    229             echo $this->_plugin->getCopyShortcode2CBIcon( $id, 1 );
     236            $text = SRC\Shortcode::getTemplate1( $id );
     237            echo SRC\Copy2CB::getShortcodeIcon( $id, 1 );
    230238            echo '&nbsp; ';
    231239            DATA\FormTag::html( 'label', [
    232                 'content' => $text
     240                 'content' => $text
    233241                ,'style' => 'cursor:text;background-color:white;padding:2px 4px 2px 4px;'
    234242            ]);
     
    240248        if ( $id > 0 ) {
    241249            $standard = $this->cypher->value == '';
    242             $text = $this->_plugin->getShortcode2Template( $id, $standard );
    243             echo $this->_plugin->getCopyShortcode2CBIcon( $id, 2, $standard );
     250            $text = SRC\Shortcode::getTemplate2( $id, $standard );
     251            echo SRC\Copy2CB::getShortcodeIcon( $id, 2, $standard );
    244252            echo '&nbsp; ';
    245253            DATA\FormTag::html( 'label', [
    246                 'content' => $text
     254                 'content' => $text
    247255                ,'style' => 'cursor:text;background-color:white;padding:2px 4px 2px 4px;'
    248256            ]);
     
    254262        if ( $id > 0 ) {
    255263            if ( $anyQrHideEnabled || $this->cypher->value != '' ) {
    256                 echo $this->_plugin->getCopyHiddenField2CBIcon( $id );
    257                 $text = $this->_plugin->getHiddenFieldTemplate( $id );
     264                echo SRC\Copy2CB::getHiddenFieldIcon( $id );
     265                $text = SRC\FORM\Base::getHiddenFieldTemplate( $id );
    258266            } else {
    259                 echo $this->_plugin->getCopyHiddenField2CBIcon( -1 );
     267                echo SRC\Copy2CB::getHiddenFieldIcon( -1 );
    260268                $text = ' - - - ';
    261269            }
    262270            echo '&nbsp; ';
    263271            DATA\FormTag::html( 'label', [
    264                 'content' => $text
     272                 'content' => $text
    265273                ,'style' => 'cursor:text;background-color:white;padding:2px 4px 2px 4px;'
    266274            ]);
     
    276284
    277285            if ( $code != '' ) {
    278                 $url = $this->_plugin->getApiUrl( $code, $cypher );
    279 
    280                 $size = $this->_plugin->config->imgSize->getValue();
    281                 $pad = $this->_plugin->config->imgPad->getValue();
     286                $url = self::plugin()->getApiUrl( $code, $cypher );
     287
     288                $size = self::plugin()->config->imgSize->getValue();
     289                $pad = self::plugin()->config->imgPad->getValue();
    282290
    283291                $fore_color = SRC\QrCode::getColor( $this->img_forecolor->value );
     
    289297
    290298                $img = DATA\FormTag::get( 'img', [
    291                     'src' => $img_url
     299                     'src' => $img_url
    292300                    ,'alt' => 'click to download'
    293301                    ,'style' => 'margin: 2px;'
     
    297305                    echo '<div style="flex-basis: 100%; text-align: center; font-style: italic;">click the image to download it</div>';
    298306                    DATA\FormTag::html( 'a', [
    299                         'href' => $img_url
     307                         'href' => $img_url
    300308                        ,'title' => 'click to download'
    301309                        ,'download' => uniqid()
     
    336344    }
    337345
     346    public function htmlDuplicate() {
     347        $this->htmlButton( 'duplicate', 'save as new', 'color: #ffffff; background-color: #bf00ff; border-color: #a200d9;' );
     348        if ( !self::plugin()->hasDuplicate() ) {
     349            echo ' ' . self::plugin()->pro('color: #bf00ff;', 'PRO version required');
     350        }
     351    }
    338352
    339353    public function loadQrCode( $id ) {
    340354        if ( $id > 0 ) {
    341             $qrcode= $this->_database->loadQrCode( $id );
     355            $qrcode= self::database()->loadQrCode( $id );
    342356            if ( $qrcode !== false ) {
    343357
     
    374388
    375389    public function htmlButtonLink( $id ) {
    376         $url = $this->_plugin->pageQrCode->getUrl( [self::QS_ID => $id] );
     390        $url = self::plugin()->pageQrCode->getUrl( [self::QS_ID => $id] );
    377391        if ( $id == 0 ) {
    378392            parent::htmlLinkButton( $url, 'create new' );
     
    394408    public function onSubmit() {
    395409
    396         if ( in_array($this->_action, [ 'save', 'generate_cypher', 'cancel_cypher', 'save_cypher' ]) ) {
     410        if ( in_array($this->_action, [ 'save', 'generate_cypher', 'cancel_cypher', 'save_cypher', 'duplicate' ]) ) {
    397411            $save = true;
    398412
     
    405419            $this->code->value = trim( $this->code->value );
    406420            if ( $this->code->value != '' ) {
    407                 $this->_plugin->config->load();
    408                 if ( !$this->_plugin->config->sharedCodeEnabled->value ) {
     421                self::plugin()->config->load();
     422                if ( !self::plugin()->config->sharedCodeEnabled->value ) {
    409423                    $code = $this->code->value;
    410424                    $id = intval($this->id->value);
    411                     $items = $this->_database->loadQrCodeByKey( $code );
     425                    $items = self::database()->loadQrCodeByKey( $code );
    412426                    if ( is_array($items) ) {
    413427                        for ($n=0; $n<count($items); $n++) {
    414428                            if ($items[$n]->code == $code && $items[$n]->qrcode_id != $id) {
    415429                                $save = false;
    416                                 self::msgErr( "Code is already in use by another QR-Code, whereas it must be unique: you can disable this restriction <a href=\"{$this->_plugin->pageConfig->url}\">here</a>." );
     430                                $url = self::plugin()->pageConfig->url;
     431                                self::msgErr( "Code is already in use by another QR-Code, whereas it must be unique: you can disable this restriction <a href=\"{$url}\">here</a>." );
    417432                                break;
    418433                            }
     
    431446            $this->url_redirect->value = trim( $this->url_redirect->value );
    432447            if ( $this->url_redirect->value == '' ) {
    433                 $save = false;
    434                 self::msgErr( 'Redirect URL is empty.' );
     448                //$save = false;
     449                self::msgWarn( "Redirect URL is empty: the qr code won't work!" );
    435450            }
    436451
     
    446461            }
    447462
    448             if ($this->img_forecolor->value == $this->img_backcolor->value) {
     463            if ( $this->img_forecolor->value == $this->img_backcolor->value ) {
    449464                $save = false;
    450465                self::msgErr( 'Foreground and background colors cannot be equal.' );
     466            }
     467
     468            if ( $this->_action == 'duplicate' ) {
     469                if ( !self::plugin()->hasDuplicate() ) {
     470                    $save = false;
     471                    $msg = $this->getProMsg('Duplication is available only in the PRO version');
     472                    self::msgWarn($msg);
     473                }
    451474            }
    452475
     
    461484                } else if ( $this->_action == 'save_cypher' ) {
    462485                    $this->showCypher = true;
     486                } else if ( $this->_action == 'duplicate' ) {
     487                    if ( self::plugin()->hasDuplicate() ) {
     488                        $this->id->value = self::plugin()->addon::getQRCodeDuplicateId();
     489                    }
    463490                }
    464491
    465                 if ( $this->_plugin->config->mfaEnabled->value == false ) {
     492                if ( self::plugin()->config->mfaEnabled->value == false ) {
    466493                    $this->only_mfa->value = false;
    467494                }
     
    491518                ];
    492519
    493                 $result = $this->_database->saveQrCode( $data, $this->id->value );
     520                $result = self::database()->saveQrCode( $data, $this->id->value );
    494521
    495522                if ( $result !== false ) {
    496523                    if ( $result === true ) {
    497524                        self::msgOk( 'Data have been saved.' );
     525                        if ($this->code_old->value != '' && $this->code_old->value != $this->code->value) {
     526                            self::msgWarn( "Image(s) changed because the qr code Key has been modified." );
     527                        }
    498528                        $this->loadQrCode( $this->id->value );
    499529                    } else {
     
    517547
    518548            if ( $id > 0 ) {
    519                 $result = $this->_database->deleteQrCode( $id );
     549                $result = self::database()->deleteQrCode( $id );
    520550                if ( $result !== false ) {
    521551                    $this->reset();
  • dynamic-qr-code/trunk/src/form/qrcodesearch.php

    r2779336 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
    5 use \SOSIDEE_DYNAMIC_QRCODE\SRC as SRC;
     5use SOSIDEE_DYNAMIC_QRCODE\SRC as SRC;
    66
    77class QrCodeSearch extends Base
     
    2525
    2626    public function htmlButtonLink( $id = 0 ) {
    27         $this->_plugin->formEditQrCode->htmlButtonLink( $id );
     27        self::plugin()->formEditQrCode->htmlButtonLink( $id );
    2828    }
    2929
     
    4646        ];
    4747
    48         $results = $this->_database->loadQrCodes( $filters );
     48        $results = self::database()->loadQrCodes( $filters );
    4949
    5050        if ( is_array($results) ) {
     
    5252                for ( $n=0; $n<count($results); $n++ ) {
    5353                    $results[$n]->creation_string = $results[$n]->creation->format( "Y/m/d H:i:s" );
    54                     $results[$n]->url_api = $this->_plugin->getApiUrl( $results[$n]->code );
     54                    $results[$n]->url_api = self::plugin()->getApiUrl( $results[$n]->code );
    5555                    $results[$n]->status_icon = SRC\QrCodeSearchStatus::getStatusIcon( !$results[$n]->disabled );
    5656                }
    5757            } else {
    58                 if ( $this->status->value > 0 ) {
     58                if ( $this->status->value != 0 ) {
    5959                    self::msgInfo( 'No results match the search.' );
    6060                } else {
  • dynamic-qr-code/trunk/src/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/src/lib/index.html

    r2684394 r3213836  
    1 <!DOCTYPE html><html><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
     1<!DOCTYPE html><html lang="en"><head><title>no way</title></head><body>you weren't supposed to be here</body></html>
  • dynamic-qr-code/trunk/src/lib/phpqrcode.php

    r2997240 r3213836  
    10041004        $imgH = $h + 2*$outerFrame;
    10051005
    1006         $base_image =ImageCreate($imgW, $imgH);
     1006        $base_image = \ImageCreate($imgW, $imgH);
    10071007
    10081008        // convert a hexadecimal color code into decimal format (red = 255 0 0, green = 0 255 0, blue = 0 0 255)
     
    13401340        }
    13411341    }
    1342 };
     1342}
    13431343
    13441344//##########################################################################
     
    29072907        $this->ecc = $ecc;
    29082908    }
    2909 };
     2909}
    29102910
    29112911//##########################################################################
     
    30003000        if($this->count < $this->dataLength) {
    30013001            $row = $this->count % $this->blocks;
    3002             $col = $this->count / $this->blocks;
     3002            //$col = $this->count / $this->blocks; //sostituzione per evitare il messaggio PHP Deprecated: Implicit conversion from float to int loses precision
     3003            $col = intval($this->count / $this->blocks);
    30033004            if($col >= $this->rsblocks[0]->dataLength) {
    30043005                $row += $this->b1;
     
    30073008        } else if($this->count < $this->dataLength + $this->eccLength) {
    30083009            $row = ($this->count - $this->dataLength) % $this->blocks;
    3009             $col = ($this->count - $this->dataLength) / $this->blocks;
     3010            //$col = ($this->count - $this->dataLength) / $this->blocks; //sostituzione per evitare il messaggio PHP Deprecated: Implicit conversion from float to int loses precision
     3011            $col = intval(($this->count - $this->dataLength) / $this->blocks);
    30103012            $ret = $this->rsblocks[$row]->ecc[$col];
    30113013        } else {
     
    32703272    }
    32713273
    3272 } ;
     3274}
    32733275
    32743276//##########################################################################
    32753277
     3278#[\AllowDynamicProperties]
    32763279class QRencode {
    32773280
  • dynamic-qr-code/trunk/src/logstatus.php

    r2763042 r3213836  
    2121        $ret[self::ACTIVE] = self::getDescription(self::ACTIVE);
    2222        $ret[self::INACTIVE] = self::getDescription(self::INACTIVE);
    23         $ret[self::DISABLED] = self::getDescription(self::DISABLED);
    2423        $ret[self::EXPIRED] = self::getDescription(self::EXPIRED);
    2524        $ret[self::FINISHED] = self::getDescription(self::FINISHED);
     25        $ret[self::DISABLED] = self::getDescription(self::DISABLED);
    2626        $ret[self::ERROR] = self::getDescription(self::ERROR);
    2727
     
    3030
    3131
    32     public static function getDescription( $value ) {
    33         $ret = '';
     32    public static function getDescription( $value, $default = '' ) {
     33        $ret = $default;
    3434        switch ($value) {
    3535            case self::ACTIVE:
  • dynamic-qr-code/trunk/src/os.php

    r2763042 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
     5use SOSIDEE_DYNAMIC_QRCODE\SOS\Mobile;
     6
    57class OS
    68{
    7     const NONE = 0;
     9
     10    const UNKNOWN = 0;
    811    const ANDROID = 1;
    912    const IOS = 2;
    1013    const OTHER = 3;
    1114
     15
    1216    public static function isValid( $value ) {
    13         if ( $value != self::NONE) {
     17        if ( $value != self::UNKNOWN) {
    1418            if ( Mobile::android() ) {
    1519                return $value == self::ANDROID;
     
    2428    }
    2529
    26     public static function getList($caption = false) {
     30    public static function getList( $caption = false ) {
    2731        $ret = array();
    2832
    2933        if ($caption !== false) {
    30             $ret[self::NONE] = $caption;
     34            $ret[self::UNKNOWN] = $caption;
    3135        }
    3236        $ret[self::ANDROID] = self::getDescription(self::ANDROID);
     
    3842
    3943    public static function getDescription( $value ) {
    40         $ret = '';
     44        $ret = 'unknown';
    4145        switch ($value) {
    4246            case self::ANDROID:
  • dynamic-qr-code/trunk/src/otkey.php

    r2753631 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
    5 use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOSWP;
     5use SOSIDEE_DYNAMIC_QRCODE\SOS\WP as SOSWP;
    66
    77class OTKey
    88{
     9    use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\TBase;
    910
    1011    const COOKIENAME = 'sos_dynqrcode_ot_key';
     
    2324
    2425    public static function deleteCookie() {
    25         return SOSWP\Cookie::del( self::COOKIENAME );
     26        SOSWP\Cookie::del( self::COOKIENAME );
    2627    }
    2728
     29    public static function setJsCookieEraser() {
     30        $cookie = self::COOKIENAME;
     31        $js = "document.cookie = '{$cookie} =; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';";
     32        self::plugin()->addDeleteCookieScript( $js );
     33    }
    2834
    2935}
  • dynamic-qr-code/trunk/src/qrcode.php

    r2779336 r3213836  
    33defined( 'SOSIDEE_DYNAMIC_QRCODE' ) or die( 'you were not supposed to be here' );
    44
    5 use SOSIDEE_DYNAMIC_QRCODE\SosPlugin;
     5use SOSIDEE_DYNAMIC_QRCODE\SOS\Http\Request;
    66
    77class QrCode
    88{
     9
     10    use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\TBase;
     11    use \SOSIDEE_DYNAMIC_QRCODE\SOS\WP\TMessage;
    912
    1013    const CYPHER_LENGTH = 66;
     
    1518    const IMAGE_BACKGROUND = '#ffffff';
    1619
    17     private static function getDateTime($date, $time) {
     20    const DATETIME_MODE_FROM = 1;
     21    const DATETIME_MODE_TO = 2;
     22
     23    private static function getDateTime($date, $time, $mode) {
    1824        if ( is_null($date) && is_null($time)) {
    1925            return null;
    2026        } else {
    2127            if ( is_null($date) ) {
    22                 $date = sosidee_server_datetime();
     28                $date = sosidee_current_datetime();
    2329            }
    2430            if ( !is_null($time) ) {
    2531                $date = $date->setTime( $time->format('G'), intval($time->format('i')), intval($time->format('s')) );
    2632            } else {
    27                 $date = $date->setTime( 0, 0, 0 );
     33                if ( $mode == self::DATETIME_MODE_FROM ) {
     34                    $date = $date->setTime( 0, 0, 0 );
     35                } else if ( $mode == self::DATETIME_MODE_TO ) {
     36                    $date = $date->setTime( 23, 59, 59 );
     37                }
    2838            }
    2939            return $date;
     
    3242
    3343    public static function getStatus( $item ) {
     44        if ( $item->disabled ) {
     45            return QrCodeStatus::DISABLED;
     46        }
     47
     48        if ( $item->device_os != OS::UNKNOWN ) {
     49            if ( !OS::isValid( $item->device_os ) ) {
     50                return QrCodeStatus::DISABLED;
     51            }
     52        }
     53
     54        if ( !DotW::isValid($item->dotw) ) {
     55            return QrCodeStatus::DISABLED;
     56        }
     57
     58        $datetime_from = self::getDateTime( $item->date_from, $item->time_from, self::DATETIME_MODE_FROM);
     59        $datetime_to = self::getDateTime( $item->date_to, $item->time_to, self::DATETIME_MODE_TO);
     60        if ( !is_null($datetime_from) || !is_null($datetime_to)  ) {
     61            $now = sosidee_current_datetime();
     62            if ( !is_null($datetime_from) && $datetime_from > $now ) {
     63                return QrCodeStatus::INACTIVE;
     64            } else if ( !is_null($datetime_to) && $datetime_to < $now ) {
     65                return QrCodeStatus::EXPIRED;
     66            }
     67        }
     68
     69        if ( $item->device_lang != '' ) {
     70            $languages = Request::getLanguages();
     71            if ( is_array($languages) ) {
     72                $found = false;
     73                foreach ($languages as $lang) {
     74                    if ( $item->device_lang == $lang ) {
     75                        $found = true;
     76                        break;
     77                    }
     78                }
     79                if ( !$found ) {
     80                    return QrCodeStatus::DISABLED;
     81                }
     82            } else {
     83                if ( !$item->browser ) {
     84                    return QrCodeStatus::DISABLED;
     85                }
     86            }
     87        }
     88
     89        if ( $item->max_scan_tot > 0 ) {
     90            self::plugin()->config->sharedCodeEnabled->load();
     91            $by_key = self::plugin()->config->sharedCodeEnabled->value;
     92            if ( $by_key ) {
     93                $current = self::database()->countActiveLogsByCode( $item->code );
     94            } else {
     95                $current = self::database()->countActiveLogsById( $item->qrcode_id );
     96            }
     97            if ( $current !== false ) {
     98                if ( $current > $item->max_scan_tot ) {
     99                    return QrCodeStatus::FINISHED;
     100                }
     101            } else {
     102                if ( $by_key ) {
     103                    sosidee_log("database.countActiveLogsByCode({$item->code}) returned false.");
     104                } else {
     105                    sosidee_log("database.countActiveLogsById({$item->qrcode_id}) returned false.");
     106                }
     107            }
     108        }
     109
     110        return QrCodeStatus::ACTIVE;
     111
     112        /*
    34113        $ret = QrCodeStatus::NONE;
    35114
    36115        if ( !$item->disabled ) {
    37             if ( OS::isValid( $item->device_os) ) {
     116            if ( OS::isValid( $item->device_os ) ) {
    38117
    39118                $datetime_from = self::getDateTime( $item->date_from, $item->time_from );
     
    60139
    61140                if ( $ret == QrCodeStatus::ACTIVE && $item->max_scan_tot > 0 ) {
    62                     $plugin = SosPlugin::instance();
    63                     $current = $plugin->database->countActiveLogs( $item->code );
     141                    //$plugin = SosPlugin::instance();
     142                    //$current = $plugin->database->countActiveLogs( $item->code );
     143                    //$current = self::plugin()->database->countActiveLogs( $item->code );
     144                    $current = self::plugin()->database->countActiveLogs( $item->qrcode_id );
    64145                    if ( $current !== false ) {
    65146                        if ( $current > $item->max_scan_tot ) {
     
    72153
    73154                if ( $ret == QrCodeStatus::ACTIVE && $item->device_lang != '' ) {
    74                     $languages = Mobile::getLanguages();
     155                    $languages = Request::getLanguages();
     156                    //$languages = Mobile::getLanguages();
    75157                    if ( is_array($languages) ) {
    76158                        $found = false;
     
    94176        }
    95177        return $ret;
     178        */
    96179    }
    97180
     
    134217    private static function initializeLibrary() {
    135218        if ( !self::$initialized ) {
    136                 $plugin = SosPlugin::instance();
    137                 $folder = $plugin->getTempFolder();
    138                 self::$rootFolder = $folder['basedir'];
    139                 self::$rootUrl = $folder['baseurl'];
    140                 require_once realpath(__DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "phpqrcode.php" );
    141                 self::$initialized = true;
     219            $folder = self::plugin()->getTempFolder();
     220            self::$rootFolder = $folder['path'];
     221            self::$rootUrl = $folder['url'];
     222            require_once realpath(__DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "phpqrcode.php" );
     223            self::$initialized = true;
    142224        }
    143225    }
     
    146228        self::initializeLibrary();
    147229        $filename = "{$name}.png";
    148         $filepath = self::$rootFolder . DIRECTORY_SEPARATOR . $filename;
     230        $filepath = self::$rootFolder . $filename;
    149231
    150232        //$text = 'https://redirect.soslink.net/dynamic-qr-code/demo'; // only for the demo
     
    158240        }
    159241
    160         return self::$rootUrl . "/" . $filename;
     242        return self::$rootUrl . $filename;
    161243    }
    162244
     
    204286
    205287    public static function getNewCypher() {
    206         $plugin = SosPlugin::instance();
    207         $length = $plugin->config->cypherLength->getValue();
     288        $length = self::plugin()->config->cypherLength->getValue();
    208289        return bin2hex( random_bytes($length) );
    209290    }
     
    216297    }
    217298
     299    public static function loadQrCodeList( $caption = false, $include_cancelled = false ) {
     300        $ret = [];
     301        if ( $caption !== false ) {
     302            $ret[0] = $caption;
     303        }
     304
     305        $results = self::database()->loadQrCodeList( $include_cancelled );
     306
     307        if ( is_array($results) ) {
     308            if ( count($results) > 0 ) {
     309                for ( $n=0; $n<count($results); $n++ ) {
     310                    $ret[ $results[$n]->qrcode_id ] = $results[$n]->description;
     311                }
     312            }
     313        } else {
     314            self::msgErr( 'A problem occurred while reading the qr code list from the database.' );
     315        }
     316        return $ret;
     317    }
     318
    218319}
  • dynamic-qr-code/trunk/src/shortcode.php

    r2779336 r3213836  
    8484    }
    8585
     86    public static function getTemplate1( $id ) {
     87        $ret = '[' . self::TAG . ' ' . self::AUTH . "={$id}]";
     88        $ret .= 'content displayed to QR code scanners';
     89        $ret .= '[/' . self::TAG . ']';
     90        return $ret;
     91    }
     92
     93    public static function getTemplate2( $id, $standard ) {
     94        $ret = '[' . self::TAG . ' ' . self::DISPLAY . "={$id}";
     95        if ( $standard ) {
     96            $ret .= ' ' . self::IMAGE . '="standard"';
     97        }
     98        $ret .= ']';
     99        return $ret;
     100    }
     101
     102
    86103}
  • dynamic-qr-code/trunk/upgradenotice.txt

    r2815343 r3213836  
     1This is a major upgrade. Please back up your site before proceeding with the update.
Note: See TracChangeset for help on using the changeset viewer.