Formation PHP avancé - Cake PHP

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

6 comments

Comments 1 - 6 of 6 previous next Post a comment

Post a comment
Embed Video
Edit your comment Cancel

10 Favorites

Formation PHP avancé - Cake PHP - Presentation Transcript

  1. Formation PHP avancé
      • Pierre de La Morinerie
    Junior Isep 2007
  2. Programme de la formation
  3. Programme de la formation
    • PHP Avancé :
      • Programmation Orientée Objet
      • Couches d'accès aux données
    • Frameworks :
      • Introduction aux frameworks
      • Présentation du modèle MVC
    • CakePHP :
      • Découverte et utilisation du framework CakePHP
      • Utilisation du scaffolding et des tests unitaires
    • Pour aller plus loin :
      • Introduction à l'eXtreme Programming et aux tests unitaires
  4. Programme de la formation
    • Objectifs de la formation :
      • Ne plus réécrire sans cesse le même code
      • Se concentrer sur les tâches essentielles
      • Pouvoir gérer de gros projets en PHP
    • En résumé :
      • Programmer mieux et plus rapidement !
  5. Programme de la formation
    • Un mot sur le déroulement
      • Rythme
      • Séances
  6. Introduction à la POO
  7. Introduction à la POO - Généralités
    • Objectifs de la Programation Orienté Objet (POO) :
      • Modéliser les programmes comme des interactions d'objets
    • Concrètement :
      • En procédural, on manipule des fonctions
      • En POO, on manipule des objets
  8. Introduction à la POO - Généralités
    • Avantages de la POO :
      • Code plus sûr
      • Programmes sont plus clairs
      • Maintenance des applications facilitée
      • Le code est facilement réutilisable
      • La POO rend possible le développement de gros programme
    • Inconvénients de la POO :
      • Oblige à réfléchir et à modéliser avant de programmer
      • La notation POO n’est pas toujours intuitive
  9. Introduction à la POO – Classes et objets
    • Qu'est-ce qu'un objet ?
      • Un objet est une structure de données
      • Mais il inclus aussi les fonctions pour traiter ces données
    • Un objet va donc comporter :
      • Des attributs, ou champs (comme dans une struct )
      • Des méthodes pour manipuler ces attributs
  10. Introduction à la POO – Classes et objets
    • Exemple : Un objet « animal » comportera :
      • Des attributs :
        • Nom
        • Âge
        • Taille
        • Poids
      • Des méthodes :
        • Nourrir()
        • Soigner()
  11. Introduction à la POO – Classes et objets
    • Attention au vocabulaire :
      • Dire que « Animal » est un objet est un abus de langage
      • « Animal » n'est qu'un moule pour créer des objets
      • À partir du moule « Animal », je peux créer :
        • Un objet « gorille », nommé André, de 6 ans
        • Un objet « lion », nommé Alex, de 13 ans
        • Un objet « tigre », nommé Henri, de 3 ans
    • Un moule d'objet est habituellement appelé une classe
    • Créer un objet à partir d'une classe s'appelle «  instancier  »
    • Ne surtout pas confondre classe (=moule) et objet (=contenu du moule) !
  12. Introduction à la POO – Classes et objets
    • Exemple 1 : créer une classe et des objet en PHP
  13. Introduction à la POO – Le constructeur
    • Le constructeur
      • Comment initialiser les valeurs par défaut d'un objet ?
      • Le constructeur est appelé à chaque instanciation d'un objet
      • C'est une fonction qui a le même nom que la classe
      • On peut y effectuer n'importe quelle opération
    • Accès aux attributs
      • La variable « $this » permet d'accéder aux attributs de l'objet
  14. Introduction à la POO – Le Constructeur
    • Exemple 2 : utilisation du constructeur
  15. Introduction à la POO – Les méthodes
    • Les méthodes
      • Ce sont des fonctions pour manipuler les attributs des objets
      • Elles peuvent aussi manipuler d'autre objets
      • Les méthodes utilisent « $this » pour accéder aux attributs
    • Autres utilisations des méthodes
      • Une méthode peut être utilisée comme une fonction classique
      • Elle peut prendre des paramètres et renvoyer un résultat
  16. Introduction à la POO – Les méthodes
    • Exemple 3 : utilisation des méthodes
  17. Introduction à la POO – L'héritage
    • L'héritage
      • Une classe peut hériter d'une autre
      • Elle comporte alors tous les attributs et méthodes de la classe parente
    • En pratique :
      • On peut définir une classe « Lion » qui hérite de « Animal »
      • Un objet de type « Lion » a alors un age, un nom...
      • On peut ensuite rajouter des particularités au Lion
  18. Introduction à la POO – L'héritage
    • Exemple 4 : héritage de classes
  19. Introduction à la POO - TD
    • TD n°1 :
      • Sujet : Modéliser des véhicules
      • Contraintes :
        • Il y a deux types de véhicules : auto et bateau
        • Tous les véhicules ont une vitesse maximale
        • Les autos comportent :
          • une distance parcourue
          • une fonction « voyager(km) » qui incrémente la distance parcourue
        • Les bateaux comportent :
          • une longueur (par défaut, la longueur est de 10)
      • Exercices :
        • 1 : modéliser une Auto et un Bateau
        • 2 : modéliser un Véhicule et deux classes héritées
  20. Introduction à la POO - TP
    • TP n°1 :
      • Sujet : Réaliser une classe MySQL
      • Contraintes :
        • Attribut s host , login , password , db_base , is_connected
        • Un constructeur MySQL($host, $login, $password, $db_base) qui stocke les paramètres dans les attributs de la classe
        • Une méthode connect() qui connecte à la BDD et met is_connected à true
        • Une méthode query($sql) qui lance une requête MySQL et renvoie le résultat (seulement si is_connected est à true )
        • Une méthode disconnect() qui déconnecte de la BDD et met is_connected à false
  21. Introduction à la POO - TP
    • TP n°1 :
      • Intérêt :
        • Utiliser facilement plusieurs connexions en simultané : un objet MySQL <=> une connexion
        • Renvoyer directement des tableaux au lieu de recordsets
        • Rajouter des fonctions de log, de traitement des erreurs, de préprocessing, de traitement des données...
        • Traiter plusieurs SGDB : Oracle, PostgreSQL, etc
  22. Les frameworks Le modèle MVC
  23. Les frameworks
    • Définition
    • Avantages
    • Qualités nécessaires
    • Les frameworks Web existants
    • Fonctionnalités
  24. Les frameworks - Définition
    • Un framework est un ensemble de bibliothèques permettant le développement rapide d'applications
    • Il existe des frameworks logiciels et des frameworks Web
    • Comporte :
      • Une architecture :
        • Définit l'organisation des fichiers dans l'application
      • Des bibliothèques
        • Fournit des composants utiles : RSS, authentification, Ajax, etc
  25. Les frameworks - Avantages
    • Avantages d'un framework :
      • Cohérence
      • Liberté
      • Qualité
      • Rapidité
  26. Les frameworks – Qualités nécessaires
    • Un framework doit être :
      • Pas trop rigide
      • Pas trop flexible
      • Permettre l'intégration de composants tierce-partie
  27. Les frameworks – L'existant
    • PHP :
      • Symphony
      • Prado
      • CakePHP
      • PHP on Trax
    • Ruby :
      • Ruby on Rails
    • Python :
      • Django
      • Turbogears
    • Java :
      • J2EE
  28. Les frameworks – L'existant
    • Un framework se choisit en fonction de :
      • L'expérience des développeurs
      • Les besoins du client (publication, développement...)
      • Le support interne (activité de la communauté)
      • L'hébergement
    • Idéalement, le framework doit être adapté à chaque projet
    • En pratique, il est bon de choisir un framework suffisamment flexible et se s'y tenir
  29. Les frameworks – Fonctionnalités
    • Que peut-on trouver dans un framework web ?
      • Architecture MVC
      • SGDB multiples
      • ActiveRecord
      • Templates
      • Validation
      • Cache
      • Javascript/Ajax
      • Url rewriting
      • Modules
      • Authentification
  30. Le modèle MVC
    • MVC <=> Modèle – Vue - Contrôleur
    • Architecture 3-tiers
    • Permet de séparer les données, la logique et la présentation
  31. Le modèle MVC
    • Modèle :
      • Représente le comportement de l'application : traitements des données, interactions avec la base de données, etc.
    • Vue :
      • Correspond à l'interface avec laquelle l'utilisateur interagit.
      • Souvent en HTML ou XML
      • La vue n'effectue aucun traitement, elle se contente d'afficher l'interfacer et les données fournies par le modèle
    • Contrôleur :
      • Répond aux événements émis par l'utilisateur
      • Contient toute la partie logique du code
  32. Le modèle MVC
    • Avantages :
      • Architecture extrêmement claire
      • Paradigme utilisé dans de nombreux projets logiciels ou Web
      • Permet de séparer la présentation de l'accès aux données
  33. Le modèle MVC - Exemple
    • Exemple : un Livre d'or
      • Modèle : classe Message
        • Requêtes SQL
        • Méthode de récupération des données : tousLesMessages(), messagesRécents(), etc
      • Contrôleur : classe ControleurMessages
        • Analyse de GET et POST pour déterminer les données demandées
        • Récupération des messages appropriés
        • Pagination
        • Appel de la Vue correspondante
      • Vue : template VueMessages
        • Fichier PHP comprenant de l'HTML et quelques variables
        • Boucle sur les données du contrôleur pour afficher la liste des messages
  34. Le modèle MVC - Exemple
    • Exemple : un Livre d'or
    • Exemple : un Livre d'or
      • Modèle : classe Message
          • Requêtes SQL
          • Méthode de récupération des données : tousLesMessages(), messagesRécents(), etc
      • Vue : template VueMessages
          • Fichier PHP comprenant de l'HTML et quelques variables
          • Boucle sur les données du contrôleur pour afficher la liste des messages
      • Contrôleur : classe ControleurMessages
          • Analyse de GET et POST pour déterminer les données demandées
          • Récupération des messages appropriés
          • Pagination
          • Appel de la Vue correspondante
  35. Introduction à CakePHP
  36. Introduction à CakePHP
    • Origines
    • Fonctionnalités
    • Pourquoi Cake ?
    • Documentation
  37. Introduction à CakePHP – Origines
    • Initié par Michal Tatarynowicz en 2005
    • Sous licence MIT (Libre, open-source, non contaminante)
    • Inspiré de Ruby on Rails :
      • « Des conventions plutôt que de la configuration »
      • Modèle MVC
      • Scaffolding
  38. Introduction à CakePHP – Fonctionnalités
    • Fonctionnalités principales :
      • Compatible PHP4 et PHP5
      • Génération de CRUD et de requêtes usuelles
      • Url rewriting
      • Templates rapides (pur PHP) et helpers
      • Facile à déployer
      • Validation des données
      • Scaffolding (=échafaudage)
      • Cache des vues et/ou des requêtes
      • SGBD multiples
  39. Introduction à CakePHP – Pourquoi Cake
    • Ce qui fait de la bonne cuisine :
      • Simple et léger
      • Facile à apprendre
      • Demeure du PHP
      • Facilement extensible
      • Bien documenté
      • Communauté active et sympathique
    • En bref...
      • Coder avec Cake est agréable
  40. Introduction à CakePHP – Documentation
    • Il faut exploiter la bonne documentation de Cake !
    • Ressources utiles :
      • www.cakephp.com – site officiel
      • manual.cakephp.com - le manuel complet de Cake
      • bakery.cakephp.org – articles, tutoriaux et exemples
      • cakephp.org/files/cakesheet.pdf – mémento général
  41. CakePHP – Premier tutoriel
  42. Premier tutoriel
    • Rien de tel qu'un bon exemple
      • Fameux tutoriel « A weblog in 15 minutes » de Ruby on Rails
      • Cake peut réaliser cela en bien moins !
  43. Premier tutoriel – Prérequis
    • Prérequis :
      • Un serveur Web
      • Un serveur de base de données
  44. Premier tutoriel – Installation de Cake
    • Installation de Cake :
      • Télécharger CakePHP 1.1.* (stable) depuis cakephp.org
      • Décompresser l'archive dans un dossier du WebRoot (par exemple « formation_cake »)
      • La structure finale doit donner :
        • /formation_cake
          • /app
          • /cake
          • /docs
          • /vendors
          • .htaccess
          • index.php
          • VERSION.txt
  45. Premier tutoriel - Test
    • Testons l'installation :
      • http://localhost/formation_cake/
  46. Premier tutoriel – Configuration
    • Configuration de Cake :
      • Aller dans le dossier /app/config/
      • Renommer «  database.php.default  » en «  database.php  »
      • Ouvrir database.php et éditer les informations de connexion :
        • var $default = array('driver' => 'mysql', 'connect' => 'mysql_connect', 'host' => 'localhost', 'login' => 'root', 'password' => '', 'database' => 'easyphp' 'prefix' => 'cake_' );
  47. Premier tutoriel – Configuration
    • Optionnel : au sujet de l'URL rewriting
      • Ouvrir le fichier de configuration d'Apache (httpd.conf)
      • Décommenter les lignes :
        • LoadModule rewrite_module modules/mod_rewrite.so
        • AddModule mod_rewrite.c
    • Si on ne veut/peut pas utiliser mod_rewrite :
      • Ouvrir le fichier /app/config/core.php
      • Décommenter la ligne :
        • define ('BASE_URL', env('SCRIPT_NAME'));
  48. Premier tutoriel – Configuration
    • Vérifions que Cake parvient à se connecter à notre BDD :
      • http://localhost/formation_cake/
  49. Premier tutoriel – Configuration
    • CakePHP est configuré : nous pouvons commencer à réaliser notre blog
  50. Premier tutoriel – BDD
    • Création de la Base de Données :
      • Ouvrez phpMyAdmin
      • Créez une table « cake_posts » :
        • CREATE TABLE posts ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, title VARCHAR(50), body TEXT, created DATETIME DEFAULT NULL, modified DATETIME DEFAULT NULL );
    • Insérez quelques posts dans la table
  51. Premier tutoriel – BDD
    • Cré ation du Modèle
    • Création du Contrôleur
    • Création de la Vue
  52. Premier tutoriel – Code
    • Modèle :
      • Lié à une table de la BDD
      • Par convention, le fichier et la classe s’appellent du nom de la table, au singulier :
      • Fichier : post.php
      • Classe : Post
    • La classe hérite de Model , qui définit des fonctions par défaut
    • L’attribut name n’est pas strictement obligatoire, mais permet de résoudre quelques bizarreries de PHP4. Il doit comporter le nom du modèle.
  53. Premier tutoriel – Code
    • Contrôleur :
      • Par convention, le fichier et la classe s’appellent du nom de la table, au pluriel :
        • Fichier : posts_controller.php
        • Classe : PostsController
      • Les fonctions du contrôleur sont appelées par :
        • /controlleur/action
        • 'index()' est l'action par défaut
        • Exemple : /posts/index
      • La méthode set() passe des données à la Vue
      • La méthode du modèle findAll() récupère tous les enregistrements du modèle, et renvoie un tableau
  54. Premier tutoriel – Code
    • Vue :
      • Un fichier HTML dans lequel on peut rajouter un peu de PHP
      • Nom du fichier : app/views/model_name/action_name.thtml
      • Exemple :
        • app/views/posts/index.thtml
    • On peut maintenant tester en allant à l’Url :
      • /posts/index
  55. Premier tutoriel – Code
    • Vue : Helpers
      • Petits composants de formatage
      • Utilisés dans les Vues
      • Permettent de formatter du HTML, des formulaires, du Javascript, des dates, du texte…
      • Documentés dans le Manuel
    • HtmlHelper :
      • Contient une méthode url() , qui prend transforme une Url absolue en Url relative :
        • /controlleur/action => localhost/formation_cake/controlleur/action
  56. Premier tutoriel – Code
    • Affichage des posts
      • Création d'une action 'view' dans notre Contrôleur
        • Une action peut prendre des paramètres
        • Il seront passés dans l'Url de la page
        • Exemple :
          • function view($id) => /posts/view/2
      • Création de la vue 'view.thtml'
  57. Premier tutoriel – Code
    • Ajout d'un Post
      • Création d'une action 'add' dans notre Contrôleur
        • $this->params contient les paramètres passés en $_POST
        • $this->data est un raccourci pour $this->params['data']
      • Model->save() sauvegarde des données
        • Format : ['Model']['field'] = value
      • Flash() affiche un message et une redirection
  58. Premier tutoriel – Code
    • Ajout d'un Post
      • Création de la vue
        • Les Helpers 'Html' et 'Form' sont très utiles
        • Mais on peut aussi écrire le code en pur Html
      • Helpers de champs
        • 1er argument : 'Model/field' : génère un name=''data[Model][field]''
        • 2ème argument : tableau d'options Html
  59. Premier tutoriel – Code
    • Ajout d'un Post - v alidation des données
      • De fait au niveau du Modèle
      • Attribut $validate :
        • 'field' => VALID_CONSTANT
      • Les constantes de validation sont :
        • VALID_NOT_EMPTY
        • VALID_NUMBER
        • VALID_EMAIL
        • VALID_YEAR
      • On peut définir la fonction Model::invalidate() pour un contrôle plus fin
  60. Premier tutoriel – Code
    • Ajout d'un Post - v alidation des données
      • Affichage des messages :
        • Fonction $html->setErrorTag('Model/field', 'Message d'erreur')
      • La validation de Cake est extensible et finement configurable à tous les niveaux (Modèle, Contrôleur, Vue)
  61. Premier tutoriel – Code
    • Suppression d'un Post
      • Création de l'action dans le Contrôleur :
        • Model->delete()
      • Inutile de créer une vue : on redirige après l'action
  62. Premier tutoriel – Code
    • Edition d'un Post
      • Création de l'action du Contrôleur
        • Pré-remplir ' $this->data ' permet de préremplir les champs
        • On utilise toujours la fonction Model->save() , comme pour un ajout
        • Si un champ 'id' est définit dans les données, ' save() ' va essayer de mettre à jour ces données
      • Création de la Vue
        • Quasiment identique à ' add.thtml'
        • On rajoute un champ ' hidden ' nommé ' id ', pour permettre la mise à jour
        • Nota : on pourrait combiner ' add.thtml ' et ' edit.thtml ' sans difficultés
  63. Premier tutoriel – Code
    • Edition des routes
      • Fichier app/config/routes.php
      • Permet d'associer n'importe quelle adresse à n'importe quelle action
    • Débogage
      • Controllé par la variable de configuration DEBUG (config.php)
      • Détermine les messages d'erreurs, les dump SQL, etc
  64. Premier tutoriel – Fin
    • Un mot sur l'extensibilité
      • App_controller : actions communes à tous les contrôleurs
      • App_model : méthodes communes à tous les modèles
      • Components : petits contrôleurs partagés
      • Elements : petits bouts de templates réutilisables (thtml)
      • Layouts : gabarits généraux (thtml)
      • Plugins : ensemble autonome de contrôleurs (ex: un forum)
  65. Premier tutoriel – Conclusion
    • Fin du tutoriel
    • Pour aller plus loin :
      • Lisez le Manuel en entier !
      • Lisez éventuellement l'API et/ou les sources
      • Essayez de rajouter des Commentaires au blog
  66. Aller plus vite : Le scaffolding
  67. Scaffolding - présentation
    • Emploi :
      • Le scaffolding produit une interface d'administration en analysant les bases de données
      • Les actions sont générées dynamiquement à chaque appel (pas de génération de code)
    • Usage :
      • Mise en place de structures temporaires
      • Développement rapide tant que les schémas ne sont pas fixés
    • Limites :
      • Ce n'est que de l' échafaudage
      • Pas totalement flexible
      • Souvent nécessaire d'écrire son propre code
  68. Scaffolding - utilisation
    • Pour activer le scaffolding dans un Contrôleur :
      • Mettre un attribut '$scaffold' dans le contrôleur
      • C'est tout !
      • Note : il faut tout de même créer un Modèle avant
  69. Scaffolding - exemple
    • Ajout de Commentaires à notre blog (1/3)
      • Création de la table 'comments' dans la Base de donnée
        • id (INT)
        • post_id (INT)
        • author (VARCHAR 50)
        • body (TEXT)
        • created (DATETIME)
  70. Scaffolding - exemple
    • Ajout de Commentaires à notre blog (2/3)
      • Création du Modèle
      • Création d'un Contrôleur vide
        • Attribut '$scaffold'
  71. Scaffolding - exemple
    • Ajout de Commentaires à notre blog (3/3)
      • Test
        • http://localhost/formation_cake/comments/index
  72. Scaffolding – modification du scaffolding
    • Remplacement des vues du scaffolding
      • Créer une ou plusieurs des vues nommées :
        • index.scaffold.thtml
        • show.scaffold.thtml
        • add.scaffold.thtml
        • edit.scaffold.thtml
      • On peut remplacer les vues scaffoldées pour toute l'application ou juste pour un contrôleur particulier
      • Possibilité de s'inspirer des vues scaffoldées de Cake
        • /cake/libs/view.templates/scaffolds
  73. Scaffolding – modification du scaffolding
    • Remplacement des actions du scaffolding
      • On peut créer des actions nommées :
        • index
        • show
        • add
        • edit
        • delete
      • C'est souvent une mauvaise idée
  74. Les associations
  75. Associations
    • Cake peut scaffolder en fonction des associations de table
      • Exemple : menu déroulant des posts dans les Commentaires
    • Il faut définir les associations dans le Modèle
  76. Associations
    • Les associations sont définies dans les Modèles
    • Les différentes possibilités sont :
      • hasOne
        • Cardinalité 1-1 : un Utilisateur a un Profil
      • belongsTo
        • Cardinalité 1-1 : un Commentaire appartient à un Post
      • hasMany
        • Cardinalité 1-N : un Post a plusieurs Commentaires
      • hasAndBelongsToMany
        • Cardinalité N-N : les Posts ont plusieurs Tags
  77. Associations
    • Utilité des associations :
      • Récupération automatiques de données
        • Le paramètre ' $recursive' des Modèles permet de récupérer en même temps un Post et ses Commentaires
      • Effacement lié
        • Les Commentaires d'un Post peuvent être effacés en même temps que celui-ci
      • Génération futée de scaffolding
        • Les listes et menus déroulants sont automatiquement mis en relation
  78. Associations - exemple
    • Exemple :
      • Rajouter l'attribut suivant au modèle ' Comment' :
        • var $belongsTo = array('Post');
      • Les Commentaires sont maintenant associés aux Posts dans les vues scaffoldées
  79. Associations - exemple
    • Exemple 2 :
      • Rajouter l'attribut suivant au modèle 'Post ' :
        • var $hasMany = array('Comment');
      • On peut maintenant accéder aux Commentaires d'un Post dans les Vues :
        • echo $post['Comment'][0]['body'];
  80. Aller (encore) plus vite : Bake.php
  81. Bake.php - présentation
    • Qu'est ce que c'est ?
      • Un script à lancer depuis la ligne de commande
    • Utilité :
      • Bake génère des fichiers de code à partir de la BDD
      • On peut générer des Modèles, des Contrôleurs et des Vues
  82. Bake.php - présentation
    • Comparaison bake/scaffolding
      • Le scaffolding génère l'affichage dynamiquement
        • Avantage : l'affichage suit instantanément un changement de schéma
        • Inconvénient : on ne peut pas éditer ou adapter le code produit
      • Bake génère le code une fois pour toute
        • Avantage : se baser sur le code produit pour développer rapidement
        • Inconvénient : ne prend pas en compte un changement de schéma
  83. Bake.php - utilisation
    • Appel de Bake :
      • Bake s'appelle depuis la ligne de commande
      • Syntaxe générale :
        • php.exe /cake/scripts/bake.php
      • On peut passer des arguments au script
    • Conseil :
      • Pour appeler ' php.exe' depuis la ligne de commande, mieux vaut que php soit dans le PATH :
        • Méthode 1 : éditer les variables d'environnement, puis redémarrer
        • Méthode 2 : taper 'set path=%path%;c:dossier_de_php'
  84. Bake.php - utilisation
    • Exemple pratique :
      • Ouvrir une invite de commande
      • Naviguer jusqu'à '.../cake/scripts'
      • Taper :
        • php bake.php
      • Bake détecte automatiquement l'application à cuisiner
      • Suivre les instructions

+ kemenarankemenaran, 3 years ago

custom

19347 views, 10 favs, 4 embeds more stats

Une formation avancée à PHP, aux frameworks, à C more

More info about this document

© All Rights Reserved

Go to text version

  • Total Views 19347
    • 19291 on SlideShare
    • 56 from embeds
  • Comments 6
  • Favorites 10
  • Downloads 489
Most viewed embeds
  • 52 views on http://web-01.blogspot.com
  • 2 views on http://www.filescon.com
  • 1 views on http://www.oplahol.com
  • 1 views on http://localhost

more

All embeds
  • 52 views on http://web-01.blogspot.com
  • 2 views on http://www.filescon.com
  • 1 views on http://www.oplahol.com
  • 1 views on http://localhost

less

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

Cancel
File a copyright complaint
Having problems? Go to our helpdesk?

Categories