Zend Framework 1.8 workshop

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.

5 comments

Comments 1 - 5 of 5 previous next Post a comment

  • + giolvani giolvani 4 months ago
    Hi Nick, tanks for you answer,

    exactly, database transactions!!! :)
    is it possible with your example?!!

    again, sorry for my english!
    tanks
  • + NickBelhomme Nick Belhomme 4 months ago
    Hi Giolvani,

    Thank you for your kind words,
    Do you mean database transactions? Could you elaborate?

    Nick
  • + giolvani giolvani 4 months ago
    Hi Nick!

    sorry for my english!

    first - congratulations for you slide, it is very good!
    second - is it possible with your example to control transaction?

    regards!
    Giolvani
  • + NickBelhomme Nick Belhomme 4 months ago
    Hi Clint,

    Thx for the feedback. More presentations are to follow somewhere within the coming weeks.

    Nick
    Feel free to visit my blog: http://blog.nickbelhomme.com
  • + guest0d16c67b Clint Berry 4 months ago
    Thank you for this! It was very helpful in getting my first ZF project going.
Post a comment
Embed Video
Edit your comment Cancel

13 Favorites

Zend Framework 1.8 workshop - Presentation Transcript

  1. Zend Framework 1.8 workshop Zend Framework Presentation Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  2. Zend Framework 1.8 workshop About Me: PHP5 Zend Certified Engineer (PHP5 ZCE) Zend Framework Certified Engineer (ZCE-ZF) ZF Contributor since 2008 Freelance Consultant PHP Community active member Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  3. Zend Framework 1.8 workshop Zend Framework • Full Stack Framework • Component Library Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  4. Zend Framework 1.8 workshop How to Get It? • Grab it from the download page: http://framework.zend.com/download/latest • Through Subversion: http://framework.zend.com/svn/framework/standard/trunk/ Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  5. Zend Framework 1.8 workshop How To Install? Add it to your php.ini include_path directive include_path = .:/usr/local/lib/php:/PathToZendFrameworkLibrary That’s it! Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  6. Zend Framework 1.8 workshop Starting A New Project With Zend_Tool First requirements: • For *nix environments copy the zf.sh and zf.php from the ZF/bin To the same directory as your PHP binary • For Windows: •copy the zf.php and zf.bat to the same directory as your PHP binary •add the php path to your PATH environment Var: # Right-click My Computer and select |Properties. # Select the Environment page. # In the System Variables area, click on PATH. # Add the php path to the end in the format VALUE1;VALUE2;c:php # Click Apply. # The changes take effect immediately. Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  7. Zend Framework 1.8 workshop Creating the project “MyProject” $ zf create project /path/to/non-existent-dir-called-MyProject Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  8. Zend Framework 1.8 workshop Adding a “MyProject” vhost Testing environment httpd.conf or httpd-vhosts.conf: <VirtualHost *:80> ServerName MyProject DocumentRoot absolute-path-to-MyProject-folder ErrorLog logsMyProject-error.log CustomLog logsMyProject-access.log common <Directory /> Options FollowSymLinks AllowOverride All Order allow,deny Allow from all Satisfy all </Directory> </VirtualHost> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  9. Zend Framework 1.8 workshop For windows: Add the following line to the /etc/host file 127.0.0.1 MyProject Restart apache, fire up the browser and go to: http://MyProject Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  10. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  11. Zend Framework 1.8 workshop Creating an Action + View Go to the MyProject directory and issue the following command to create the helloAction in the IndexController and corresponding view: $ zf create action hello index For a full list of commands simply visit: http://framework.zend.com/manual/en/zend.tool.project.create-a-project.html Or issue the command: $ zf --help Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  12. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  13. Zend Framework 1.8 workshop Creating a Module and Controller $ zf create module admin $ zf create controller index 1 admin Note: Trying to create a controller that already exists in another Module might result in an error. Depending on the Zend_Tool Verion you have. The solution is to apply the patch from ZF Issue Tracker: http://framework.zend.com/issues/browse/ZF-6853 Note: If you applied this patch, make sure all controller names in the admin module start with Admin_ Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  14. Zend Framework 1.8 workshop Registering the Module class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initAutoloadModuleAdmin() { $autoloader = new Zend_Application_Module_Autoloader(array( 'namespace' => 'Admin', 'basePath' => APPLICATION_PATH.'/modules/admin', )); return $autoloader; } } The method is called automatically by Zend_Application as it starts with _init. You can choose the remainder of the method name as you like. Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  15. Zend Framework 1.8 workshop Registering the Module myProject/application/configs/application.ini resources.frontController.moduleDirectory = APPLICATION_PATH "/modules" Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  16. Zend Framework 1.8 workshop Setting up the Mysql Database Add to configs/application.ini [production] =============================== resources.db.adapter = PDO_MYSQL resources.db.params.host = localhost resources.db.params.username = nick resources.db.params.password = 12345 resources.db.params.dbname = myproject Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  17. Zend Framework 1.8 workshop Create the database table CREATE TABLE users ( id int(11) NOT NULL auto_increment, username varchar(100) NOT NULL, pwd varchar(32) NOT NULL, firstname varchar(20) NOT NULL, PRIMARY KEY (id) ); Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  18. Zend Framework 1.8 workshop Populate the table INSERT INTO users (username, pwd, firstname) VALUES ('NickBelhomme', md5('hello'), 'Nick'), ('ChanieNavez', md5('strong'), 'Chantal'), ('ElvisP', md5('presley'), 'Elvis'); Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  19. Zend Framework 1.8 workshop The Model + DAO Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  20. Zend Framework 1.8 workshop myProject/application/modules/admin/models/dao/Interface.php interface Admin_Model_Dao_Interface { public function find($id); public function insert($username, $pwd, $firstname); public function update($id, $username, $pwd, $firstname); public function delete($id); public function findAll(); } Common interface between all DAOs. Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  21. Zend Framework 1.8 workshop myProject/application/modules/admin/models/dao/UserDB.php class Admin_Model_Dao_UserDB extends Zend_Db_Table implements Admin_Model_Dao_Interface { protected $_name = 'users'; public function find($id) { Very Simple DAO $id = (int)$id; $row = $this->fetchRow('id = ' . $id); (Data Access Object) if (!$row) { throw new Exception("Count not find row $id"); } return $row; } public function insert($username, $pwd, $firstname) { $data = array( 'username' => $username, 'pwd' => $this->hashPassword($pwd), 'firstname' => $firstname, ); parent::insert($data); } //... } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  22. Zend Framework 1.8 workshop myProject/application/modules/admin/models/Dao/UserDB.php class Admin_Model_Dao_UserDB extends Zend_Db_Table implements Admin_Model_Dao_Interface { //… public function update($id, $username, $pwd, $firstname) { $data = array( Very Simple DAO 'username' => $username, 'pwd' => $this->hashPassword($pwd), (Data Access Object) 'firstname' => $firstname, To explain the principle ); of an extra layer parent::update($data, 'id = '. (int)$id); } public function delete($id) { parent::delete('id =' . (int)$id); } public function findAll() { return $this->fetchAll(); } protected function hashPassword($pwd) { return md5($pwd); } } ?> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  23. Zend Framework 1.8 workshop myProject/application/modules/admin/models/User.php class Admin_Model_User { const DAO_CLASS = 'Admin_Model_Dao_UserDB'; protected $dao; public function __construct() { $daoClassName = self::DAO_CLASS; $this->dao = new $daoClassName(); The Model } using the DAO. public function find($id) { return $this->dao->find($id); Easy Switching between } Different data resources public function insert($username, $pwd, $firstname) { return $this->dao->insert($username, $pwd, $firstname); } public function update($id, $username, $pwd, $firstname) { return $this->dao->update($id, $username, $pwd, $firstname); } // ... } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  24. Zend Framework 1.8 workshop myProject/application/modules/admin/models/User.php <?php class Admin_Model_User { The Model // ... using the DAO. public function delete($id) { Easy Switching between return $this->dao->delete($id); Different data resources } public function findAll() { return $this->dao->findAll(); } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  25. Zend Framework 1.8 workshop The Actions and Views Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  26. Zend Framework 1.8 workshop Setting up the admin actions $ zf create action add index 1 admin $ zf create action edit index 1 admin $ zf create action delete index 1 admin Again if you are using a version of Zend_Tool which isn’t fully module Aware you can patch the Zend_Tool_Project_Provider_Action with if (self::hasResource($this->_loadedProfile, $name, $controllerName, $module)) Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  27. Zend Framework 1.8 workshop The Admin_IndexController indexAction public function indexAction() { $users = new Admin_Model_User(); $this->view->users = $users->findAll(); } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  28. Zend Framework 1.8 workshop The corresponding index.phtml view script: myProject/application/modules/admin/views/scripts/index/index.phtml <p><a href="<?php echo $this->url(array('controller'=>'index', 'action'=>'add'));?>">Add new user</a></p> <table> <tr> <th>Username</th> <th>First Name</th> <th>&nbsp;</th> </tr> <?php foreach($this->users as $user) : ?> <tr> <td><?php echo $this->escape($user->username);?></td> <td><?php echo $this->escape($user->firstname);?></td> <td> <a href="<?php echo $this->url(array('controller'=>'index', 'action'=>'edit', 'id'=>$user->id));?>">Edit</a> <a href="<?php echo $this->url(array('controller'=>'index', 'action'=>'delete', 'id'=>$user->id));?>">Delete</a> </td> </tr> <?php endforeach; ?> </table> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  29. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  30. Zend Framework 1.8 workshop The Admin_IndexController deleteAction REST: public function deleteAction() irreversible { action use if ($this->getRequest()->isPost()) { POST not $del = $this->getRequest()->getPost('del'); GET if ($del == 'Yes') { $id = $this->getRequest()->getPost('id'); $users = new Admin_Model_User(); $users->delete($id); } $this->_redirect('/admin/'); } else { $id = $this->_getParam('id', 0); $users = new Admin_Model_User(); $this->view->user = $users->find($id); } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  31. Zend Framework 1.8 workshop The corresponding delete.phtml view script: myProject/application/modules/admin/views/scripts/index/delete.phtml <p>Are you sure that you want to delete '<?php echo $this->escape($this->user['username']); ?>' aka '<?php echo $this->escape($this->user['firstname']); ?>'? </p> <form action="<?php echo $this->url(array('action'=>'delete')); ?>" method="post"> <fieldset> <input type="hidden" name="id" value="<?php echo $this->escape($this->user['id']); ?>" /> <input type="submit" name="del" value="Yes" /> <input type="submit" name="del" value="No" /> </fieldset> </form> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  32. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  33. Zend Framework 1.8 workshop The Admin_IndexController addAction public function addAction() { if ($this->getRequest()->isPost()) { $action = $this->getRequest()->getPost('action'); if ($action == 'add') { $username = $this->getRequest()->getPost('username'); $pwd = $this->getRequest()->getPost('pwd'); $firstname = $this->getRequest()->getPost('firstname'); $users = new Admin_Model_User(); $users->insert($username, $pwd, $firstname); } $this->_redirect('/admin/'); } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  34. Zend Framework 1.8 workshop The corresponding add.phtml view script: myProject/application/modules/admin/views/scripts/index/add.phtml <h2>Add a new User</h2> <form action="<?php echo $this->url(array('action'=>'add')); ?>" method="post"> <fieldset> username: <input type="text" name="username"><br/> password: <input type="password" name="pwd"><br/> firstname: <input type="text" name="firstname"><br/> <input type="submit" name="action" value="add" /> </fieldset> </form> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  35. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  36. Zend Framework 1.8 workshop The Admin_IndexController editAction public function editAction() { if ($this->getRequest()->isPost()) { $action = $this->getRequest()->getPost('action'); if ($action == 'edit') { $id = $this->getRequest()->getPost('id'); $username = $this->getRequest()->getPost('username'); $pwd = $this->getRequest()->getPost('pwd'); $firstname = $this->getRequest()->getPost('firstname'); $users = new Admin_Model_User(); $users->update($username, $pwd, $firstname); } $this->_redirect('/admin/'); } else { $id = $this->_getParam('id', 0); $users = new Admin_Model_User(); $this->view->user = $users->find($id); } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  37. Zend Framework 1.8 workshop The corresponding edit.phtml view script: myProject/application/modules/admin/views/scripts/index/edit.phtml <h2>Edit User: <?php echo $this->escape($this->user->username); ?></h2> <form action="<?php echo $this->url(array('action'=>'edit')); ?>" method="post"> <fieldset> <input type="hidden" name="id" value="<?php echo $this->escape($this->user->id); ?>"> username: <input type="text" name="username" value="<?php echo $this->escape($this->user->username); ?>"><br/> password: <input type="password" name="pwd"><br/> firstname: <input type="text" name="firstname" value="<?php echo $this->escape($this->user->firstname); ?>"><br/> <input type="submit" name="action" value="edit" /> </fieldset> </form> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  38. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  39. Zend Framework 1.8 workshop Authentication: Zend_Auth Authentication is loosely defined as determining whether an entity actually is what it purports to be (i.e., identification), based on some set of credentials. http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  40. Zend Framework 1.8 workshop Append the DAO and User Classes interface Admin_Model_Dao_Interface { // … public function findCredentials($username, $pwd); } class Admin_Model_Dao_UserDB extends Zend_Db_Table implements Admin_Model_Dao_Interface { // … public function findCredentials($username, $pwd) { $select = $this->select()->where('username = ?', $username) ->where('pwd = ?', $this->hashPassword($pwd)); $row = $this->fetchRow($select); if($row) { return $row; } return false; } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  41. Zend Framework 1.8 workshop Append the DAO and User Classes class Admin_Model_User { // ... public function findCredentials($username, $password) { return $this->dao->findCredentials($username, $password); } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  42. Zend Framework 1.8 workshop Always use a vendor or project prefix And inform the autoloader of library prefixes Prepend the application bootstrap class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initAutoloadModuleDefault() { $autoloader = new Zend_Application_Module_Autoloader(array( 'namespace' => 'Myp', 'basePath' => dirname(__FILE__) )); return $autoloader; } //... } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  43. Zend Framework 1.8 workshop Create an application model: The Auth Adapter myProject/application/models/AuthAdapter.php class Myp_Model_AuthAdapter implements Zend_Auth_Adapter_Interface { protected $username; protected $password; protected $user; public function __construct($username, $password) { $this->username = $username; $this->password = $password; $this->user = new Admin_Model_User(); } public function authenticate() { $match = $this->user->findCredentials($this->username, $this->password); if(!$match) { $result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null); } else { $user = current($match); $result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $user); } return $result; } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  44. Zend Framework 1.8 workshop The IndexController loginAction $ zf create action login index 1 Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  45. Zend Framework 1.8 workshop The IndexController loginAction public function loginAction() { $auth = Zend_Auth::getInstance(); if(Zend_Auth::getInstance()->hasIdentity()) { $this->_redirect('/index/hello'); } else if ($this->getRequest()->isPost()) { $action = $this->getRequest()->getPost('action'); if ($action == 'login') { $username = $this->getRequest()->getPost('username'); $pwd = $this->getRequest()->getPost('pwd'); $authAdapter = new Myp_Model_AuthAdapter($username, $pwd); $result = $auth->authenticate($authAdapter); if(!$result->isValid()) { switch ($result->getCode()) { case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: $this->view->error = 'user credentials not found'; } } else { $this->_redirect('/index/hello'); } } } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  46. Zend Framework 1.8 workshop The corresponding login.phtml view script: myProject/application/views/scripts/index/login.phtml <h2>Login</h2> <form action="<?php echo $this->url(array('action'=>'login')); ?>" method="post"> <fieldset> username: <input type="text" name="username"><br/> password: <input type="password" name="pwd"><br/> <div><?php echo $this->escape($this->error);?></div> <input type="submit" name="action" value="login" /> </fieldset> </form> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  47. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  48. Zend Framework 1.8 workshop The IndexController helloAction public function helloAction() { if(Zend_Auth::getInstance()->hasIdentity()) { $this->view->user = Zend_Auth::getInstance()->getIdentity(); } } Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  49. Zend Framework 1.8 workshop The corresponding hello.phtml view script: myProject/application/views/scripts/index/hello.phtml <?php if(isset($this->user)):?> welcome <?php echo $this->escape($this->user['firstname']); ?>, to the MyProject application. <?php else: ?> you need to login first. <a href="<?php echo $this->url(array('action' => 'login')); ?>">login</a> <?php endif; ?> Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  50. Zend Framework 1.8 workshop Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  51. Zend Framework 1.8 workshop And that is Authentication. if(Zend_Auth::getInstance()->hasIdentity()) Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  52. Zend Framework 1.8 workshop What about? •Authorization (Zend_Acl) •Filter Input, Escape Output? •Input Validation (Zend_Validate) •Input filtering (Zend_Filter) •Dynamic Forms (Zend_Form) And all the other great stuff???!!!! Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  53. Zend Framework 1.8 workshop There is always next time! 1 hour courses, remember??? ;) Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer
  54. Zend Framework 1.8 workshop Resources •http://blog.nickbelhomme.com •http://www.slideshare.net/weierophinney/zend-framework-workshop-dpc09 •http://en.wikipedia.org/wiki/Zend_Framework •http://blog.astrumfutura.com/archives/373-The-M-in-MVC-Why-Models- are-Misunderstood-and-Unappreciated.html Source code of this workshop available at: http://blog.nickbelhomme.com/wp-content/uploads/workshopzf1.8.zip Nick Belhomme 17 June 2009 PHP5 Zend Certified Engineer + Zend Framework Certified Engineer

+ Nick BelhommeNick Belhomme, 5 months ago

custom

3925 views, 13 favs, 4 embeds more stats

An introduction to Zend Framework 1.8 using Zend_To more

More info about this document

© All Rights Reserved

Go to text version

  • Total Views 3925
    • 3399 on SlideShare
    • 526 from embeds
  • Comments 5
  • Favorites 13
  • Downloads 204
Most viewed embeds
  • 327 views on http://blog.nickbelhomme.com
  • 187 views on http://www.harikt.com
  • 10 views on http://harikt.com
  • 2 views on http://static.slidesharecdn.com

more

All embeds
  • 327 views on http://blog.nickbelhomme.com
  • 187 views on http://www.harikt.com
  • 10 views on http://harikt.com
  • 2 views on http://static.slidesharecdn.com

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