├── .gitignore
├── Resources
├── examples
│ └── Application
│ │ ├── Resources
│ │ ├── views
│ │ │ ├── Guestbook
│ │ │ │ ├── sign.html.phtml
│ │ │ │ └── index.html.phtml
│ │ │ └── layout.html.phtml
│ │ └── config
│ │ │ ├── routing.yml
│ │ │ └── routing.ini
│ │ ├── Model
│ │ ├── DbTable
│ │ │ └── Guestbook.php
│ │ ├── Guestbook.php
│ │ └── GuestbookMapper.php
│ │ ├── ApplicationBundle.php
│ │ ├── Controller
│ │ └── GuestbookController.php
│ │ └── Form
│ │ └── Guestbook.php
├── views
│ └── layout.html.phtml
└── config
│ └── compat.xml
├── Tests
├── phpunit.dist.xml
├── Router
│ └── Loader
│ │ ├── fixtures
│ │ └── routes.ini
│ │ └── ZFRouterLoaderTest.php
├── TestInit.php
├── View
│ └── ZendViewEngineTest.php
└── Controller
│ └── RouteNameParserTest.php
├── Controller
├── Helpers
│ ├── ContextSwitch.php
│ ├── ViewRenderer.php
│ ├── Layout.php
│ ├── HelperBroker.php
│ ├── Helper.php
│ ├── UrlHelper.php
│ ├── Redirector.php
│ └── FlashMessenger.php
├── CatchAllRequestListener.php
├── ZendResponse.php
├── RouteNameParser.php
├── ZendController.php
└── ZendRequest.php
├── WhitewashingZFMvcCompatBundle.php
├── View
├── ParameterBag.php
├── View1.php
├── CoreViewListener.php
└── ZendViewEngine.php
├── DependencyInjection
└── WhitewashingZFMvcCompatExtension.php
├── Router
└── Loader
│ └── ZFRouterLoader.php
└── README.markdown
/.gitignore:
--------------------------------------------------------------------------------
1 | Tests/phpunit.xml
2 |
--------------------------------------------------------------------------------
/Resources/examples/Application/Resources/views/Guestbook/sign.html.phtml:
--------------------------------------------------------------------------------
1 | Please use the form below to sign our guestbook!
2 |
3 | form->setAction($this->url());
5 | echo $this->form->__toSTring();
--------------------------------------------------------------------------------
/Resources/examples/Application/Model/DbTable/Guestbook.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Resources/views/layout.html.phtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Zend Framework Compatibility Bundle Start
5 |
6 |
7 |
8 | content; ?>
9 |
10 |
--------------------------------------------------------------------------------
/Resources/examples/Application/Resources/config/routing.yml:
--------------------------------------------------------------------------------
1 | zfmvccompat_guestbook_homepage:
2 | pattern: /zfguestbook
3 | defaults: { _controller: "ApplicationBundle:Guestbook:index" }
4 |
5 | zfmvccompat_guestbook_sign:
6 | pattern: /zfguestbook/sign
7 | defaults: { _controller: "ApplicationBundle:Guestbook:sign" }
--------------------------------------------------------------------------------
/Tests/Router/Loader/fixtures/routes.ini:
--------------------------------------------------------------------------------
1 | [routes]
2 | routes.archive.route = "archive/:year/*"
3 | routes.archive.defaults.controller = archive
4 | routes.archive.defaults.action = show
5 | routes.archive.defaults.year = 2000
6 | routes.archive.reqs.year = "\d+"
7 |
8 | routes.news.type = "Zend_Controller_Router_Route_Static"
9 | routes.news.route = "news"
10 | routes.news.defaults.controller = "news"
11 | routes.news.defaults.action = "list"
--------------------------------------------------------------------------------
/Resources/examples/Application/Resources/views/Guestbook/index.html.phtml:
--------------------------------------------------------------------------------
1 | Sign Our Guestbook
5 |
6 | Guestbook Entries:
7 |
8 | entries as $entry): ?>
9 | - escape($entry->email) ?>
10 | - escape($entry->comment) ?>
11 |
12 |
--------------------------------------------------------------------------------
/Resources/examples/Application/Resources/config/routing.ini:
--------------------------------------------------------------------------------
1 | [routes]
2 | zfmvccompat_guestbook_homepage.route = "zfguestbook"
3 | zfmvccompat_guestbook_homepage.defaults.module = "Application"
4 | zfmvccompat_guestbook_homepage.defaults.controller = "Guestbook"
5 | zfmvccompat_guestbook_homepage.defaults.action = "index"
6 |
7 | zfmvccompat_guestbook_sign.route = "zfguestbook/sign"
8 | zfmvccompat_guestbook_sign.defaults.module = "Application"
9 | zfmvccompat_guestbook_sign.defaults.controller = "Guestbook"
10 | zfmvccompat_guestbook_sign.defaults.action = "sign"
11 |
--------------------------------------------------------------------------------
/Resources/examples/Application/ApplicationBundle.php:
--------------------------------------------------------------------------------
1 | load("routes.ini");
15 |
16 | $this->assertInstanceOf('Symfony\Component\Routing\Route', $collection->get('archive'));
17 | $this->assertInstanceOf('Symfony\Component\Routing\Route', $collection->get('news'));
18 | }
19 | }
--------------------------------------------------------------------------------
/Resources/examples/Application/Resources/views/layout.html.phtml:
--------------------------------------------------------------------------------
1 | doctype() ?>
2 |
3 |
4 |
5 | Zend Framework Quickstart Application
6 |
7 |
8 |
19 |
20 | content ?>
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Resources/examples/Application/Controller/GuestbookController.php:
--------------------------------------------------------------------------------
1 | view->entries = $guestbook->fetchAll();
12 | }
13 |
14 | public function signAction()
15 | {
16 | $request = $this->getRequest();
17 | $form = new \Application_Form_Guestbook();
18 |
19 | if ($this->getRequest()->isPost()) {
20 | if ($form->isValid($request->getPost())) {
21 | $comment = new \Application_Model_Guestbook($form->getValues());
22 | $mapper = new \Application_Model_GuestbookMapper();
23 | $mapper->save($comment);
24 | return $this->_helper->redirector('index');
25 | }
26 | }
27 |
28 | $this->view->form = $form;
29 | }
30 | }
--------------------------------------------------------------------------------
/Controller/Helpers/ViewRenderer.php:
--------------------------------------------------------------------------------
1 | noRender = (bool)$flag;
29 | return $this;
30 | }
31 |
32 | public function getNoRender()
33 | {
34 | return $this->noRender || self::$neverRender;
35 | }
36 |
37 | public function setNeverRender($flag = true)
38 | {
39 | self::$neverRender = (bool)$flag;
40 | return $this;
41 | }
42 | }
--------------------------------------------------------------------------------
/WhitewashingZFMvcCompatBundle.php:
--------------------------------------------------------------------------------
1 | container->has('whitewashing.zfmvcompat.db')) {
23 | \Zend_Db_Table::setDefaultAdapter($this->container->get('whitewashing.zfmvcompat.db'));
24 | }
25 |
26 | $refl = new \ReflectionClass('Zend_Session');
27 | $vars = array('_sessionStarted', '_readable', '_writable');
28 | foreach ($vars AS $var) {
29 | $property = $refl->getProperty($var);
30 | $property->setAccessible(true);
31 | $property->setValue(null, true);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/View/ParameterBag.php:
--------------------------------------------------------------------------------
1 | $v) {
24 | $this->assign($k, $v);
25 | }
26 | } else {
27 | $this->params[$spec] = $value;
28 | }
29 | }
30 |
31 | public function clearVars()
32 | {
33 | $this->params = array();
34 | return $this;
35 | }
36 |
37 | public function __isset($offset)
38 | {
39 | return isset($this->params[$offset]);
40 | }
41 |
42 | public function __get($offset)
43 | {
44 | return $this->params[$offset];
45 | }
46 |
47 | public function __set($offset, $value)
48 | {
49 | $this->params[$offset] = $value;
50 | }
51 |
52 | public function __unset($offset)
53 | {
54 | unset($this->params[$offset]);
55 | }
56 |
57 | public function allVars()
58 | {
59 | return $this->params;
60 | }
61 | }
--------------------------------------------------------------------------------
/Controller/Helpers/Layout.php:
--------------------------------------------------------------------------------
1 | layout = $defaultLayoutResource;
25 | }
26 |
27 | public function disableLayout()
28 | {
29 | $this->enabled = false;
30 | return $this;
31 | }
32 |
33 | public function enableLayout()
34 | {
35 | $this->enabled = true;
36 | return $this;
37 | }
38 |
39 | public function setLayout($resource, $enable)
40 | {
41 | $this->layout = $resource;
42 | if ($enable) {
43 | $this->enabled = true;
44 | }
45 | return $this;
46 | }
47 |
48 | public function getLayout()
49 | {
50 | return $this->layout;
51 | }
52 |
53 | public function isEnabled()
54 | {
55 | return $this->enabled;
56 | }
57 |
58 | public function getName()
59 | {
60 | return 'layout';
61 | }
62 |
63 | public function direct()
64 | {
65 | return $this;
66 | }
67 | }
--------------------------------------------------------------------------------
/Resources/examples/Application/Form/Guestbook.php:
--------------------------------------------------------------------------------
1 | setMethod('post');
8 |
9 | // Add an email element
10 | $this->addElement('text', 'email', array(
11 | 'label' => 'Your email address:',
12 | 'required' => true,
13 | 'filters' => array('StringTrim'),
14 | 'validators' => array(
15 | 'EmailAddress',
16 | )
17 | ));
18 |
19 | // Add the comment element
20 | $this->addElement('textarea', 'comment', array(
21 | 'label' => 'Please Comment:',
22 | 'required' => true,
23 | 'validators' => array(
24 | array('validator' => 'StringLength', 'options' => array(0, 20))
25 | )
26 | ));
27 |
28 | // Add a captcha
29 | $this->addElement('captcha', 'captcha', array(
30 | 'label' => 'Please enter the 5 letters displayed below:',
31 | 'required' => true,
32 | 'captcha' => array(
33 | 'captcha' => 'Figlet',
34 | 'wordLen' => 5,
35 | 'timeout' => 300
36 | )
37 | ));
38 |
39 | // Add the submit button
40 | $this->addElement('submit', 'submit', array(
41 | 'ignore' => true,
42 | 'label' => 'Sign Guestbook',
43 | ));
44 |
45 | // And finally add some CSRF protection
46 | $this->addElement('hash', 'csrf', array(
47 | 'ignore' => true,
48 | ));
49 | }
50 | }
--------------------------------------------------------------------------------
/Tests/TestInit.php:
--------------------------------------------------------------------------------
1 | registerNamespaces(array(
18 | 'Symfony' => $GLOBALS['SYMFONY2_SRC'],
19 | ));
20 | $loader->registerPrefixes(array(
21 | 'Zend_' => $GLOBALS['ZF1_LIB'],
22 | ));
23 | $loader->register();
24 |
25 | $files = array(
26 | "../View/CoreViewListener.php",
27 | "../View/ParameterBag.php",
28 | "../View/View1.php",
29 | "../View/ZendViewEngine.php",
30 | "../WhitewashingZFMvcCompatBundle.php",
31 | "../DependencyInjection/WhitewashingZFMvcCompatExtension.php",
32 | "../Router/Loader/ZFRouterLoader.php",
33 | "../Controller/ZendController.php",
34 | "../Controller/ZendRequest.php",
35 | "../Controller/ZendResponse.php",
36 | "../Controller/RouteNameParser.php",
37 | "../Controller/CatchAllRequestListener.php",
38 | "../Controller/Helpers/Helper.php",
39 | "../Controller/Helpers/HelperBroker.php",
40 | "../Controller/Helpers/Layout.php",
41 | "../Controller/Helpers/ContextSwitch.php",
42 | "../Controller/Helpers/Redirector.php",
43 | "../Controller/Helpers/UrlHelper.php",
44 | "../Controller/Helpers/ViewRenderer.php",
45 | );
46 |
47 | foreach ($files AS $file) {
48 | require_once($file);
49 | }
--------------------------------------------------------------------------------
/Controller/CatchAllRequestListener.php:
--------------------------------------------------------------------------------
1 | parser = $parser;
30 | $this->enabledBundles = $enabledBundles;
31 | }
32 |
33 | public function resolve(GetResponseEvent $event)
34 | {
35 | $request = $event->getRequest();
36 |
37 | if ($request->attributes->has('_controller')) {
38 | return;
39 | }
40 |
41 | $url = $request->getPathInfo();
42 |
43 | $parts = explode('/', $url);
44 | if (count($parts) < 4) {
45 | return;
46 | }
47 |
48 | $bundle = sprintf('%sBundle', $this->parser->formatModule($parts[1]));
49 |
50 | if (!in_array($bundle, $this->enabledBundles)) {
51 | return;
52 | }
53 |
54 | $controllerName = sprintf(
55 | '%s:%s:%s',
56 | $bundle,
57 | $this->parser->formatController($parts[2]),
58 | $parts[3]
59 | );
60 |
61 | $request->attributes->add(array('_controller'=> $controllerName));
62 | }
63 | }
--------------------------------------------------------------------------------
/Controller/Helpers/HelperBroker.php:
--------------------------------------------------------------------------------
1 | get($helper);
37 | $helper->setActionController($controller);
38 | $this->helpers[$helper->getName()] = $helper;
39 | }
40 | }
41 |
42 | public function __get($helper)
43 | {
44 | return $this->getHelper($helper);
45 | }
46 |
47 | public function getHelper($name)
48 | {
49 | $name = strtolower($name);
50 | if (!isset($this->helpers[$name])) {
51 | throw new \RuntimeException("No Zend ActionHelper with name $name registered.");
52 | }
53 | return $this->helpers[$name];
54 | }
55 |
56 | public function __call($method, $args)
57 | {
58 | $helper = $this->getHelper($method);
59 | return call_user_func_array(array($helper, 'direct'), $args);
60 | }
61 | }
--------------------------------------------------------------------------------
/Resources/examples/Application/Model/Guestbook.php:
--------------------------------------------------------------------------------
1 | setOptions($options);
13 | }
14 | }
15 |
16 | public function __set($name, $value)
17 | {
18 | $method = 'set' . $name;
19 | if (('mapper' == $name) || !method_exists($this, $method)) {
20 | throw new Exception('Invalid guestbook property');
21 | }
22 | $this->$method($value);
23 | }
24 |
25 | public function __get($name)
26 | {
27 | $method = 'get' . $name;
28 | if (('mapper' == $name) || !method_exists($this, $method)) {
29 | throw new Exception('Invalid guestbook property');
30 | }
31 | return $this->$method();
32 | }
33 |
34 | public function setOptions(array $options)
35 | {
36 | $methods = get_class_methods($this);
37 | foreach ($options as $key => $value) {
38 | $method = 'set' . ucfirst($key);
39 | if (in_array($method, $methods)) {
40 | $this->$method($value);
41 | }
42 | }
43 | return $this;
44 | }
45 |
46 | public function setComment($text)
47 | {
48 | $this->_comment = (string) $text;
49 | return $this;
50 | }
51 |
52 | public function getComment()
53 | {
54 | return $this->_comment;
55 | }
56 |
57 | public function setEmail($email)
58 | {
59 | $this->_email = (string) $email;
60 | return $this;
61 | }
62 |
63 | public function getEmail()
64 | {
65 | return $this->_email;
66 | }
67 |
68 | public function setCreated($ts)
69 | {
70 | $this->_created = $ts;
71 | return $this;
72 | }
73 |
74 | public function getCreated()
75 | {
76 | return $this->_created;
77 | }
78 |
79 | public function setId($id)
80 | {
81 | $this->_id = (int) $id;
82 | return $this;
83 | }
84 |
85 | public function getId()
86 | {
87 | return $this->_id;
88 | }
89 | }
--------------------------------------------------------------------------------
/Resources/examples/Application/Model/GuestbookMapper.php:
--------------------------------------------------------------------------------
1 | _dbTable = $dbTable;
15 | return $this;
16 | }
17 |
18 | public function getDbTable()
19 | {
20 | if (null === $this->_dbTable) {
21 | $this->setDbTable('Application_Model_DbTable_Guestbook');
22 | }
23 | return $this->_dbTable;
24 | }
25 |
26 | public function save(Application_Model_Guestbook $guestbook)
27 | {
28 | $data = array(
29 | 'email' => $guestbook->getEmail(),
30 | 'comment' => $guestbook->getComment(),
31 | 'created' => date('Y-m-d H:i:s'),
32 | );
33 |
34 | if (null === ($id = $guestbook->getId())) {
35 | unset($data['id']);
36 | $this->getDbTable()->insert($data);
37 | } else {
38 | $this->getDbTable()->update($data, array('id = ?' => $id));
39 | }
40 | }
41 |
42 | public function find($id, Application_Model_Guestbook $guestbook)
43 | {
44 | $result = $this->getDbTable()->find($id);
45 | if (0 == count($result)) {
46 | return;
47 | }
48 | $row = $result->current();
49 | $guestbook->setId($row->id)
50 | ->setEmail($row->email)
51 | ->setComment($row->comment)
52 | ->setCreated($row->created);
53 | }
54 |
55 | public function fetchAll()
56 | {
57 | $resultSet = $this->getDbTable()->fetchAll();
58 | $entries = array();
59 | foreach ($resultSet as $row) {
60 | $entry = new Application_Model_Guestbook();
61 | $entry->setId($row->id)
62 | ->setEmail($row->email)
63 | ->setComment($row->comment)
64 | ->setCreated($row->created);
65 | $entries[] = $entry;
66 | }
67 | return $entries;
68 | }
69 | }
--------------------------------------------------------------------------------
/DependencyInjection/WhitewashingZFMvcCompatExtension.php:
--------------------------------------------------------------------------------
1 | load('compat.xml');
31 |
32 | foreach ($configs AS $config) {
33 | if (isset($config['default_layout_resource'])) {
34 | $container->setParameter(
35 | 'whitewashing.zfmvccompat.default_layout_resource',
36 | $config['default_layout_resource']
37 | );
38 | }
39 | if (isset($config['catchall_bundles'])) {
40 | $container->setParameter(
41 | 'whitewashing.zfmvccompat.catchall_bundles',
42 | $config['catchall_bundles']
43 | );
44 | }
45 | if (isset($config['db_conn'])) {
46 | $def = new Definition('Zend_Db_Adapter_Abstract');
47 | $def->setFactoryClass('Zend_Db');
48 | $def->setFactoryMethod('factory');
49 | $def->setArguments(array($config['db_conn']['adapter'], $config['db_conn']['params']));
50 |
51 | $container->setDefinition('whitewashing.zfmvcompat.db', $def);
52 | }
53 | }
54 | }
55 |
56 | public function getAlias()
57 | {
58 | return 'whitewashing_zf_mvc_compat';
59 | }
60 | }
--------------------------------------------------------------------------------
/Controller/Helpers/Helper.php:
--------------------------------------------------------------------------------
1 | _actionController = $actionController;
29 | return $this;
30 | }
31 |
32 | /**
33 | * Retrieve current action controller
34 | *
35 | * @return Zend_Controller_Action
36 | */
37 | public function getActionController()
38 | {
39 | return $this->_actionController;
40 | }
41 |
42 | /**
43 | * Hook into action controller initialization
44 | *
45 | * @return void
46 | */
47 | public function init()
48 | {
49 | }
50 |
51 | /**
52 | * Hook into action controller preDispatch() workflow
53 | *
54 | * @return void
55 | */
56 | public function preDispatch()
57 | {
58 | }
59 |
60 | /**
61 | * Hook into action controller postDispatch() workflow
62 | *
63 | * @return void
64 | */
65 | public function postDispatch()
66 | {
67 | }
68 |
69 | /**
70 | * getRequest() -
71 | *
72 | * @return Zend_Controller_Request_Abstract $request
73 | */
74 | public function getRequest()
75 | {
76 | return $this->getActionController()->getRequest();
77 | }
78 |
79 | /**
80 | * getResponse() -
81 | *
82 | * @return Zend_Controller_Response_Abstract $response
83 | */
84 | public function getResponse()
85 | {
86 | return $this->getActionController()->getResponse();
87 | }
88 |
89 | /**
90 | * getName()
91 | *
92 | * @return string
93 | */
94 | abstract public function getName();
95 |
96 | public function __call($method, $args)
97 | {
98 | throw new \BadMethodCallException("$method() is not supported.");
99 | }
100 | }
--------------------------------------------------------------------------------
/Tests/View/ZendViewEngineTest.php:
--------------------------------------------------------------------------------
1 | locator = $this->getMock('Symfony\Component\Config\FileLocatorInterface');
18 | $this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
19 | $this->nameParser = $this->getMock('Symfony\Component\Templating\TemplateNameParserInterface');
20 | $this->view = $this->getMock('Zend_View_Interface');
21 | $this->engine = new ZendViewEngine($this->locator, $this->container, $this->nameParser, $this->view);
22 | }
23 |
24 | public function testSupports()
25 | {
26 | $templateResource = 'HelloBundle:test:index.html.phtml';
27 |
28 | $templateReference = $this->getMock('Symfony\Component\Templating\TemplateReferenceInterface');
29 | $templateReference->expects($this->once())->method('get')
30 | ->with($this->equalTo('engine'))
31 | ->will($this->returnValue('phtml'));
32 |
33 | $this->nameParser->expects($this->once())->method('parse')
34 | ->with($this->equalTo($templateResource))
35 | ->will($this->returnValue($templateReference));
36 |
37 | $this->assertTrue($this->engine->supports($templateResource));
38 | }
39 |
40 | public function testLoad()
41 | {
42 | $templateResource = 'HelloBundle:test:index.html.phtml';
43 | $parsedTemplate = array(
44 | 'engine' => 'phtml', 'format' => 'html',
45 | 'bundle' => 'HelloBundle', 'controller' => 'test', 'action' => 'index'
46 | );
47 | $templatePath = '/template.path';
48 |
49 | $this->nameParser->expects($this->exactly(2))->method('parse')
50 | ->with($this->equalTo($templateResource))
51 | ->will($this->returnValue($parsedTemplate));
52 |
53 | $this->locator->expects($this->once())->method('locate')
54 | ->with($this->equalTo($parsedTemplate))
55 | ->will($this->returnValue($templatePath));
56 |
57 | $this->assertEquals($templatePath, $this->engine->load($templateResource));
58 | $this->assertEquals($templatePath, $this->engine->load($templateResource));
59 | }
60 | }
--------------------------------------------------------------------------------
/View/View1.php:
--------------------------------------------------------------------------------
1 | container = $container;
27 | $this->parser = $parser;
28 | }
29 |
30 | public function action($action, $controller, $module, array $params = array())
31 | {
32 | $options['attributes'] = $params;
33 |
34 | $symfonyController = sprintf('%sBundle:%s:%s',
35 | $this->parser->formatModule($module), $this->parser->formatController($controller), $action
36 | );
37 | return $this->container->get('http_kernel')->render($symfonyController, $options);
38 | }
39 |
40 | public function baseUrl()
41 | {
42 | return $this->container->get('request')->getUriForPath('/');
43 | }
44 |
45 | public function partial($resource, array $params = array())
46 | {
47 | return $this->container->get('templating')->render($resource, $params);
48 | }
49 |
50 | public function partialLoop($resource, array $models = array())
51 | {
52 | $html = '';
53 | foreach ($models AS $model) {
54 | $html .= $this->container->get('templating')->render($resource, $model);
55 | }
56 | return $html;
57 | }
58 |
59 | public function url(array $urlOptions = array(), $name = null, $absolute = false)
60 | {
61 | return $this->container->get('whitewashing.zfmvccompat.actionhelper.url')->url($urlOptions, $name, $absolute);
62 | }
63 |
64 | public function flashMessenger()
65 | {
66 | $flashMessenger = $this->container->get('whitewashing.zfmvccompat.actionhelper.flashmessenger');
67 |
68 | //get messages from previous requests
69 | $messages = $flashMessenger->getMessages();
70 |
71 | //add any messages from this request
72 | if ($flashMessenger->hasCurrentMessages()) {
73 | $messages = array_merge($messages, $flashMessenger->getCurrentMessages());
74 | //we don't need to display them twice.
75 | $flashMessenger->clearCurrentMessages();
76 | }
77 |
78 | return $messages;
79 | }
80 | }
--------------------------------------------------------------------------------
/Controller/ZendResponse.php:
--------------------------------------------------------------------------------
1 | headers[$name]) && !$replace) {
28 | return $this;
29 | }
30 |
31 | $this->headers[$name] = $value;
32 | return $this;
33 | }
34 |
35 | public function setRedirect($url, $status = 302)
36 | {
37 | $this->redirect = $url;
38 | $this->status = $status;
39 | }
40 |
41 | public function generateResponse()
42 | {
43 | $response = new Response($this->content, $this->status, $this->headers);
44 | if ($this->redirect) {
45 | $response->setRedirect($this->redirect, $this->status);
46 | }
47 | }
48 |
49 | public function isRedirect()
50 | {
51 | return $this->redirect !== false;
52 | }
53 |
54 | public function getHeaders()
55 | {
56 | return $this->headers;
57 | }
58 |
59 | public function clearHeaders()
60 | {
61 | $this->headers = array();
62 | return $this;
63 | }
64 |
65 | public function clearHeader($name)
66 | {
67 | unset($this->headers[$name]);
68 | return $this;
69 | }
70 |
71 | public function clearAllHeaders()
72 | {
73 | $this->clearHeaders();
74 | }
75 |
76 | public function setHttpResponseCode($status)
77 | {
78 | $this->status = $status;
79 | return $this;
80 | }
81 |
82 | public function getHttpResponseCode()
83 | {
84 | return $this->status;
85 | }
86 |
87 | public function setBody($content)
88 | {
89 | $this->content = $content;
90 | return $this;
91 | }
92 |
93 | public function appendBody($content)
94 | {
95 | $this->content .= $content;
96 | return $this;
97 | }
98 |
99 | public function clearBody()
100 | {
101 | $this->content = "";
102 | return $this;
103 | }
104 |
105 | public function getBody()
106 | {
107 | return $this->content;
108 | }
109 |
110 | public function __call($method, $args)
111 | {
112 | throw new \BadMethodCallException("not implemented");
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/Router/Loader/ZFRouterLoader.php:
--------------------------------------------------------------------------------
1 | locator->locate($file);
22 | $type = $type ?: pathinfo($file, PATHINFO_EXTENSION);
23 | switch($type) {
24 | case 'php':
25 | $data = require($file);
26 | $config = new \Zend_Config($data);
27 | break;
28 | case 'xml':
29 | $config = new \Zend_Config_Xml($file);
30 | break;
31 | case 'ini':
32 | $config = new \Zend_Config_Ini($file, "routes");
33 | break;
34 | }
35 | $data = $config->toArray();
36 | if (isset($data['routes'])) {
37 | $data = $data['routes'];
38 | }
39 |
40 | $collection = new RouteCollection;
41 | foreach ($data AS $routeName => $config) {
42 | if (isset($config['type']) && $config['type'] == "Zend_Controller_Router_Route_Regex") {
43 | throw new \InvalidArgumentException("Not supported");
44 | }
45 |
46 | if (!isset($config['reqs'])) {
47 | $config['reqs'] = array();
48 | }
49 | if (!isset($config['defaults'])) {
50 | $config['defaults'] = array();
51 | }
52 | if (!isset($config['options'])) {
53 | $config['options'] = array();
54 | }
55 |
56 | if (!isset($config['defaults']['module'])) {
57 | // TODO: DefaultModule config
58 | $config['defaults']['module'] = 'Default';
59 | }
60 | if (!isset($config['defaults']['controller'])) {
61 | $config['defaults']['controller'] = 'Index';
62 | }
63 | if (!isset($config['defaults']['action'])) {
64 | $config['defaults']['action'] = 'index';
65 | }
66 | $config['defaults']['_controller'] = sprintf('%sBundle:%s:%s',
67 | $config['defaults']['module'],
68 | $config['defaults']['controller'],
69 | $config['defaults']['action']
70 | );
71 |
72 | if (preg_match_all('(:([^/]+)+)', $config['route'], $matches)) {
73 | for ($i = 0; $i < count($matches[0]); $i++) {
74 | $config['route'] = str_replace($matches[0][$i], "{" . $matches[1][$i] . "}", $config['route']);
75 | }
76 | }
77 |
78 | $route = new Route($config['route'], $config['defaults'], $config['reqs'], $config['options']);
79 | $collection->add($routeName, $route);
80 | }
81 |
82 | return $collection;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Tests/Controller/RouteNameParserTest.php:
--------------------------------------------------------------------------------
1 | kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
25 | $this->parser = new RouteNameParser($this->kernel);
26 | }
27 |
28 | public function testNotSupportsServices()
29 | {
30 | $this->assertEquals(array(), $this->parser->parse('fos_user_controller.actionName'));
31 | }
32 |
33 | public function testSupportsUncompiledSyntax()
34 | {
35 | $this->assertEquals(
36 | array("module" => "Hello", "controller" => "Test", "action" => "index"),
37 | $this->parser->parse("HelloBundle:Test:index")
38 | );
39 | }
40 |
41 | public function testSupportsCompiledSyntax()
42 | {
43 | $bundle = $this->getMock('WhitewashingCompatCompiledBundleMock', array('getName', 'getNamespace'));
44 | $bundle->expects($this->at(0))
45 | ->method('getNamespace')
46 | ->will($this->returnValue('Whitewashing\ZFMvcCompatBundle'));
47 | $bundle->expects($this->at(1))
48 | ->method('getName')
49 | ->will($this->returnValue('HelloBundle'));
50 |
51 | $this->kernel->expects($this->once())
52 | ->method('getBundles')
53 | ->will($this->returnValue(array($bundle)));
54 |
55 | $this->assertEquals(
56 | array("module" => "Hello", "controller" => "Test", "action" => "index"),
57 | $this->parser->parse("Whitewashing\\ZFMvcCompatBundle\\Tests\\Controller\\TestController::indexAction")
58 | );
59 |
60 | // cached?
61 | $this->assertEquals(
62 | array("module" => "Hello", "controller" => "Test", "action" => "index"),
63 | $this->parser->parse("Whitewashing\\ZFMvcCompatBundle\\Tests\\Controller\\TestController::indexAction")
64 | );
65 | }
66 |
67 | public function testFormatModule()
68 | {
69 | $bundle = $this->getMock('WhitewashingCompatFormatBundleMock', array('getName', 'getNamespace'));
70 | $bundle->expects($this->any())
71 | ->method('getName')
72 | ->will($this->returnValue('HeLLoBundle'));
73 |
74 | $this->kernel->expects($this->once())
75 | ->method('getBundles')
76 | ->will($this->returnValue(array($bundle)));
77 |
78 | $this->assertEquals('HeLLo', $this->parser->formatModule('hello'));
79 | }
80 |
81 | public function testFormatController()
82 | {
83 | $this->assertEquals('Test', $this->parser->formatController('test'));
84 | }
85 | }
86 |
87 | class TestController
88 | {
89 |
90 | }
--------------------------------------------------------------------------------
/Controller/RouteNameParser.php:
--------------------------------------------------------------------------------
1 | kernel = $kernel;
32 | }
33 |
34 | public function parse($symfonyControllerName)
35 | {
36 | if (isset($this->cache[$symfonyControllerName])) {
37 | return $this->cache[$symfonyControllerName];
38 | }
39 |
40 | // skip controllers as services
41 | if (strpos($symfonyControllerName, ".") !== false) {
42 | return array();
43 | }
44 |
45 | if (substr_count($symfonyControllerName, "::") == 1) {
46 | $details = array();
47 | list($controllerName, $actionName) = explode("::", $symfonyControllerName);
48 | $details['action'] = str_replace("Action", "", $actionName);
49 | $controllerRefl = new \ReflectionClass($controllerName);
50 | $details['controller'] = str_replace("Controller", "", $controllerRefl->getShortName());
51 | $controllerNamespace = $controllerRefl->getNamespaceName();
52 |
53 | foreach ($this->kernel->getBundles() AS $bundle) {
54 | if (strpos($controllerNamespace, $bundle->getNamespace()) === 0) {
55 | $details['module'] = str_replace("Bundle", "", $bundle->getName());
56 | break;
57 | }
58 | }
59 | } else {
60 | list($module, $controller, $action) = explode(":", $symfonyControllerName);
61 | $details['action'] = $action;
62 | $details['controller'] = $controller;
63 | $details['module'] = str_replace("Bundle", "", $module);
64 | }
65 |
66 | return $this->cache[$symfonyControllerName] = $details;
67 | }
68 |
69 | /**
70 | * Get correct casing of the module which is based on the bundle.
71 | *
72 | * @param string $module
73 | * @return string
74 | */
75 | public function formatModule($module)
76 | {
77 | $module = strtolower($module);
78 | if (isset($this->moduleCache[$module])) {
79 | return $this->moduleCache[$module];
80 | }
81 |
82 | foreach ($this->kernel->getBundles() AS $bundle) {
83 | if ($module."bundle" == strtolower($bundle->getName())) {
84 | return $this->moduleCache[$module] = str_replace("Bundle", "", $bundle->getName());
85 | }
86 | }
87 | throw new \RuntimeException("Couldnt find a matching bundle for the module $module");
88 | }
89 |
90 | public function formatController($controller)
91 | {
92 | return ucfirst($controller);
93 | }
94 | }
--------------------------------------------------------------------------------
/Controller/Helpers/UrlHelper.php:
--------------------------------------------------------------------------------
1 | router = $router;
35 | $this->routeNameParser = $routeNameParser;
36 | $this->request = $request;
37 | }
38 |
39 | public function simple($action, $controller = null, $module = null, array $params = array())
40 | {
41 | $zendRequest = $this->getActionController()->getRequest();
42 | if (!$controller) {
43 | $controller = $zendRequest->getControllerName();
44 | } else {
45 | $controller = $this->routeNameParser->formatController($controller);
46 | }
47 | if (!$module) {
48 | $module = $zendRequest->getModuleName();
49 | } else {
50 | $module = $this->routeNameParser->formatModule($module);
51 | }
52 |
53 | $routes = $this->router->getRouteCollection()->all();
54 | foreach ($routes AS $route) {
55 | $details = $this->routeNameParser->parse($route->getDefault('_controller'));
56 | if (!isset($details['module']) || !isset($details['controller']) || !isset($details['action'])) {
57 | continue;
58 | }
59 |
60 | $defaults = $route->getDefaults();
61 | if ($module == $details['module'] &&
62 | $controller == $details['controller'] &&
63 | $action == $details['action'] &&
64 | count(array_intersect_key($defaults, $params)) == (count($defaults)-1) ) {
65 |
66 | /* @var $pattern Route */
67 | $pattern = $route->getPattern();
68 | foreach ($params AS $name => $value) {
69 | $pattern = str_replace("{$name}", $value, $pattern);
70 | }
71 |
72 | return $this->request->getUriForPath($pattern);
73 | }
74 | }
75 | throw new \RuntimeException("Did not find a route matching the given module/controller/actions pair.");
76 | }
77 |
78 | public function url($urlOptions = array(), $name = null, $absolute = false)
79 | {
80 | if ($name === null) {
81 | $name = $this->request->get('_route');
82 | }
83 |
84 | return $this->router->generate($name, $urlOptions, $absolute);
85 | }
86 |
87 | public function getName()
88 | {
89 | return 'url';
90 | }
91 |
92 | public function direct($action, $controller = null, $module = null, array $params = array())
93 | {
94 | return $this->simple($action, $controller, $module, $params);
95 | }
96 | }
--------------------------------------------------------------------------------
/View/CoreViewListener.php:
--------------------------------------------------------------------------------
1 | templating = $templating;
38 | $this->zendView = $zendView;
39 | }
40 |
41 | public function filterResponse(GetResponseForControllerResultEvent $event)
42 | {
43 | /* @var $request \Symfony\Component\HttpFoundation\Request */
44 | $request = $event->getRequest();
45 |
46 |
47 | if ($request->attributes->has('zend_compat_controller') && !$event->hasResponse()) {
48 | /* @var $zendController ZendController */
49 | $zendController = $request->attributes->get('zend_compat_controller');
50 | $zendController->postDispatch();
51 | /* @var $zendRequest ZendRequest */
52 | $zendRequest = $zendController->getRequest();
53 |
54 | /* @var $response Symfony\Component\HttpFoundation\Response */
55 | $response = new Response();
56 |
57 | /* @var $zendResponse ZendResponse */
58 | $zendResponse = $zendController->getResponse();
59 | $response->headers->add($zendResponse->getHeaders());
60 | $response->setStatusCode($zendResponse->getHttpResponseCode());
61 |
62 | if ($zendController->getHelper('viewrenderer')->getNoRender() === false) {
63 | // TODO: "html" => ContextSwitch
64 | $viewName = sprintf("%sBundle:%s:%s.%s.%s",
65 | $zendRequest->getModuleName(),
66 | $zendRequest->getControllerName(),
67 | $zendRequest->getActionName(),
68 | "html", "phtml"
69 | );
70 |
71 | $vars = $zendController->view->allVars();
72 | foreach ($vars AS $k => $v) {
73 | if ($v instanceof \Zend_Form) {
74 | $v->setView($this->zendView);
75 |
76 | foreach ($v->getElements() as $element) {
77 | $element->setView($this->zendView);
78 | }
79 | }
80 | }
81 |
82 | $content = $this->templating->render($viewName, $vars);
83 |
84 | if ($zendController->getHelper('layout')->isEnabled()) {
85 | $content = $this->templating->render($zendController->getHelper('layout')->getLayout(), array('content' => $content));
86 | }
87 | $response->setContent($content);
88 | }
89 | $event->setResponse($response);
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Controller/Helpers/Redirector.php:
--------------------------------------------------------------------------------
1 | urlHelper = $urlHelper;
38 | }
39 |
40 | public function getName()
41 | {
42 | return "redirector";
43 | }
44 |
45 | /**
46 | * Return use absolute URI flag
47 | *
48 | * @return boolean
49 | */
50 | public function getUseAbsoluteUri()
51 | {
52 | return $this->useAbsoluteUri;
53 | }
54 |
55 | /**
56 | * Set use absolute URI flag
57 | *
58 | * @param boolean $flag
59 | * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface
60 | */
61 | public function setUseAbsoluteUri($flag = true)
62 | {
63 | $this->useAbsoluteUri = ($flag) ? true : false;
64 | return $this;
65 | }
66 |
67 | public function setGotoSimple($action, $controller = null, $module = null, array $params = array())
68 | {
69 | $this->response = new RedirectResponse($this->urlHelper->direct($action, $controller, $module, $params));
70 | }
71 |
72 | public function setGotoRoute(array $urlOptions = array(), $name = null, $absolute = true)
73 | {
74 | $this->response = new RedirectResponse($this->urlHelper->url($urlOptions, $name, $absolute || $this->useAbsoluteUri));
75 | }
76 |
77 | public function setGotoUrl($url, array $options = array())
78 | {
79 | if (!isset($options['code'])) {
80 | $options['code'] = null;
81 | }
82 | $this->response = new RedirectResponse($url, $options['code']);
83 | }
84 |
85 | public function gotoSimple($action, $controller = null, $module = null, array $params = array())
86 | {
87 | $this->setGotoSimple($action, $controller, $module, $params);
88 | return $this->response;
89 | }
90 |
91 | public function gotoSimpleAndExit($action, $controller = null, $module = null, array $params = array())
92 | {
93 | $this->setGotoSimple($action, $controller, $module, $params);
94 | return $this->response;
95 | }
96 |
97 | public function gotoRoute(array $urlOptions = array(), $name = null, $absolute = true)
98 | {
99 | $this->setGotoRoute($urlOptions, $name, $absolute || $this->useAbsoluteUri);
100 | return $this->response;
101 | }
102 |
103 | public function gotoRouteAndExit(array $urlOptions = array(), $absolute = true)
104 | {
105 | $this->setGotoRoute($urlOptions, $name, $absolute || $this->useAbsoluteUri);
106 | return $this->response;
107 | }
108 |
109 | public function gotoUrl($url, array $options = array())
110 | {
111 | $this->setGotoUrl($url, $options);
112 | return $this->response;
113 | }
114 |
115 | public function gotoUrlAndExit($url, array $options = array())
116 | {
117 | $this->setGotoUrl($url, $options);
118 | return $this->response;
119 | }
120 |
121 | public function direct($action, $controller = null, $module = null, array $params = array())
122 | {
123 | return $this->gotoSimple($action, $controller, $module, $params);
124 | }
125 | }
--------------------------------------------------------------------------------
/View/ZendViewEngine.php:
--------------------------------------------------------------------------------
1 | locator = $locator;
71 | $this->container = $container;
72 | $this->parser = $parser;
73 | $this->view = $zendView;
74 | // Zend View is not able to handle absolute paths except with this little trick
75 | $this->view->setScriptPath('');
76 | }
77 |
78 | public function exists($name)
79 | {
80 | return (file_exists($this->findTemplate($name)));
81 | }
82 |
83 | public function load($name)
84 | {
85 | return $this->findTemplate($name);
86 | }
87 |
88 | public function render($name, array $parameters = array())
89 | {
90 | $templateName = $this->load($name);
91 | $view = clone $this->view;
92 | $view->assign($parameters);
93 | return $view->render($templateName);
94 | }
95 |
96 | /**
97 | * Renders a view and returns a Response.
98 | *
99 | * @param string $view The view name
100 | * @param array $parameters An array of parameters to pass to the view
101 | * @param Response $response A Response instance
102 | *
103 | * @return Response A Response instance
104 | */
105 | public function renderResponse($view, array $parameters = array(), Response $response = null)
106 | {
107 | if (null === $response) {
108 | $response = $this->container->get('response');
109 | }
110 |
111 | $response->setContent($this->render($view, $parameters));
112 |
113 | return $response;
114 | }
115 |
116 | public function supports($name)
117 | {
118 | $template = $this->parser->parse($name);
119 | return $template && 'phtml' === $template->get('engine');
120 | }
121 |
122 | protected function findTemplate($name)
123 | {
124 | if (!is_array($name)) {
125 | $name = $this->parser->parse($name);
126 | }
127 |
128 | $key = md5(serialize($name));
129 | if (isset($this->cache[$key])) {
130 | return $this->cache[$key];
131 | }
132 |
133 | if (false == $file = $this->locator->locate($name)) {
134 | throw new \RuntimeException(sprintf('Unable to find template "%s".', json_encode($name)));
135 | }
136 |
137 | return $this->cache[$key] = $file;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/Controller/ZendController.php:
--------------------------------------------------------------------------------
1 | container = $container;
48 | $this->request = $container->get('request');
49 | $this->request->attributes->set('zend_compat_controller', $this);
50 | $this->_request = $this->container->get('whitewashing.zfmvccompat.controller.request');
51 | $this->_response = new ZendResponse();
52 | $this->view = new ParameterBag();
53 | $this->_helper = new HelperBroker($this->container, $this);
54 |
55 | $this->init();
56 | $this->preDispatch();
57 | }
58 |
59 | public function init() {}
60 |
61 | public function preDispatch() {}
62 |
63 | public function postDispatch() {}
64 |
65 | /**
66 | * @param string $name
67 | * @return Helper
68 | */
69 | public function getHelper($name)
70 | {
71 | return $this->_helper->getHelper($name);
72 | }
73 |
74 | protected function _getParam($name, $default = null)
75 | {
76 | $value = $this->_request->getParam($name);
77 | if ((null === $value || '' === $value) && (null !== $default)) {
78 | $value = $default;
79 | }
80 |
81 | return $value;
82 | }
83 |
84 | protected function _setParam($name, $value)
85 | {
86 | $this->_request->setParam($name, $value);
87 | return $this;
88 | }
89 |
90 | protected function _hasParam($name)
91 | {
92 | return null !== $this->_request->getParam($name);
93 | }
94 |
95 | protected function _getAllParams()
96 | {
97 | return $this->_request->getParams();
98 | }
99 |
100 | /**
101 | * @return ZendRequest
102 | */
103 | public function getRequest()
104 | {
105 | return $this->_request;
106 | }
107 |
108 | /**
109 | * @return ZendResponse
110 | */
111 | public function getResponse()
112 | {
113 | return $this->_response;
114 | }
115 |
116 | /**
117 | * Forward to another controller/action.
118 | *
119 | * It is important to supply the unformatted names, i.e. "article"
120 | * rather than "ArticleController". The dispatcher will do the
121 | * appropriate formatting when the request is received.
122 | *
123 | * If only an action name is provided, forwards to that action in this
124 | * controller.
125 | *
126 | * If an action and controller are specified, forwards to that action and
127 | * controller in this module.
128 | *
129 | * Specifying an action, controller, and module is the most specific way to
130 | * forward.
131 | *
132 | * A fourth argument, $params, will be used to set the request parameters.
133 | * If either the controller or module are unnecessary for forwarding,
134 | * simply pass null values for them before specifying the parameters.
135 | *
136 | * @param string $action
137 | * @param string $controller
138 | * @param string $module
139 | * @param array $params
140 | * @return void
141 | */
142 | final protected function _forward($action, $controller = null, $module = null, array $params = null)
143 | {
144 | if (!$controller) {
145 | $controller = $this->_request->getControllerName();
146 | }
147 | if (!$module) {
148 | $module = $this->_request->getModuleName();
149 | }
150 |
151 | $nameParser = $this->container->get('whitewashing.zfmvccompat.nameparser');
152 | $controller = $nameParser->formatModule($module)."Bundle:".$nameParser->formatController($controller).":".$action;
153 | return $this->container->get('http_kernel')->forward($controller, array(), $params);
154 | }
155 |
156 | /**
157 | * Redirect to another URL
158 | *
159 | * Proxies to {@link Zend_Controller_Action_Helper_Redirector::gotoUrl()}.
160 | *
161 | * @param string $url
162 | * @param array $options Options to be used when redirecting
163 | * @return RedirectResponse The symfony redirect response
164 | */
165 | protected function _redirect($url, array $options = array())
166 | {
167 | return new RedirectResponse($this->container->get('request')->getUriForPath($url));
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/Resources/config/compat.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Whitewashing\ZFMvcCompatBundle\View\ZendViewEngine
9 | WhitewashingZFMvcCompatBundle::layout.html.phtml
10 |
11 |
12 | Whitewashing\ZFMvcCompatBundle\View\CoreViewListener
13 | Whitewashing\ZFMvcCompatBundle\Controller\CatchAllRequestListener
14 | Whitewashing\ZFMvcCompatBundle\View\View1
15 | Whitewashing\ZFMvcCompatBundle\Controller\RouteNameParser
16 | Whitewashing\ZFMvcCompatBundle\Controller\ZendRequest
17 | Whitewashing\ZFMvcCompatBundle\Controller\Helpers\ContextSwitch
18 | Whitewashing\ZFMvcCompatBundle\Controller\Helpers\FlashMessenger
19 | Whitewashing\ZFMvcCompatBundle\Controller\Helpers\UrlHelper
20 | Whitewashing\ZFMvcCompatBundle\Controller\Helpers\Redirector
21 | Whitewashing\ZFMvcCompatBundle\Controller\Helpers\Layout
22 | Whitewashing\ZFMvcCompatBundle\Controller\Helpers\ViewRenderer
23 | Whitewashing\ZFMvcCompatBundle\Router\Loader\ZFRouterLoader
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | %whitewashing.zfmvccompat.catchall_bundles%
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | %whitewashing.zfmvccompat.default_layout_resource%
80 |
81 |
82 |
83 | %whitewashing.zfmvccompat.default_layout_resource%
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/Controller/Helpers/FlashMessenger.php:
--------------------------------------------------------------------------------
1 | get('session')->setFlash($namespace, $message)
9 | *
10 | * @author Richard Fullmer
11 | */
12 | class FlashMessenger extends Helper
13 | {
14 | /**
15 | * $_messages - Messages from previous request
16 | *
17 | * @var array
18 | */
19 | static protected $_messages = array();
20 |
21 | /**
22 | * $_session - Zend_Session storage object
23 | *
24 | * @var Zend_Session
25 | */
26 | static protected $_session = null;
27 |
28 | /**
29 | * $_messageAdded - Wether a message has been previously added
30 | *
31 | * @var boolean
32 | */
33 | static protected $_messageAdded = false;
34 |
35 | /**
36 | * $_namespace - Instance namespace, default is 'default'
37 | *
38 | * @var string
39 | */
40 | protected $_namespace = 'default';
41 |
42 | /**
43 | * __construct() - Instance constructor, needed to get iterators, etc
44 | *
45 | * @param string $namespace
46 | * @return void
47 | */
48 | public function __construct()
49 | {
50 | if (!self::$_session instanceof \Zend_Session_Namespace) {
51 | self::$_session = new \Zend_Session_Namespace($this->getName());
52 | foreach (self::$_session as $namespace => $messages) {
53 | self::$_messages[$namespace] = $messages;
54 | unset(self::$_session->{$namespace});
55 | }
56 | }
57 | }
58 |
59 | /**
60 | * setNamespace() - change the namespace messages are added to, useful for
61 | * per action controller messaging between requests
62 | *
63 | * @param string $namespace
64 | * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
65 | */
66 | public function setNamespace($namespace = 'default')
67 | {
68 | $this->_namespace = $namespace;
69 | return $this;
70 | }
71 |
72 | /**
73 | * resetNamespace() - reset the namespace to the default
74 | *
75 | * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
76 | */
77 | public function resetNamespace()
78 | {
79 | $this->setNamespace();
80 | return $this;
81 | }
82 |
83 | /**
84 | * addMessage() - Add a message to flash message
85 | *
86 | * @param string $message
87 | * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
88 | */
89 | public function addMessage($message)
90 | {
91 | if (self::$_messageAdded === false) {
92 | self::$_session->setExpirationHops(1, null, true);
93 | }
94 |
95 | if (!is_array(self::$_session->{$this->_namespace})) {
96 | self::$_session->{$this->_namespace} = array();
97 | }
98 |
99 | self::$_session->{$this->_namespace}[] = $message;
100 |
101 | return $this;
102 | }
103 |
104 | /**
105 | * hasMessages() - Wether a specific namespace has messages
106 | *
107 | * @return boolean
108 | */
109 | public function hasMessages()
110 | {
111 | return isset(self::$_messages[$this->_namespace]);
112 | }
113 |
114 | /**
115 | * getMessages() - Get messages from a specific namespace
116 | *
117 | * @return array
118 | */
119 | public function getMessages()
120 | {
121 | if ($this->hasMessages()) {
122 | return self::$_messages[$this->_namespace];
123 | }
124 |
125 | return array();
126 | }
127 |
128 | /**
129 | * Clear all messages from the previous request & current namespace
130 | *
131 | * @return boolean True if messages were cleared, false if none existed
132 | */
133 | public function clearMessages()
134 | {
135 | if ($this->hasMessages()) {
136 | unset(self::$_messages[$this->_namespace]);
137 | return true;
138 | }
139 |
140 | return false;
141 | }
142 |
143 | /**
144 | * hasCurrentMessages() - check to see if messages have been added to current
145 | * namespace within this request
146 | *
147 | * @return boolean
148 | */
149 | public function hasCurrentMessages()
150 | {
151 | return isset(self::$_session->{$this->_namespace});
152 | }
153 |
154 | /**
155 | * getCurrentMessages() - get messages that have been added to the current
156 | * namespace within this request
157 | *
158 | * @return array
159 | */
160 | public function getCurrentMessages()
161 | {
162 | if ($this->hasCurrentMessages()) {
163 | return self::$_session->{$this->_namespace};
164 | }
165 |
166 | return array();
167 | }
168 |
169 | /**
170 | * clear messages from the current request & current namespace
171 | *
172 | * @return boolean
173 | */
174 | public function clearCurrentMessages()
175 | {
176 | if ($this->hasCurrentMessages()) {
177 | unset(self::$_session->{$this->_namespace});
178 | return true;
179 | }
180 |
181 | return false;
182 | }
183 |
184 | /**
185 | * getIterator() - complete the IteratorAggregate interface, for iterating
186 | *
187 | * @return ArrayObject
188 | */
189 | public function getIterator()
190 | {
191 | if ($this->hasMessages()) {
192 | return new \ArrayObject($this->getMessages());
193 | }
194 |
195 | return new \ArrayObject();
196 | }
197 |
198 | /**
199 | * count() - Complete the countable interface
200 | *
201 | * @return int
202 | */
203 | public function count()
204 | {
205 | if ($this->hasMessages()) {
206 | return count($this->getMessages());
207 | }
208 |
209 | return 0;
210 | }
211 |
212 | /**
213 | * Strategy pattern: proxy to addMessage()
214 | *
215 | * @param string $message
216 | */
217 | public function direct($message)
218 | {
219 | return $this->addMessage($message);
220 | }
221 |
222 | /**
223 | * getName()
224 | *
225 | * @return string
226 | */
227 | public function getName()
228 | {
229 | return 'flashmessenger';
230 | }
231 |
232 |
233 | }
234 |
--------------------------------------------------------------------------------
/Controller/ZendRequest.php:
--------------------------------------------------------------------------------
1 | request = $request;
48 | $this->parser = $parser;
49 | }
50 |
51 | private function parseRequest()
52 | {
53 | if ($this->actionName) {
54 | return;
55 | }
56 |
57 | $details = $this->parser->parse($this->request->attributes->get('_controller'));
58 | $this->actionName = $details['action'];
59 | $this->controllerName = $details['controller'];
60 | $this->moduleName = $details['module'];
61 | }
62 |
63 | public function __get($name)
64 | {
65 | if ($this->request->attributes->has($name)) {
66 | return $this->request->attributes->get($name);
67 | } else if ($this->request->query->has($name)) {
68 | return $this->request->query->get($name);
69 | } else if ($this->request->request->has($name)) {
70 | return $this->request->request->get($name);
71 | } else if ($this->request->cookies->has($name)) {
72 | return $this->request->cookies->get($name);
73 | } else if ($this->request->server->has($name)) {
74 | return $this->request->server->get($name);
75 | } else {
76 | return null;
77 | }
78 | }
79 |
80 | public function get($name)
81 | {
82 | return $this->__get($name);
83 | }
84 |
85 | public function set($name, $value)
86 | {
87 | throw new \BadMethodCallException("Cannot set value, please use setParam()");
88 | }
89 |
90 | public function __set($name, $value)
91 | {
92 | $this->set($name, $value);
93 | }
94 |
95 | public function has($name)
96 | {
97 | if (isset($this->request->attributes[$name])) {
98 | return true;
99 | } else if (isset($this->request->query[$name])) {
100 | return true;
101 | } else if (isset($this->request->request[$name])) {
102 | return true;
103 | } else if (isset($this->request->cookies[$name])) {
104 | return true;
105 | } else if (isset($this->request->server[$name])) {
106 | return true;
107 | } else {
108 | return false;
109 | }
110 | }
111 |
112 | public function __isset($name)
113 | {
114 | return $this->has($name);
115 | }
116 |
117 | public function getQuery($name = null, $default = null)
118 | {
119 | if (null === $name) {
120 | return $this->request->query->all();
121 | }
122 |
123 | return (isset($this->request->query[$name])) ? $this->request->query[$name] : $default;
124 | }
125 |
126 | public function getPost($name = null, $default = null)
127 | {
128 | if (null === $name) {
129 | return $this->request->request->all();
130 | }
131 |
132 | return (isset($this->request->request[$name])) ? $this->request->request[$name] : $default;
133 | }
134 |
135 | public function getCookie($name = null, $default = null)
136 | {
137 | if (null === $name) {
138 | return $this->request->cookies->all();
139 | }
140 |
141 | return (isset($this->request->cookies[$name])) ? $this->request->cookies[$name] : $default;
142 | }
143 |
144 | public function getServer($name = null, $default = null)
145 | {
146 | if (null === $name) {
147 | return $this->request->server->all();
148 | }
149 |
150 | return (isset($this->request->server[$name])) ? $this->request->server[$name] : $default;
151 | }
152 |
153 | public function getEnv($key = null, $default = null)
154 | {
155 | if (null === $key) {
156 | return $_ENV;
157 | }
158 |
159 | return (isset($_ENV[$key])) ? $_ENV[$key] : $default;
160 | }
161 |
162 | public function getRequestUri()
163 | {
164 | return $this->request->getRequestUri();
165 | }
166 |
167 | public function getBaseUrl()
168 | {
169 | return $this->request->getBaseUrl();
170 | }
171 |
172 | public function getBasePath()
173 | {
174 | return $this->request->getBasePath();
175 | }
176 |
177 | public function getPathInfo()
178 | {
179 | return $this->request->getPathInfo();
180 | }
181 |
182 | /**
183 | * Set allowed parameter sources
184 | *
185 | * Can be empty array, or contain one or more of '_GET' or '_POST'.
186 | *
187 | * @param array $paramSoures
188 | * @return Zend_Controller_Request_Http
189 | */
190 | public function setParamSources(array $paramSources = array())
191 | {
192 | $this->paramSources = $paramSources;
193 | return $this;
194 | }
195 |
196 | /**
197 | * Get list of allowed parameter sources
198 | *
199 | * @return array
200 | */
201 | public function getParamSources()
202 | {
203 | return $this->paramSources;
204 | }
205 |
206 | public function getParam($key, $default = null)
207 | {
208 | $paramSources = $this->getParamSources();
209 | if (isset($this->_params[$key])) {
210 | return $this->_params[$key];
211 | } else if ($this->request->attributes->has($key)) {
212 | return $this->request->attributes->get($key);
213 | } elseif (in_array('_GET', $paramSources) && $this->request->query->has($key)) {
214 | return $this->request->query->get($key);
215 | } elseif (in_array('_POST', $paramSources) && $this->request->request->has($key)) {
216 | return $this->request->request->get($key);
217 | }
218 |
219 | return $default;
220 | }
221 |
222 | public function getParams()
223 | {
224 | $return = $this->params;
225 | $paramSources = $this->getParamSources();
226 | if (in_array('_GET', $paramSources)) {
227 | $return += $this->request->query->all();
228 | }
229 | if (in_array('_POST', $paramSources)) {
230 | $return += $this->request->request->all();
231 | }
232 | return $return;
233 | }
234 |
235 | public function setParams(array $params)
236 | {
237 | foreach ($params as $key => $value) {
238 | $this->setParam($key, $value);
239 | }
240 | return $this;
241 | }
242 |
243 | public function setParam($key, $value)
244 | {
245 | $this->params[$key] = $value;
246 | return $this;
247 | }
248 |
249 | public function getMethod()
250 | {
251 | return $this->request->getMethod();
252 | }
253 |
254 | public function isPost()
255 | {
256 | return ($this->request->getMethod() == 'POST');
257 | }
258 |
259 | public function isGet()
260 | {
261 | return ($this->request->getMethod() == 'GET');
262 | }
263 |
264 | public function isPut()
265 | {
266 | return ($this->request->getMethod() == 'PUT');
267 | }
268 |
269 | public function isDelete()
270 | {
271 | return ($this->request->getMethod() == 'DELETE');
272 | }
273 |
274 | public function isOptions()
275 | {
276 | return ($this->request->getMethod() == 'OPTIONS');
277 | }
278 |
279 | public function isHead()
280 | {
281 | return ($this->request->getMethod() == 'HEAD');
282 | }
283 |
284 | public function isXmlHttpRequest()
285 | {
286 | return $this->request->isXmlHttpRequest();
287 | }
288 |
289 | public function isFlashRequest()
290 | {
291 | $header = strtolower($this->request->headers->get('USER_AGENT'));
292 | return (strstr($header, ' flash')) ? true : false;
293 | }
294 |
295 | public function isSecure()
296 | {
297 | return $this->request->isSecure();
298 | }
299 |
300 | public function getHeader($name)
301 | {
302 | return $this->request->headers->get($name);
303 | }
304 |
305 | public function getScheme()
306 | {
307 | return $this->request->getScheme();
308 | }
309 |
310 | public function getHttpHost()
311 | {
312 | return $this->request->getHttpHost();
313 | }
314 |
315 | public function getClientIp($proxy)
316 | {
317 | return $this->request->getClientIp($proxy);
318 | }
319 |
320 | public function getModuleName()
321 | {
322 | $this->parseRequest();
323 | return $this->moduleName;
324 | }
325 |
326 | public function getControllerName()
327 | {
328 | $this->parseRequest();
329 | return $this->controllerName;
330 | }
331 |
332 | public function getActionName()
333 | {
334 | $this->parseRequest();
335 | return $this->actionName;
336 | }
337 |
338 | public function getUserParams()
339 | {
340 | return $this->params;
341 | }
342 |
343 | public function getUserParam($key, $default = null)
344 | {
345 | if (isset($this->params[$key])) {
346 | return $this->params[$key];
347 | }
348 | return $default;
349 | }
350 |
351 | public function clearParams()
352 | {
353 | $this->params = array();
354 | return $this;
355 | }
356 | }
357 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | # Symfony2 Zend MVC 1.x Compatibility Bundle
2 |
3 | Simplifies moving your Zend 1.x MVC apps to Symfony 2 if you follow the way I interpreted the Zend project guidelines closely enough :-)
4 |
5 | ## Overview
6 |
7 | ### What it can do:
8 |
9 | * Has a base controller that mimics Zend_Controller_Action functionality
10 | * Uses Zend_View as template engine and just replaces certain view helpers with the Symfony2 functionality.
11 | * Ports most of the common action helpers or implements proxies that implement Symfony2 functionality.
12 | * Adds a catch-all route mechanism for selected bundles.
13 | * Import ZF Routing format files
14 |
15 | ### What it cannot do yet (Waiting for your pull requests)
16 |
17 | * Support for custom Zend_View helpers (high priority)
18 | * Expose Symfony View Globals such as the User through Zend_View
19 | * Re-implement the Controller Plugin cycle (currently: use Symfony internals to port your plugins)
20 | * All the inflection madness with dashes, lowercase, uppercase whatnot routing to controller/action naming. Currently only simple inflection is used.
21 | * Context handling: The ContextSwitch and AjaxContext helpers are not ported yet.
22 | * Have a console task to import a module from a ZF Project and do some work of the steps Installation automatically.
23 |
24 | ### What it will never do
25 |
26 | * Make Zend Application code reusable (Use the dependency injection container)
27 | * Handle calls to Zend_Controller_FrontController, you have to get rid of them.
28 | * Make the ActionStack Helper work. This concept is flawed and should be replaced with calls to $this->action() in the view, which replaces it with Symfony internal functionality that is dispatching actions very fast.
29 |
30 | ### Example
31 |
32 | In the ZFMvcCompatBundle\Resources\examples folder is an example bundle that implements the Guestbook tutorial as
33 | a Symfony bundle using the compat layer. You can use it by adding "Application\ApplicationBundle()" as bundle to the Kernel,
34 | configure the autoloader to use "Application" as namespace and "Application_" as directory. You can configure
35 | the compat bundle with:
36 |
37 | whitewashing_zf_mvc_compat:
38 | default_layout_resource: "ApplicationBundle::layout.html.phtml"
39 | db_conn:
40 | adapter: pdo_mysql
41 | params:
42 | host: localhost
43 | username: root
44 | password:
45 | dbname: zfmvccompat
46 |
47 | The database schema is:
48 |
49 | CREATE TABLE `guestbook` (
50 | `id` int(11) NOT NULL AUTO_INCREMENT,
51 | `email` varchar(32) NOT NULL DEFAULT 'noemail@test.com',
52 | `comment` text,
53 | `created` datetime NOT NULL,
54 | PRIMARY KEY (`id`)
55 | ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
56 |
57 | ## Installation
58 |
59 | 1. Add the bundle to your AppKernel::registerBundles() method:
60 |
61 | return array(
62 | //..
63 | new Whitewashing\ZFMvcCompatBundle\WhitewashingZFMvcCompatBundle(),
64 | );
65 |
66 | 2. Add the Whitewashing namespace to your autolod.php.
67 |
68 | 3. Register Zend_View as template engine in your config.yml:
69 |
70 | framework:
71 | templating: { engines: ["twig", "phtml"] }
72 |
73 | 4. Enable the Compat Bundle in config.yml:
74 |
75 | whitewashing_zf_mvc_compat:
76 | default_layout_resource: "MyBundle::layout.html.phtml"
77 |
78 | ## Usage
79 |
80 | It should be obvious that you won't be able to port your Zend Framework app to Symfony2 just by installing this bundle, manual labour will be necessary.
81 | Each Zend Framework module will need to be ported to a Symfony2 Bundle.
82 |
83 | 1. Create a bundle for your module. The Bundle Name should be "ModuleName" + "Bundle". So in the case of a "blog" module you need to call your Bundle class "BlogBundle".
84 | This can easily create clashes if you want to use a blog bundle built for Symfony in the future, but using this semantics you don't need to fix all your "_redirect", "_forward"
85 | and redirector helper calls. If you do want to use a another bundle name then make sure that whenever you specify $module in the Zend API you need that to be $module . "Bundle".
86 |
87 | 2. Move all controllers into the $BundleRoot."/Controller/" directory and namespace the classes according to PSR-0. src/Appliction/BlogBundle/Controller/PostController.php
88 | should become:
89 |
90 | namespace Application\BlogBundle\Controller;
91 | use Whitewashing\ZFMvcCompatBundle\Controller\ZendController;
92 |
93 | class PostController extends ZendController
94 | {
95 | }
96 |
97 | IMPORTANT: Since your Controllers are now inside a namespace you have to either "use" import all classes or prefix them with \.
98 |
99 | 3. Move all your views into $BundleRoot."/Resources/views" and rename the "default" context html views into "viewName.html.phtml" instead of "viewName.phtml"
100 |
101 | 4. Move your layout into $BundleRoot."/Resources/views/layout.html.phtml"
102 |
103 | Replace the call `$this->layout()->content` with `$this->content`
104 |
105 | Different layout blocks are NOT supported. Use `$this->action()` for that.
106 |
107 | 5. View Layer: Replace the scriptname in calls to $this->partial() and $this->partialLoop() with the symfony resources, for example:
108 |
109 | partial("HelloBundle:Test:partial.html.phtml", array("name" => "Someone else!")); ?>
110 |
111 | 6. Routing
112 |
113 | There is simple support for static and router routes in the compatibility layer through
114 | ``Whitewashing\ZFMvcCompatBundle\Router\Loader\ZFRouterLoader``. If you just use them you can
115 | use xml, ini or php Zend_Config inputs by defining for example the Guestbook example:
116 |
117 | guestbookzf:
118 | type: zfmvc
119 | resource: "@WhitewashingZFMvcCompatBundle/Resources/examples/Application/Resources/config/routing.ini"
120 |
121 | You should however convert all your Zend routes to Symfony routes, place them in a $BundleRoot."/Resources/routing.yml" and import
122 | them in your app/config/routing.yml. Additionally Symfony has no "catch-all" routes by default, so you have to make use
123 | of the catch all mechanism defined by the compat bundle:
124 |
125 | whitewashing_zf_mvc_compat:
126 | catchall_bundles: ["BlogBundle"]
127 |
128 | When this mechanism is enabled you can request:
129 |
130 | http://appuri/{module}/{controller}/{action}
131 |
132 | 7. Security and ACLs
133 |
134 | You probably implemented some kind of authentication, security and acl mechanism using controller plugins, Zend_Acl and
135 | Zend_Auth. You have to use Zend_Acl inside a kernel event, preferably after routing took place to reimplement that logic.
136 |
137 | ## Semantic differences
138 |
139 | ### FrontController
140 |
141 | Every code statically referencing the FrontController WILL fail. There is
142 | no such thing as a static/singleton front controller. Get the resources you
143 | need through the DIC.
144 |
145 | ### Request
146 |
147 | * Zend_Controller_Request_Http::__get does check for $_ENV and the PATH_INFO or REQUEST_URI keys.
148 | * Zend_Controller_Request_Http Aliases for params are not supported
149 | * Zend_Controller_Request_Http setters are not implemented
150 |
151 | ### Response
152 |
153 | * setHeader(), getHeader(), clearHeader() dont normalize the header key.
154 | * setRawHeader(), getRawHeader(), getRawHeaders() are not implemented
155 | * canSendHeaders(), sendHeaders() not implemented
156 | * Named body segments are not implemented. Symfony2 uses multiple response instances for that.
157 | All methods referencing a code will only reference the default segment or throw an exception
158 | (append(), prepend(), insert()).
159 | * All exception related code is not implemented.
160 |
161 | ### Zend_Controller_Action
162 |
163 | * IMPORTANT: Make sure $this->_redirect and $this->_forward are always called with a leading "return" statement.
164 | * $this->view only calls to a ParameterBag that temporarily holds all view parameters. Calling view helpers inside the controller won't work!
165 |
166 | ### Zend_Controller_Action_HelperBroker
167 |
168 | The HelperBroker in this compatibility layer only implements the necessary ZF functionality.
169 | You cannot extend it with your own helpers. Use the Dependency Injenction container in the Controller and request services to use:
170 |
171 | class MyController extends ZendController
172 | {
173 | public function indexAction()
174 | {
175 | $this->get('my.action.helper')->doAction();
176 | }
177 | }
178 |
179 | If someone cares please implement the helper broker as extensionable object, its
180 | in `Whitewashing\Zend\Mvc1CompatBundle\Controller\Helpers\HelperBroker`. It should
181 | use DIC tags to register helpers through an interface that has a getName() method
182 | and the regular action helper stuff.
183 |
184 | ### List of ported Action Helpers
185 |
186 | * Url
187 | * Redirector
188 | * ViewRenderer
189 | * Layout
190 | * FlashMessenger
191 |
192 | #### Url Action Helper
193 |
194 | * $this->getHelper('url')->url($urlOptions, $name) will not allow to include 'controller', 'module' or 'action' parameters in $urlOptions as the original Zend router allows.
195 | * $this->_helper->url($action, $ctrl, $module, $params) is an expensive method, iterating over the collection of all routes.
196 | * The third parameter of the UrlHelper#url method is now $absolute = true/false, the original third and fourth parameter $reset/$encode have been dropped.
197 |
198 | #### Zend Layout
199 |
200 | Parts of the API of `Zend_Layout` and the respective action helper has been ported, though it changed semantically.
201 |
202 | In your config.yml when defining the `zendmvc1.compat:` section you have to specify a "default_layout_resource" parameter,
203 | that takes of the form "BundleName::layoutFile.phtml" and resides in Bundle/Resources/views/layoutFile.phtml respectively.
204 | The following very common API calls work:
205 |
206 | $this->_helper->layout()->disableLayout();
207 | $this->_helper->layout()->enableLayout();
208 | $this->_helper->layout()->setLayout("HelloBundle::layout.phtml", $enable)
209 |
210 | As you can see, `setLayout` also expects a bundle resource, not a path anymore. You have to change all occurances
211 | throughout your code, but I doubt that will be many.
212 |
213 | #### View Renderer
214 |
215 | Only the functions setNoRender() and setNeverRender() have been ported.
--------------------------------------------------------------------------------