From a6202230d6c8890dc0ff393f049bad71a1efabde Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Mon, 18 Apr 2016 11:30:38 +0200 Subject: [PATCH] =?UTF-8?q?Ordre=20des=20param=C3=A8tres=20quelconque=20po?= =?UTF-8?q?ur=20ModuleRequest();=20Youhou!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manager/ModuleRequest.php | 2 +- manager/module/call_log.php | 15 +- manager/module/charts.php | 8 +- manager/module/module.php | 17 +- manager/module/token.php | 14 +- manager/module/user.php | 20 +- phpunit/coverage/Database.php.html | 18 +- phpunit/coverage/ManagerError.php.html | 2 +- phpunit/coverage/ResourceDispatcher.php.html | 94 ++-- phpunit/coverage/autoloader.php.html | 14 +- phpunit/coverage/index.html | 94 +++- phpunit/coverage/sessionManager.php.html | 2 +- phpunit/tests/ModuleRequest.php | 22 + tags | 429 ++++++++++++++----- 14 files changed, 526 insertions(+), 225 deletions(-) diff --git a/manager/ModuleRequest.php b/manager/ModuleRequest.php index 625f705..6a3fffb 100755 --- a/manager/ModuleRequest.php +++ b/manager/ModuleRequest.php @@ -118,7 +118,7 @@ /* [3] On amorce la methode =========================================================*/ - $returned = call_user_func_array( $this->getFunctionCaller(), $this->params ); + $returned = call_user_func( $this->getFunctionCaller(), $this->params ); /* [4] Gestion de la reponse diff --git a/manager/module/call_log.php b/manager/module/call_log.php index 65173ee..5aad1d9 100644 --- a/manager/module/call_log.php +++ b/manager/module/call_log.php @@ -18,8 +18,11 @@ * @return contact Retourne un tableau associatif contenant les correspondances numero/nom de contact * */ - public static function unserialize($content=null){ - /* [2] On recupere le xml + public static function unserialize($params){ + $content = null; + extract($params); + + /* [2] On recupere le xml =========================================================*/ $xml = simplexml_load_string($content); @@ -58,7 +61,7 @@ $msms[$num]+= 1; else $msms[$num] = 1; - + // On enregistre le nom si c'est pas fait if( !isset($names[$num]) ) $names[$num] = $log['Name']; @@ -70,9 +73,9 @@ // Sinon on incremente son nombre d'apparition if( isset($call[$num]) ) $call[$num]+= 1; - else + else $call[$num] = 1; - + // On enregistre le nom si c'est pas fait if( !isset($names[$num]) ) $names[$num] = $log['Name']; @@ -122,4 +125,4 @@ } -?> \ No newline at end of file +?> diff --git a/manager/module/charts.php b/manager/module/charts.php index 531917f..6b08c94 100755 --- a/manager/module/charts.php +++ b/manager/module/charts.php @@ -28,7 +28,9 @@ * @return render Contenu du svg representation graphique des donnees * */ - public static function network_render($data){ + public static function network_render($params){ + extract($params); + return networkChart::render($data); } @@ -36,7 +38,7 @@ - + @@ -45,4 +47,4 @@ } -?> \ No newline at end of file +?> diff --git a/manager/module/module.php b/manager/module/module.php index 3c2e195..43002d1 100644 --- a/manager/module/module.php +++ b/manager/module/module.php @@ -6,14 +6,23 @@ class module{ public static function method(){ - // On recupère les arguments - $arguments = func_get_args(); + + return array( + 'ModuleError' => ManagerError::Success, + 'ReceivedArguments' => func_get_args() + ); + + } + + + public static function phpunitParams($params){ + extract($params); return array( 'ModuleError' => ManagerError::Success, - 'ReceivedArguments' => $arguments + 'p1' => $p1, + 'p2' => $p2 ); - } diff --git a/manager/module/token.php b/manager/module/token.php index 6f96a38..6ddbcfa 100755 --- a/manager/module/token.php +++ b/manager/module/token.php @@ -17,7 +17,9 @@ * @id_token UID du token en question * */ - public static function remove($id_token){ + public static function remove($params){ + extract($params); + /* [1] Suppression du token =========================================================*/ $remove = new Repo('token/remove', array($id_token)); @@ -44,13 +46,15 @@ * @return FALSE Renvoie FALSE si erreur * */ - public static function generate($name, $duration){ + public static function generate($params){ + extract($params); + /* [0] Verification des INPUT =========================================================*/ if( !Database::check('varchar(50)', $name) || !Database::check('numeric', $duration) ) return array('ModuleError' => ManagerError::ParamError); // erreur de parametre - + /* [1] On cree le token et recupere son id ou FAUX =========================================================*/ $create = new Repo('token/generate', array($name, $duration)); @@ -73,7 +77,7 @@ - + @@ -82,4 +86,4 @@ } -?> \ No newline at end of file +?> diff --git a/manager/module/user.php b/manager/module/user.php index 606e256..9daa673 100755 --- a/manager/module/user.php +++ b/manager/module/user.php @@ -17,7 +17,9 @@ * @return id_user Retourne l'id de l'utilisateur si les logins sont corrects * */ - public static function login($login, $password){ + public static function login($params){ + extract($params); + /* [1] On verifie les logins =========================================================*/ $check = new Repo('user/login', array($login, $password)); @@ -35,7 +37,7 @@ /* [4] Retour de l'id user =========================================================*/ - + return array( 'ModuleError' => ManagerError::Success, 'id_user' => $user['id_user'] @@ -64,7 +66,9 @@ * @return user Tableau contenant les informations de l'utilisateur * */ - public static function getById($user_id){ + public static function getById($params){ + extract($params); + /* [1] On recupere les donnees de l'utilisateur =========================================================*/ $getUser = new Repo('user/getById', array($user_id)); @@ -131,7 +135,9 @@ * @return id_user Renvoie l'id de l'utilisateur cree * */ - public static function create($login, $password, $mail, $reference, $permissions){ + public static function create($params){ + extract($params); + /* [0] Verification et formattage des INPUT =========================================================*/ $password = sessionManager::sha1($password); @@ -163,7 +169,9 @@ * @id_user UID de l'utilisateur en question * */ - public static function remove($id_user){ + public static function remove($params){ + extract($params); + /* [1] On verifie que l'utilisateur existe =========================================================*/ $exists = new Repo('user/getById', array($id_user)); @@ -202,4 +210,4 @@ } -?> \ No newline at end of file +?> diff --git a/phpunit/coverage/Database.php.html b/phpunit/coverage/Database.php.html index e49482d..7df64ec 100755 --- a/phpunit/coverage/Database.php.html +++ b/phpunit/coverage/Database.php.html @@ -435,17 +435,17 @@         *         */         public static function check($type, $value){ -             $checker = true; +             $checker = true;             /* [0] On verifie que $value n'est pas nul             =========================================================*/ -             if( is_null($value) ) return false; +             if( is_null($value) ) return false;             /* [1] Si de type VARCHAR(min, max)             =========================================================*/ -             if( preg_match('/^varchar\((\d+), ?(\d+)\)$/', $type, $match) ){ +             if( preg_match('/^varchar\((\d+), ?(\d+)\)$/', $type, $match) ){                 // On recupere la taille min                 $min = (int) $match[1];                 // On recupere la taille max @@ -458,7 +458,7 @@             /* [2] Si de type ARRAY(type_elements)             =========================================================*/ -             if( preg_match('/^array<(.+)>$/', $type, $match) ){ +             if( preg_match('/^array<(.+)>$/', $type, $match) ){                 // Si c'est pas un tableau on retourne une erreur                 if( !is_array($value) )                     return false; @@ -480,13 +480,13 @@             =========================================================*/                         switch($type){                 // Entier positif (id dans BDD) -                 case 'id': -                     return $checker && is_numeric($value) && $value <= 2147483647 && $value >= 0; +                 case 'id': +                     return $checker && is_numeric($value) && $value <= 2147483647 && $value >= 0;                     break;                 // String quelconque (peut etre vide) -                 case 'text': -                     return $checker && is_string($value); +                 case 'text': +                     return $checker && is_string($value);                 // Adresse mail (255 caracteres max)                 case 'mail': @@ -559,7 +559,7 @@ Dead Code

- Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:04:04 UTC 2016. + Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:29:41 UTC 2016.

diff --git a/phpunit/coverage/ManagerError.php.html b/phpunit/coverage/ManagerError.php.html index 3745a17..1005715 100755 --- a/phpunit/coverage/ManagerError.php.html +++ b/phpunit/coverage/ManagerError.php.html @@ -247,7 +247,7 @@ Dead Code

- Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:04:04 UTC 2016. + Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:29:41 UTC 2016.

diff --git a/phpunit/coverage/ResourceDispatcher.php.html b/phpunit/coverage/ResourceDispatcher.php.html index 6a9a653..e01e245 100755 --- a/phpunit/coverage/ResourceDispatcher.php.html +++ b/phpunit/coverage/ResourceDispatcher.php.html @@ -262,49 +262,49 @@         *         */         public function __construct($url, $view=false){ -             $this->error = ManagerError::Success; +             $this->error = ManagerError::Success;             /* [0] On met a jour la configuration             =====================================================*/             // Extensions supportees -             $extensions_conf = json_decode( file_get_contents(__ROOT__.self::$extension_config_path), true ); +             $extensions_conf = json_decode( file_get_contents(__ROOT__.self::$extension_config_path), true );             // Gestion de l'erreur de parsage -             if( $extensions_conf == null ){ +             if( $extensions_conf == null ){                 $this->error = ManagerError::ParsingFailed;                 return false;             } -             self::$supported_extensions = $extensions_conf; +             self::$supported_extensions = $extensions_conf;             // Dossiers supportes -             $parents_conf = json_decode( file_get_contents(__ROOT__.self::$parents_config_path), true ); +             $parents_conf = json_decode( file_get_contents(__ROOT__.self::$parents_config_path), true );                          // Gestion de l'erreur de parsage -             if( $parents_conf == null ){ +             if( $parents_conf == null ){                 $this->error = ManagerError::ParsingFailed;                 return false;             } -             self::$supported_parents = $parents_conf; +             self::$supported_parents = $parents_conf;             /* [1] On recupere les donnees de l'URL             ==================================================*/ -             $serialFlags = array_slice( explode('/',$url), 1 ); +             $serialFlags = array_slice( explode('/',$url), 1 );             /* [2] On check/cree les drapeaux avec ces donnees             ==================================================*/ -             if( !$this->createFlags($serialFlags) ){ // Creation des drapeaux +             if( !$this->createFlags($serialFlags) ){ // Creation des drapeaux                 $this->error = ManagerError::InvalidFlags;                 return false;             }             /* [3] On construit le chemin a partir des tags             ==================================================*/ -             if( !$this->buildPath() ){ // Construction du chemin +             if( !$this->buildPath() ){ // Construction du chemin                 $this->error = ManagerError::UnreachableResource;                 return false;             } @@ -312,10 +312,10 @@             /* [4] On gere l'affichage pour l'appel externe/interne             ==================================================*/             if( $view ) // Appel externe -                 $this->view(); +                 $this->view();              -             return true; +             return true;         } @@ -328,8 +328,8 @@         *         */         public static function getResource($route){ -             $instance = new ResourceDispatcher($route); -             return $instance->getContent(); +             $instance = new ResourceDispatcher($route); +             return $instance->getContent();         } @@ -345,51 +345,51 @@             /* [1] Verification des flags (version serialisee)             ======================================================*/ -             $correct = true; +             $correct = true;             // Verification du nombre de drapeaux () au moins 3 -             $correct = $correct && count($serialFlags) >= 3; +             $correct = $correct && count($serialFlags) >= 3;             // Verification que l'extension est correcte -             $correct = $correct && array_key_exists($serialFlags[0], self::$supported_extensions); +             $correct = $correct && array_key_exists($serialFlags[0], self::$supported_extensions);             // Verification du filename -             $correct = $correct && preg_match('/^[\w_\.-]+$/i', $serialFlags[1]); +             $correct = $correct && preg_match('/^[\w_\.-]+$/i', $serialFlags[1]);             // Verification du parent -             $correct = $correct && array_key_exists($serialFlags[2], self::$supported_parents); +             $correct = $correct && array_key_exists($serialFlags[2], self::$supported_parents);             // Verification du sous-parent (optionnel) -             $opt_subParent = count($serialFlags) >= 4; +             $opt_subParent = count($serialFlags) >= 4;             if( $opt_subParent ) -                 $correct = $correct && preg_match('/^[\w_-]+$/i', $serialFlags[3]); +                 $correct = $correct && preg_match('/^[\w_-]+$/i', $serialFlags[3]);             // Verification de la couleur (optionnel) -             $opt_color = count($serialFlags) >= 5 && preg_match('/^[\da-f]{6,8}+$/i', $serialFlags[4]); +             $opt_color = count($serialFlags) >= 5 && preg_match('/^[\da-f]{6,8}+$/i', $serialFlags[4]); -             if( !$correct ) -                 return false; +             if( !$correct ) +                 return false;                              /* [2] Creation (non serialisee) des flags             ======================================================*/             // Si tout se deroule bien, on cree les flags -             $this->flags = array( -                 'extension' => $serialFlags[0], -                 'filename'  => $serialFlags[1], -                 'parent'    => $serialFlags[2] -             ); +             $this->flags = array( +                 'extension' => $serialFlags[0], +                 'filename'  => $serialFlags[1], +                 'parent'    => $serialFlags[2] +             );             // Ajout du sous-parent optionnel             if( $opt_subParent ) -                 $this->flags['subparent'] = $serialFlags[3]; +                 $this->flags['subparent'] = $serialFlags[3];             // Ajout du color optionnel             if( $opt_color ) -                 $this->flags['color'] = '#'.$serialFlags[4]; +                 $this->flags['color'] = '#'.$serialFlags[4]; -             return true; +             return true;         } @@ -408,10 +408,10 @@             /* [1] On recupere le HEADER associe a l'extension             ==========================================================*/             // Si aucun header pour cet cle, on retourne une erreur -             if( !isset(self::$supported_extensions[$this->flags['extension']]) ) return false; +             if( !isset(self::$supported_extensions[$this->flags['extension']]) ) return false;             // On recupere le header associe -             $header = self::$supported_extensions[$this->flags['extension']]; +             $header = self::$supported_extensions[$this->flags['extension']]; @@ -420,23 +420,23 @@             /* [2] On recupere le chemin associe au parent             ==========================================================*/             // Si aucun dossier pour cet indice, on retourne une erreur -             if( !isset(self::$supported_parents[$this->flags['parent']]) ) return false; +             if( !isset(self::$supported_parents[$this->flags['parent']]) ) return false;             // On recupere le dossier associe -             $parent = self::$supported_parents[$this->flags['parent']]; +             $parent = self::$supported_parents[$this->flags['parent']];             /* [3] Gestion du sous-parent optionnel             ==========================================================*/ -             $opt_subParent = (isset($this->flags['subparent'])) ? $this->flags['subparent'].'/' : ''; +             $opt_subParent = (isset($this->flags['subparent'])) ? $this->flags['subparent'].'/' : '';             /* [4] Gestion du color optionnel             =========================================================*/ -             $this->stylesheet = ""; +             $this->stylesheet = "";             // si le color est defini -             if( isset($this->flags['color']) ){ +             if( isset($this->flags['color']) ){                 $this->stylesheet = "\n<style type='text/css'>\n";                     $this->stylesheet .= "\t#stylisable{\n";                         $this->stylesheet .= "\t\tfill: ".$this->flags['color']." !important;\n"; @@ -449,15 +449,15 @@             /* [5] On definit le header             ==========================================================*/ -             $this->header = $header; +             $this->header = $header;             /* [6] On construit le chemin              ==========================================================*/ -             $this->path = __ROOT__.$parent.'/'.$opt_subParent.$this->flags['filename'].'.'.$this->flags['extension']; +             $this->path = __ROOT__.$parent.'/'.$opt_subParent.$this->flags['filename'].'.'.$this->flags['extension'];             /* [7] On retourne si le fichier existe ou non             ==========================================================*/ -             return @file_get_contents( $this->path ) != false; +             return @file_get_contents( $this->path ) != false;         } @@ -489,15 +489,15 @@         */         public function getContent(){             // S'il y a eu une erreur en amont -             if( $this->error != ManagerError::Success ) -                 return false; // on retourne faux +             if( $this->error != ManagerError::Success ) +                 return false; // on retourne faux             // On inclut le contenu -             $content = file_get_contents($this->path); +             $content = file_get_contents($this->path);             // On retourne tout -             return str_replace( '</svg>', $this->stylesheet.'</svg>', $content ); +             return str_replace( '</svg>', $this->stylesheet.'</svg>', $content );         } @@ -517,7 +517,7 @@ Dead Code

- Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:04:04 UTC 2016. + Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:29:41 UTC 2016.

diff --git a/phpunit/coverage/autoloader.php.html b/phpunit/coverage/autoloader.php.html index 725a46a..04ed2cb 100755 --- a/phpunit/coverage/autoloader.php.html +++ b/phpunit/coverage/autoloader.php.html @@ -167,19 +167,19 @@     *     */     function autoloader($className){ -         $path = ''; +         $path = '';         /* [1] On utilise le namespace pour localiser         ===============================================*/         // On remplace les '\' par des '/' -         $path = str_replace('\\', '/', $className) . '.php'; -         $path = __ROOT__.'/'.$path; +         $path = str_replace('\\', '/', $className) . '.php'; +         $path = __ROOT__.'/'.$path;         // Si le fichier existe -         if( file_exists($path) ) -             require_once $path; // on inclue le fichier +         if( file_exists($path) ) +             require_once $path; // on inclue le fichier -     } +     }          // On definit l'autoloader comme autoloader (obvious)     spl_autoload_register('autoloader', false, true); @@ -214,7 +214,7 @@ Dead Code

- Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:04:04 UTC 2016. + Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:29:41 UTC 2016.

diff --git a/phpunit/coverage/index.html b/phpunit/coverage/index.html index 0981eb5..fa41039 100755 --- a/phpunit/coverage/index.html +++ b/phpunit/coverage/index.html @@ -43,29 +43,57 @@ Total
-
- 66.21% covered (warning) +
+ 67.51% covered (warning)
-
66.21%
-
241 / 364
+
67.51%
+
266 / 394
-
- 44.44% covered (danger) +
+ 47.73% covered (danger)
-
44.44%
-
16 / 36
+
47.73%
+
21 / 44
-
- 14.29% covered (danger) +
+ 11.11% covered (danger)
-
14.29%
-
1 / 7
+
11.11%
+
1 / 9
+ + + + module +
+
+ 57.14% covered (warning) +
+
+ +
57.14%
+
4 / 7
+
+
+ 50.00% covered (danger) +
+
+ +
50.00%
+
1 / 2
+
+
+ 0.00% covered (danger) +
+
+ +
0.00%
+
0 / 1
@@ -153,15 +181,15 @@ - ModuleRequest.php + ModuleAnswer.php
-
- 77.27% covered (warning) +
+ 56.52% covered (warning)
-
77.27%
-
68 / 88
+
56.52%
+
13 / 23
50.00% covered (danger) @@ -169,7 +197,35 @@
50.00%
-
4 / 8
+
3 / 6
+
+
+ 0.00% covered (danger) +
+
+ +
0.00%
+
0 / 1
+ + + + ModuleRequest.php +
+
+ 86.36% covered (warning) +
+
+ +
86.36%
+
76 / 88
+
+
+ 62.50% covered (warning) +
+
+ +
62.50%
+
5 / 8
0.00% covered (danger) @@ -294,7 +350,7 @@ High: 90% to 100%

- Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:04:04 UTC 2016. + Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:29:41 UTC 2016.

diff --git a/phpunit/coverage/sessionManager.php.html b/phpunit/coverage/sessionManager.php.html index 2242773..30b5ca7 100755 --- a/phpunit/coverage/sessionManager.php.html +++ b/phpunit/coverage/sessionManager.php.html @@ -315,7 +315,7 @@ Dead Code

- Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:04:04 UTC 2016. + Generated by PHP_CodeCoverage 2.1.7 using PHP 5.6.11-1ubuntu3.1 and PHPUnit 4.7.6 at Mon Apr 18 9:29:41 UTC 2016.

diff --git a/phpunit/tests/ModuleRequest.php b/phpunit/tests/ModuleRequest.php index f725ee5..f7c5b31 100644 --- a/phpunit/tests/ModuleRequest.php +++ b/phpunit/tests/ModuleRequest.php @@ -143,6 +143,28 @@ $req = new \manager\ModuleRequest( 'module/phpunitParams', $params ); $this->assertEquals( $req->error, \manager\ManagerError::Success ); } + public function testConstructParamOrdered(){ + $_SESSION['permission'] = array(); + + $params = array( 'p1' => 'sometext', 'p2' => 10 ); + + $req = new \manager\ModuleRequest( 'module/phpunitParams', $params ); + $ans = $req->dispatch(); + + $this->assertEquals( $ans->get('p1'), $params['p1'] ); + $this->assertEquals( $ans->get('p2'), $params['p2'] ); + } + public function testConstructParamUnordered(){ + $_SESSION['permission'] = array(); + + $params = array( 'p2' => 10, 'p1' => 'sometext' ); + + $req = new \manager\ModuleRequest( 'module/phpunitParams', $params ); + $ans = $req->dispatch(); + + $this->assertEquals( $ans->get('p1'), $params['p1'] ); + $this->assertEquals( $ans->get('p2'), $params['p2'] ); + } } diff --git a/tags b/tags index 22574f4..98eaa5b 100644 --- a/tags +++ b/tags @@ -16,36 +16,43 @@ $.fn.emulateTransitionEnd.callback phpunit/coverage/js/bootstrap.min.js /^if(typ $.fn.popover.noConflict phpunit/coverage/js/bootstrap.min.js /^};Tooltip.prototype.getPosition=function($element){$element=$element||this.$element;var el=$element[0];var isBody=el.tagName=="BODY";var elRect=el.getBoundingClientRect();if(elRect.width==null){elRect=$.extend({},elRect,{width:elRect.right-elRect.left,height:elRect.bottom-elRect.top})}var elOffset=isBody?{top:0,left:0}:$element.offset();var scroll={scroll:isBody?document.documentElement.scrollTop||document.body.scrollTop:$element.scrollTop()};var outerDims=isBody?{width:$(window).width(),height:$(window).height()}:null;return $.extend({},elRect,scroll,outerDims,elOffset)};Tooltip.prototype.getCalculatedOffset=function(placement,pos,actualWidth,actualHeight){return placement=="bottom"?{top:pos.top+pos.height,left:pos.left+pos.width\/2-actualWidth\/2}:placement=="top"?{top:pos.top-actualHeight,left:pos.left+pos.width\/2-actualWidth\/2}:placement=="left"?{top:pos.top+pos.height\/2-actualHeight\/2,left:pos.left-actualWidth}:{top:pos.top+pos.height\/2-actualHeight\/2,left:pos.left+pos.width}};Tooltip.prototype.getViewportAdjustedDelta=function(placement,pos,actualWidth,actualHeight){var delta={top:0,left:0};if(!this.$viewport)return delta;var viewportPadding=this.options.viewport&&this.options.viewport.padding||0;var viewportDimensions=this.getPosition(this.$viewport);if(\/right|left\/.test(placement)){var topEdgeOffset=pos.top-viewportPadding-viewportDimensions.scroll;var bottomEdgeOffset=pos.top+viewportPadding-viewportDimensions.scroll+actualHeight;if(topEdgeOffsetviewportDimensions.top+viewportDimensions.height){delta.top=viewportDimensions.top+viewportDimensions.height-bottomEdgeOffset}}else{var leftEdgeOffset=pos.left-viewportPadding;var rightEdgeOffset=pos.left+viewportPadding+actualWidth;if(leftEdgeOffsetviewportDimensions.right){delta.left=viewportDimensions.left+viewportDimensions.width-rightEdgeOffset}}return delta};Tooltip.prototype.getTitle=function(){var title;var $e=this.$element;var o=this.options;title=$e.attr("data-original-title")||(typeof o.title=="function"?o.title.call($e[0]):o.title);return title};Tooltip.prototype.getUID=function(prefix){do prefix+=~~(Math.random()*1e6);while(document.getElementById(prefix));return prefix};Tooltip.prototype.tip=function(){if(!this.$tip){this.$tip=$(this.options.template);if(this.$tip.length!=1){throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!")}}return this.$tip};Tooltip.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")};Tooltip.prototype.enable=function(){this.enabled=true};Tooltip.prototype.disable=function(){this.enabled=false};Tooltip.prototype.toggleEnabled=function(){this.enabled=!this.enabled};Tooltip.prototype.toggle=function(e){var self=this;if(e){self=$(e.currentTarget).data("bs."+this.type);if(!self){self=new this.constructor(e.currentTarget,this.getDelegateOptions());$(e.currentTarget).data("bs."+this.type,self)}}if(e){self.inState.click=!self.inState.click;if(self.isInStateTrue())self.enter(self);else self.leave(self)}else{self.tip().hasClass("in")?self.leave(self):self.enter(self)}};Tooltip.prototype.destroy=function(){var that=this;clearTimeout(this.timeout);this.hide(function(){that.$element.off("."+that.type).removeData("bs."+that.type);if(that.$tip){that.$tip.detach()}that.$tip=null;that.$arrow=null;that.$viewport=null})};function Plugin(option){return this.each(function(){var $this=$(this);var data=$this.data("bs.tooltip");var options=typeof option=="object"&&option;if(!data&&\/destroy|hide\/.test(option))return;if(!data)$this.data("bs.tooltip",data=new Tooltip(this,options));if(typeof option=="string")data[option]()})}var old=$.fn.tooltip;$.fn.tooltip=Plugin;$.fn.tooltip.Constructor=Tooltip;$.fn.tooltip.noConflict=function(){$.fn.tooltip=old;return this}}(jQuery);+function($){"use strict";var Popover=function(element,options){this.init("popover",element,options)};if(!$.fn.tooltip)throw new Error("Popover requires tooltip.js");Popover.VERSION="3.3.5";Popover.DEFAULTS=$.extend({},$.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'