4. Multiple files upload OOP, namespaces & How to recognize mobile device – OOP, SPA, MVC domain style, PHP outside web doc root

HOME

Two scripts for multiple files upload – OOP, namespaces (see also article 10)

<?php
// 1. J:\zwamp64\vdrive\web\papl1\upload\index.php
use Classes\File\Upload; // = dir/subdir/classname 
                         // = namespace_name/clsname

// set the maximum upload size in bytes
$max = 10000 *      // 6 GB
        600 * 1024; // 600 KB
if (isset($_POST['upload'])) {
    // path to the upload folder : 
    //work: $destination = 'C:/upload_test/'; //or  __DIR__;
    $destination = DROOTPATH.DS.'FILE_TRANSFER'.DS; 
              // CONVENTION: below web doc.root
    require_once __DIR__.'/Classes/File/Upload.php'; // clsscript
    // -----------------------
    
    
    try {
        $loader = new Upload($destination);
        $loader->setMaxSize($max);
        $loader->allowAllTypes();
        $loader->upload();
        $result = $loader->getMessages();
    } catch (Exception $e) {
        echo $e->getMessage();
    }
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Multiple Upload</title>
</head>

<body>
<?php
if (isset($result)) {
    echo '<ul>';
    foreach ($result as $message) {
        echo "<li>$message</li>";
    }
    echo '</ul>';
}
?>
<form action="" method="post" enctype="multipart/form-data">
  <p>
    <label for="image">Upload files (multiple selections permitted):
    </label>
    <input type="file" name="image[]" id="imageid" multiple>
  </p>
  <p>
    <input type="submit" name="upload" id="uploadid" value="Upload">
  </p>
</form>


<h3>Upload info ($_FILES)</h3>
<pre>
<?php if (isset($_POST['upload'])) 
{
  print_r($_FILES);
?>
Error levels in $_FILES array $err = $_FILES['file']['error'];
Error level Meaning
0 Upload successful $err = UPLOAD_ERR_OK
1 File exceeds maximum upload size specified in php.ini (default 2 MB)
  UPLOAD_ERR_INI_SIZE
  upload_max_filesize in php.ini eg 6400M (=6,4 GB)
  post_max_size = 64000M
  file_uploads = On  (see Local value in phpinfo -> Core section)
  upload_tmp_dir = "j:/wamp/tmp"  or whatever, default C:\Windows\Temp
  max_file_uploads = 20  for single request
  max_execution_time  60 sekundi<br />
  max_input_time  60 sek. (parse $_POST, $_GET, $_FILE arrays)
2 File exceeds size specified by MAX_FILE_SIZE in HTML form eg 6400M
  UPLOAD_ERR_FORM_SIZE
3 File only partially uploaded UPLOAD_ERR_PARTIAL
4 Form submitted with no file specified UPLOAD_ERR_NO_FILE
Error level 5 is currently not defined.
6 No temporary folder UPLOAD_ERR_NO_TMP_DIR (no destination_path)
7 Cannot write file to disk UPLOAD_ERR_CANT_WRITE (chmod 777)
8 Upload stopped by an unspecified PHP extension UPLOAD_ERR_EXTENSION
<?php } ?>
</pre>


<h3>$_POST parameters of this page</h3>

<table>
    <tr>
        <th>Parameter name</th>
        <th>Value</th>
    </tr>
    <?php 
     $count = 0; foreach ($_POST as $name => $value) { $count++ ?>
      <tr class="<?php echo $count % 2 == 0 ? 'alt' : ''; ?>">
        <td><?php echo htmlentities(stripslashes($name)) ?></td>
        <td><?php echo nl2br(htmlentities(stripslashes($value))) ?></td>
      </tr>
    <?php } 
echo '</table>';
?>

</body>
</html>
<?php
// 2. J:\zwamp64\vdrive\web\papl1\upload\Classes\File\Upload.php
namespace Classes\File; // dir/subdir
class Upload {

    protected $uploaded = [];
    protected $destination;
    protected $max = 51200;
    protected $messages = [];
    protected $permitted = [
        'image/gif',
        'image/jpeg',
        'image/pjpeg',
        'image/png'
    ];
    protected $typeCheckingOn = true;
    protected $notTrusted = ['bin', 'cgi', 'exe', 'js', 'pl', 'php'
           , 'py', 'sh'];
    protected $suffix = '.upload';
    protected $newName;
    protected $renameDuplicates;


    public function __construct($path) {
        if (!is_dir($path) || !is_writable($path)) {
            throw new \Exception("$path must be a valid
                 , writable directory.");
        }
        $this->destination = $path;
    }

    public function upload($renameDuplicates = true) {
        $this->renameDuplicates = $renameDuplicates;
        $uploaded = current($_FILES);
        if (is_array($uploaded['name'])) {
            // deal with multiple uploads
            foreach ($uploaded['name'] as $key => $value) {
                $currentFile['name'] = $uploaded['name'][$key];
                $currentFile['type'] = $uploaded['type'][$key];
                $currentFile['tmp_name'] = $uploaded['tmp_name'][$key];
                $currentFile['error'] = $uploaded['error'][$key];
                $currentFile['size'] = $uploaded['size'][$key];
                if ($this->checkFile($currentFile)) {
                    $this->moveFile($currentFile);
                }
            }
        } else {
            if ($this->checkFile($uploaded)) {
                $this->moveFile($uploaded);
            }
        }
    }

    public function getMessages() {
        return $this->messages;
    }

    public function getMaxSize() {
        return number_format($this->max/1024, 1) . ' KB';
    }

    public function setMaxSize($num) {
        if (is_numeric($num) && $num > 0) {
            $this->max = (int) $num;
        }
    }

    public function allowAllTypes($suffix = true) {
        $this->typeCheckingOn = false;
        if (!$suffix) {
            $this->suffix = '';  // empty string
        }
    }

    protected function checkFile($file) {
        $accept = true;
        if ($file['error'] != 0) {
            $this->getErrorMessage($file);
            // stop checking if no file submitted
            if ($file['error'] == 4) {
                return false;
            } else {
                $accept = false;
            }
        }
        if (!$this->checkSize($file)) {
            $accept = false;
        }
        if ($this->typeCheckingOn) {
            if (!$this->checkType($file)) {
                $accept = false;
            }
        }
        if ($accept) {
            $this->checkName($file);
        }
        return $accept;
    }

    protected function getErrorMessage($file) {
        switch($file['error']) {
            case 1:
            case 2:
                $this->messages[] = $file['name'] . ' is too big: (max: ' .
                    $this->getMaxSize() . ').';
                break;
            case 3:
                $this->messages[] = $file['name'] 
                     . ' was only partially uploaded.';
                break;
            case 4:
                $this->messages[] = 'No file submitted.';
                break;
            default:
                $this->messages[] = 
                   'Sorry, there was a problem uploading ' 
                   . $file['name'];
                break;
        }
    }

    protected function checkSize($file) {
        if ($file['error'] == 1 || $file['error'] == 2) {
            return false;
        } elseif ($file['size'] == 0) {
            $this->messages[] = $file['name'] . ' is an empty file.';
            return false;
        } elseif ($file['size'] > $this->max) {
            $this->messages[] = $file['name'] 
                     . ' exceeds the maximum size
                for a file (' . $this->getMaxSize() . ').';
            return false;
        } else {
            return true;
        }
    }

    protected function checkType($file) {
        if (in_array($file['type'], $this->permitted)) {
            return true;
        } else {
            if (!empty($file['type'])) {
                $this->messages[] = $file['name'] 
                    . ' is not permitted type of file.';
            }
            return false;
        }
    }

    protected function checkName($file) {
        $this->newName = null;
        $nospaces = str_replace(' ', '_', $file['name']);
        if ($nospaces != $file['name']) {
            $this->newName = $nospaces;
        }
        $extension = pathinfo($nospaces, PATHINFO_EXTENSION);
        if (!$this->typeCheckingOn && !empty($this->suffix)) {
            if (in_array($extension
                  , $this->notTrusted) || empty($extension)) {
                $this->newName = $nospaces . $this->suffix;
            }
        }
        if ($this->renameDuplicates) {
            $name = isset($this->newName) 
                       ? $this->newName : $file['name'];
            $existing = scandir($this->destination);
            if (in_array($name, $existing)) {
                // rename file
                $basename = pathinfo($name, PATHINFO_FILENAME);
                $extension = pathinfo($name, PATHINFO_EXTENSION);
                $i = 1;
                do {
                    $this->newName = $basename . '_' . $i++;
                    if (!empty($extension)) {
                        $this->newName .= ".$extension";
                    }
                } while (in_array($this->newName, $existing));
            }
        }
    }

    protected function moveFile($file) {
        $filename = isset($this->newName) 
                ? $this->newName : $file['name'];
        $success = move_uploaded_file($file['tmp_name']
              , $this->destination . $filename);
        if ($success) {
            $result = $file['name'] . ' was uploaded successfully to '
              . 'server directory : <br />'. $this->destination ;
            if (!is_null($this->newName)) {
                $result .= ', and was renamed ' . $this->newName;
            }
            $this->messages[] = $result;
        } else {
            $this->messages[] = 'Could not upload ' . $file['name'];
        }
    }
}

How to recognize mobile device – non OOP code

Excellent code to learn object oriented programming, model-view-controller code separation (structured programming), single page application (require scripts, not URL them), most code outside Apache doc root.

function findDevice() {
    $userAgent=strtolower($_SERVER['HTTP_USER_AGENT']);
$device=array('iphone','ipad','android','silk','blackberry', 'touch');
$deviceLength=count($device);

for($ii=0;$ii < $deviceLength;$ii ++) {
if(strstr($userAgent, $device[$ii])) {
return $device[$ii];
} else return 'desktop/laptop';
}
}

OOP, SPA, MVC domain style, PHP outside web doc root

Display ibrowser properties (view class methode):

  1. Device = desktop/laptop
  2. Browser = firefox
  3. userAgent = mozilla/5.0 (windows nt 6.3; win64; x64; rv:25.3) gecko/20150323 firefox/31.9 palemoon/25.3.1

Or display one property – returned from getter: Device = desktop/laptop

About OOP programs

  1. CODE INSIDE APACHE DOC ROOT (this page script) :  kod  edit  phpinfo
    INCLUDED CODE FROM OUTSIDE APACHE DOC ROOT :
  2. code behind this page script (model .pcls) :  kod  edit  phpinfo
  3. code config – set up :  kod  edit  phpinfo
  4. code helper (util) :  kod  edit  phpinfo
  5. /**
    * This page URL $idxurl = 
    *    http://dev:8083/inc/utl/get_ibrowser_device.php
    *   displays o u t p u t  o f  server script 
    *          $idx.DS.$idxscript =
    *   J:\dev_web\htdocs\inc\utl\get_ibrowser_device.php, 
    *           which contains :
    *      MODEL_fn_call from public fn __ c o n s t r u c t ( )
    *      protected_VIEW_fn_call from public fn
    *      CONTROLLER_code before c l a s s  C l i e n t
    *
    * server script i n c l u d e s scripts which are outside Apache doc root :
    *   1. config $confglob                : require_once('J:\dev_web\inc\confglob.php');
    *   2. helper (util) $edrun            : require_once('J:\dev_web\inc\utl\kod_edit_run.php');
    *   3. code behind (class) $codebehind : require_once('J:\dev_web\inc\utl\get_ibrowser_device.pcls');
    *
    * $confglob contains  P H P  s e t  u p :
    *    ini_set('display_errors','2');
    *    ERROR_REPORTING(E_ALL);
    **/

SCRIPTS:

  1. J:\dev_web\htdocs\inc\utl\get_ibrowser_device.php
    // 1. a d r e s s e s :
    if (!defined('DS')) define('DS',DIRECTORY_SEPARATOR);
    if (!defined('CONFGLOB_DIR')) define('CONFGLOB_DIR',
    realpath($_SERVER['DOCUMENT_ROOT'].'/../inc'));
    $apl = dirname(dirname(__DIR__)).DS.’htdocs’; // *** !!! *** ONLY YOU TO SET UP, used for link
    $idx = __DIR__ ; $idxscript = basename(__FILE__) ;// 2. i n c l u d e s :
    $confglob   = CONFGLOB_DIR.DS.’confglob.php’;
    $edrun      = CONFGLOB_DIR.DS.’utl’.DS.’kod_edit_run.php’;
    $codebehind = CONFGLOB_DIR.DS.’utl’.DS.’get_ibrowser_device.pcls’;
    require_once($confglob);   // c o n f i g
    require_once($edrun);      // h e l p e r
    require_once($codebehind); // m o d e l// 3. c o n t r o l l e r :
    $trigger = new Client(); // trigger becouse can direct output view// ************** e n d  c o n t r o l l e r  p r o g r a m// v i e w :
    ?>
    <!DOCTYPE html>
    <html lang=”hr”>
    <head>
    <title>Is mobile</title>
    <meta content=”text/html; charset=utf-8″; http-equiv=”content-type”>
    <!–base href=’/’–>
    <link rel=’stylesheet’ href=’lib/bootstrap/dist/css/bootstrap.min.css’ />
    <link rel=’stylesheet’ href=’src/bootstrap.min.css’ />
    </head>
    <body><h2>How to recognize mobile device – non OOP code</h2>
    <p><code><code><span style=”color:#000000; “><span style=”color:#007700; “>function </span><span style=”color:#0000BB; “>findDevice</span><span style=”color:#007700; “>() {<br>
    </span></span><code><span style=”color:#000000; “><span style=”color:#007700; “>    $</span><span style=”color:#0000BB; “>userAgent</span><span style=”color:#007700; “>=</span><span style=”color:#0000BB; “>strtolower</span><span style=”color:#007700; “>(</span><span style=”color:#0000BB; “>$_SERVER</span><span style=”color:#007700; “>[</span><span style=”color:#DD0000; “>’HTTP_USER_AGENT'</span><span style=”color:#007700; “>]);<br>
    </span><span style=”color:#FF8000; “>
    </span><span style=”color:#007700; “>$</span><span style=”color:#0000BB; “>device</span><span style=”color:#007700; “>=array(</span><span style=”color:#DD0000; “>’iphone'</span><span style=”color:#007700; “>,</span><span style=”color:#DD0000; “>’ipad'</span><span style=”color:#007700; “>,</span><span style=”color:#DD0000; “>’android'</span><span style=”color:#007700; “>,</span><span style=”color:#DD0000; “>’silk'</span><span style=”color:#007700; “>,</span><span style=”color:#DD0000; “>’blackberry'</span><span style=”color:#007700; “>, </span><span style=”color:#DD0000; “>’touch'</span><span style=”color:#007700; “>);<br>$</span><span style=”color:#0000BB; “>deviceLength</span><span style=”color:#007700; “>=</span><span style=”color:#0000BB; “>count</span><span style=”color:#007700; “>($</span><span style=”color:#0000BB; “>device</span><span style=”color:#007700; “>);<br>
    </span></span></code><span style=”color:#000000; “><span style=”color:#007700; “><br>
    for(</span><span style=”color:#0000BB; “>$ii</span><span style=”color:#007700; “>=</span><span style=”color:#0000BB; “>0</span><span style=”color:#007700; “>;</span><span style=”color:#0000BB; “>$ii </span><span style=”color:#007700; “>&lt; $</span><span style=”color:#0000BB; “>deviceLength</span><span style=”color:#007700; “>;</span><span style=”color:#0000BB; “>$ii </span><span style=”color:#007700; “>++) {<br>
    if(</span><span style=”color:#0000BB; “>strstr</span><span style=”color:#007700; “>($</span><span style=”color:#0000BB; “>userAgent</span><span style=”color:#007700; “>, $</span><span style=”color:#0000BB; “>device</span><span style=”color:#007700; “>[</span><span style=”color:#0000BB; “>$ii</span><span style=”color:#007700; “>])) {<br>
    </span><span style=”color:#FF8000; “>        </span><span style=”color:#007700; “>return $</span><span style=”color:#0000BB; “>device</span><span style=”color:#007700; “>[</span><span style=”color:#0000BB; “>$ii</span><span style=”color:#007700; “>];<br>
    } else return </span><span style=”color:#DD0000; “>’desktop/laptop'</span><span style=”color:#007700; “>;<br>
    }<br>
    }</span></span></code></code></p>
    <h2>OOP, SPA, MVC domain style, PHP outside web doc root</h2>
    <p>Display ibrowser properties (view class methode):<br />
    <?php $trigger -> out_vew_ibrowse_params() ; ?>
    </p>

    <p>Or display one property – returned from getter: Device =
    <?php echo $trigger->get_device(); ?> </p>

    <h2>About OOP programs</h2>
    <ol>
    <li>CODE INSIDE APACHE DOC ROOT (this page script) :
    <?php kod_edit_run(
    $idx       // script_dir
    , $idxscript // script
    , MDURL); ?>
    <br>
    <br>
    INCLUDED CODE FROM OUTSIDE APACHE DOC ROOT : <br>
    <li>code behind this page script (model .pcls) :
    <?php kod_edit_run(
    dirname($codebehind)  // script_dir
    , basename($codebehind) // script
    , MDURL); ?>
    <li> code config – set up :
    <?php kod_edit_run(
    dirname($confglob)  // script_dir
    , basename($confglob) // script
    , MDURL); ?>
    <li>code helper (util) :
    <?php kod_edit_run(
    dirname($edrun)  // script_dir
    , basename($edrun) // script
    , MDURL); ?>
    <li> <pre>/**
    * This page URL $idxurl = <a href=”<?php echo $idxurl; ?>”><?php echo $idxurl; ?><a>
    *   displays o u t p u t  o f  server script $idx.DS.$idxscript =
    *   <?php echo $idx.DS.$idxscript; ?>, which contains :
    *      MODEL_fn_call from public fn __ c o n s t r u c t ( )
    *      protected_VIEW_fn_call from public fn
    *      CONTROLLER_code before c l a s s  C l i e n t
    *
    * server script i n c l u d e s scripts which are outside Apache doc root :
    *   1. config $confglob                : require_once(‘<?php echo $confglob; ?>’);
    *   2. helper (util) $edrun            : require_once(‘<?php echo $edrun; ?>’);
    *   3. code behind (class) $codebehind : require_once(‘<?php echo $codebehind; ?>’);
    *
    * $confglob contains  P H P  s e t  u p :
    *    ini_set(‘display_errors’,’2′);
    *    ERROR_REPORTING(E_ALL);
    **/ </pre>
    </ol>

    <?php
    class Client
    {
    private $IbrowserProp;

    // M O D E L :
    public function __construct()   {
    $this->IbrowserProp = new getIbrowserProp();
    } // e n d  p u b l i c  f n  _ _c o n s t r u c t ( )

    public function get_device() {
    return  $this->IbrowserProp->findDevice() ;
    } // e n d

    // V I E W :
    public function out_vew_ibrowse_params() {
    $this->vew_ibrowse_params();
    } // e n d
    protected function vew_ibrowse_params()  // public private protected
    {
    echo ‘<ol>’;
    echo ‘<li>Device = ‘    . $this->IbrowserProp->findDevice() . ‘<br/>’;
    echo ‘<li>Browser = ‘   . $this->IbrowserProp->findBrowser() . ‘<br/>’;
    echo ‘<li>userAgent = ‘ . $this->IbrowserProp->getUserAgent() . ‘<br/>’;
    echo ‘</ol>’;
    } // e n d  p u b l i c  f n  _ _c o n s t r u c t ( )

    } // e n d  c l a s s  C l i e n t

    ?>
    </body>
    </html>

  2. J:\dev_web\inc\utl\get_ibrowser_device.pcls
    <?php
    ini_set("display_errors","2");
    ERROR_REPORTING(E_ALL);
    //User agent as property of object
    class getIbrowserProp
    {
    private $userAgent;
    private $device;
    private $browser;
    private $deviceLength;
    private $browserLength;
    public function __construct()
    {
    $this->userAgent=strtolower($_SERVER[‘HTTP_USER_AGENT’]);
    //$this->userAgent=strtolower($this->userAgent);$this->device=array(‘iphone’,’ipad’,’android’,’silk’,’blackberry’, ‘touch’);
    $this->browser= array(‘firefox’,’chrome’,’opera’,’msie’,’safari’,’blackberry’,’trident’);
    $this->deviceLength=count($this->device);
    $this->browserLength=count($this->browser);
    }
    public function findDevice()
    {
    for($ii=0;$ii < $this->deviceLength;$ii ++)
    {
    if(strstr($this->userAgent,$this->device[$ii]))
    {
    //$device = $this->device[$ii];
    //if (is_null($device)) $device = ‘desktop/laptop’;
    //return $device;
    return $this->device[$ii];
    } else return ‘desktop/laptop’;
    }
    }//public function get_device() {
    //    return $this->vew_ibrowse_params();
    //} // e n dpublic function findBrowser()
    {
    for($ii=0;$ii < $this->browserLength;$ii ++)
    {
    if(strstr($this->userAgent,$this->browser[$ii]))
    {
    return $this->browser[$ii];
    }
    }
    }
    public function getUserAgent()
    {
    return($this->userAgent);
    }
    }?>
  3. J:\dev_web\inc\confglob.php
    <?php
    // J:\dev_web\inc\confglob.php - NOT WEB ACCESSIBLE
    //    - SAME LEVEL AS APACHE DOC ROOT
    ini_set("display_errors","2");
    ERROR_REPORTING(E_ALL);
    $md=realpath($_SERVER[‘DOCUMENT_ROOT’]);// 1. rel.adresses are ok for both  p a t h s  &   u r l s :
    $idxrel = str_replace($md,”, $idx); // str_replace(DS,’/’,
    $aplrel = str_replace($md,”, $apl); // str_replace(DS,’/’,// 2. u r l s  – s u b a p l,  a p l,  m d (main doc.root = Apache doc.root):
    $mdurl =’http://’.$_SERVER[“SERVER_NAME”].’:’.$_SERVER[“SERVER_PORT”];
    if (!defined(‘MDURL’)) define(‘MDURL’, $mdurl);
    $idxurl = $mdurl.str_replace(DS,’/’,$idxrel).’/’.$idxscript;
    $aplurl = $mdurl.’/’.substr(str_replace(DS,’/’,$aplrel),1);
    $imgurl = $mdurl.’/inc/img’;
  4. J:\dev_web\inc\utl\kod_edit_run.php
    <?php
    function kod_edit_run($script_dir_path, $script_name, $web_docroot_url)
    {
    $ds = DIRECTORY_SEPARATOR;
    echo <<< EOKOD
    <a href="$web_docroot_url/inc/utl/showsource.php
    ?file=$script_dir_path$ds$script_name
    &line=1&prev=10000&next=10000
    "  target="_blank">&nbsp;kod</a>
    <a href=”$web_docroot_url/inc/utl/edservertxt.php
    ?file=$script_dir_path$ds$script_name
    ” target=”_blank”>&nbsp;edit</a><a href=”$web_docroot_url/phpinfo_inc.php
    ” target=”_blank”>&nbsp;phpinfo</a>
    EOKOD;
    /* call it so:
    kod_edit_run(
    $idx       // script_dir_path
    , $idxscript // script_name
    , MDURL);    // web_docroot_url = (Apache) web server URL
    */
    }