I try to add a new controller which has one action called confirmAgbAction.
<?php
namespace Eddcapone\MyExtension\Controller;
/**
* CustomController
*/
class CustomController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* action list
*
* #return void
*/
public function confirmAgbAction()
{
echo "<p>HALLO WELT</p>";
}
}
I even added it to ext_localconf.php
<?php
if (!defined('TYPO3_MODE')) {
die('Access denied.');
}
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Eddcapone.' . $_EXTKEY,
'Myfilelist',
array(
'Category' => 'list,show',
'File' => 'show',
'Download' => 'download',
'Custom' => 'confirmAgb'
),
// non-cacheable actions
array(
'Category' => 'list,show',
'File' => 'topFive',
'Download' => 'download',
'Custom' => 'confirmAgb'
)
);
This is how I call the action in the template:
<f:link.action controller="Custom" action="confirmAgb" pluginName="Myfilelist" class="mbButton">Download</f:link.action>
However, i always get:
#1313855173: The controller "Custom" is not allowed by this plugin. Please check for TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in your ext_localconf.php.
There are two common possibilities for your error:
You use a flexform to embed your plugin. Either you have not added Custom->confirmAgb to the allowed calls in your flexform or you have added it but did not update the plugin (plugin configuration only updates when you save the plugin/tt_content element)
You have two plugins on the page and the error is triggered by the other plugin because there the controller->action combination is not allowed.
PS: try adding this to your TS (setup.txt) and the plugins now should pick the default action if the given one is not found:
plugin.tx_yourextensionmvc.callDefaultActionIfActionCantBeResolved = 1
There could be more uncommon cases
You should absolutely avoid using $_EXTKEY in configurePlugin and other Extbase contexts. Extbase requires the Vendor.ExtensionName format - $_EXTKEY is in the lowercase_underscored format. Defining those parameters as hardcoded values should solve your problem with resolving controllers for your given plugin.
To be precise: use Eddcapone.Myextension as extension name parameter in your command(s) to register/configure plugins.
Related
I built an extension and I would like to add plugin options at the time of adding the plugin to the page
Extension Name : hotels
in Hotel model ,
<?php
class Hotel{
... get set methods ...
}
?>
in HotelController.php
<?php
namespace TYPO3\Hotels\Controller;
class HotelController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController{
public function listAction(){
// $this->view->assign('result', array('test' => 'hello, u r in list')); }
}
?>
in ext_localconf.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'TYPO3.' . $_EXTKEY,
'hotels',
array('Hotel' => 'list,single,display,update,save,preview,edit')
);
in ext_tables.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'hotels',
'list of Hotels'
);
$pluginSignature = str_replace('_','',$_EXTKEY) . '_hotels';
$TCA['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] ='pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue($pluginSignature, 'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/flexform_myhotel.xml');
Somehow, I think i'm missing something. This gives an error :
I can see the option in backend side at time of adding extension but when i want to show (view) that Page where I add that extension , generates an error .
----> The default controller for extension "Hotels" and plugin "hotels" can not be determined. Please check for TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in your ext_localconf.php.
Please Guide me
In TYPO3 6.x, you are advised to use namespaced classes and tell the configurePlugin method your vendor name.
As you didnt include any of your controller code, I'll try to sketch it:
At first, make sure, you use a namespaced controller class-remember to set a Vendor name.
Make sure, your actions are named with the *Action suffix
EXT: myext/Classes/Controller/HotelController
namespace MyVendor\MyExt\Controller;
class HotelController {
/**
* #return void
*/
public function listAction(){
}
}
Next, mention the namespace in configurePlugin like this:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'MyVendor.' . $_EXTKEY,
// UpperCamelCase please, refer to [1]
'Hotels',
array('Hotel' => 'list,single,display,update,save,preview,edit')
);
This allows the class locator to resolve the classes correctly.
To verify it, make sure you re-install your extension.
PS: Please use the namespaced classes whenever possible in 6.x. The old Tx_* classes are only aliases and put additional load on your interpreter.
1 - TYPO3 API Docs for ExtensionUtility::configurePlugin()
Update:
There is a multitude of possible errors.
You wired a FlexForm. Did you set the switchableControllerActions appropriately?
One thing I saw more than once: The f:link.action (or f:uri.action respectively) doesnt like to be without an appropriate controller attribute
You clearly missed the namespace concept :) Rename your ControllerClass to HotelController and the file must live in Classes/Controller/HotelController.php, then do the adjustments to configurePlugin() to reflect the vendorName as I described
Try it.
in ext_localconf.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'TYPO3.' . $_EXTKEY,
'hotels',
array(
'Hotel' => 'list,single,display,update,save,preview,edit'
),
// non-cacheable actions
array(
'Hotel' => 'list',
)
);
in ext_tables.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'hotels',
'list of Hotels'
);
$extensionName = \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($_EXTKEY);
$pluginSignature = strtolower($extensionName). '_hotels';
if (TYPO3_MODE === 'BE') {
/**
* Registers a Backend Module
*/
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
'TYPO3.' . $_EXTKEY,
'web', // Make module a submodule of 'web'
'hotels', // Submodule key
'', // Position
array(
'Hotel' => 'list,single,display,update,save,preview,edit'
),
array(
'access' => 'user,group',
'icon' => 'EXT:' . $_EXTKEY . '/ext_icon.gif',
'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_hotels.xlf',
)
);
}
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'Hotels List');
#Clear cache and remove typo3temp data
I created new resources with this code:
class WebserviceRequest extends WebserviceRequestCore {
public static function getResources(){
$resources = parent::getResources();
// if you do not have class for your table
$resources['test'] = array('description' => 'Manage My API', 'specific_management' => true);
$resources['categoryecommerce'] = array('description' => 'o jacie marcin', 'class' => 'CategoryEcommerce');
$mp_resource = Hook::exec('addMobikulResources', array('resources' => $resources), null, true, false);
if (is_array($mp_resource) && count($mp_resource)) {
foreach ($mp_resource as $new_resources) {
if (is_array($new_resources) && count($new_resources)) {
$resources = array_merge($resources, $new_resources);
}
}
}
ksort($resources);
return $resources;
}
}
And new class:
class CategoryEcommerceCore extends ObjectModelCore {
public $category_id;
public $category_core_id;
public static $definition = array(
'table' => "category_ecommerce",
'primary' => 'category_id',
'fields' => array(
'category_core_id' => array('type' => self::TYPE_INT),
)
);
protected $webserviceParameters = array();
}
Webservice is override properly. My class WebserviceRequest is copying to
/override/classes/webservice/WebserviceRequest
but class isn't copying to /override/classes/ when i installing my module.
How to add new resourcess with own logic ? I want to add categories within relation to my table.
Regards
Martin
As soon as there is literally nothing regarding the API except Webkul tutorial... I tried to implement the "Webkul's" tutorial, but also failed. However seems that it's better to use hooks instead of overrides. I used my "reverse engineering skills" to determine the way to create that API, so-o-o-o, BEHOLD! :D
Let's assume you have a custom PrestaShop 1.7 module. Your file is mymodule.php and here are several steps.
This is an install method wich allows you to register the hook within database (you can uninstall and reinstall the module for this method to be executed):
public function install() {
parent::install();
$this->registerHook('addWebserviceResources');
return true;
}
Add the hook listener:
public function hookAddWebserviceResources($resources) {
$added_resources['test'] = [
'description' => 'Test',
'specific_management' => true,
];
return $added_resources;
}
That specific_management option shows you are going to use WebsiteSpecificManagement file instead of database model file.
Create WebsiteSpecificManagement file, called WebsiteSpecificManagementTest (Test - is CamelCased name of your endpoint). You can take the skeleton for this file from /classes/webservice/WebserviceSpecificManagementSearch.php. Remove everything except:
setObjectOutput
setWsObject
getWsObject
getObjectOutput
setUrlSegment
getUrlSegment
getContent (should return $this->output; and nothing more)
manage - you should rewrite it to return/process the data you want.
Add
include_once(_PS_MODULE_DIR_.'YOURMODULENAME/classes/WebserviceSpecificManagementTest.php');
to your module file (haven't figured out how to include automatically).
Go to /Backoffice/index.php?controller=AdminWebservice and setup the new "Auth" key for your application, selecting the test endpoint from the permissions list. Remember the key.
Visit /api/test?ws_key=YOUR_KEY_GENERATED_ON_STEP_4 and see the XML response.
Add &output_format=JSON to your URL to see the response in JSON.
You have to use something like $this->output = json_encode(['blah' => 'world']) within manage method at WebsiteSpecificManagementTest.
I am trying to add some Hooks to my OwnCloud app called Metadata, and i can't seem to figure it out (the hook is not being fired).
I tried following the content https://doc.owncloud.org/server/8.2/developer_manual/app/init.html and https://doc.owncloud.org/server/8.2/developer_manual/app/hooks.html (although it seems like the second one is outdated).
Basically all i am trying to do for now is the catch the pre-rename hook and write something to a file.
My code is :
myapp/appinfo/app.php
namespace OCA\Metadata\AppInfo;
use OCP\AppFramework\App;
$app = new App('metadata');
$container = $app->getContainer();
$container->query('OCP\INavigationManager')->add(function () use ($container) {
$urlGenerator = $container->query('OCP\IURLGenerator');
$l10n = $container->query('OCP\IL10N');
return [
// the string under which your app will be referenced in owncloud
'id' => 'metadata',
// sorting weight for the navigation. The higher the number, the higher
// will it be listed in the navigation
'order' => 10,
// the route that will be shown on startup
'href' => $urlGenerator->linkToRoute('metadata.page.index'),
// the icon that will be shown in the navigation
// this file needs to exist in img/
'icon' => $urlGenerator->imagePath('metadata', 'app.svg'),
// the title of your application. This will be used in the
// navigation or on the settings page of your app
'name' => $l10n->t('Metadata'),
];
});
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OC\Metadata\Hooks', 'postRename');
and then myapp/hooks.php
<?php
namespace OCA\Metadata;
use OC\Files\Filesystem;
use OC\Files\View;
class Hooks {
// private $userManager;
public static function postRename($params) {
file_put_contents("/var/www/data/owncloud_print2.log", "post_rename");
}
}
nothing ever gets written to the file. i have also tried other approaches all with no luck. anyone knows what i am doing wrong??
my connecthook was wrong. it should be:
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Metadata\Hooks', 'postRename');
I built an extension and I would like to add plugin options at the time of adding the plugin to the page
Extension Name : hotels
in Hotel model ,
<?php
class Hotel{
... get set methods ...
}
?>
in HotelController.php
<?php
namespace TYPO3\Hotels\Controller;
class HotelController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController{
public function listAction(){
// $this->view->assign('result', array('test' => 'hello, u r in list')); }
}
?>
in ext_localconf.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'TYPO3.' . $_EXTKEY,
'hotels',
array('Hotel' => 'list,single,display,update,save,preview,edit')
);
in ext_tables.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'hotels',
'list of Hotels'
);
$pluginSignature = str_replace('_','',$_EXTKEY) . '_hotels';
$TCA['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] ='pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue($pluginSignature, 'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/flexform_myhotel.xml');
Somehow, I think i'm missing something. This gives an error :
I can see the option in backend side at time of adding extension but when i want to show (view) that Page where I add that extension , generates an error .
----> The default controller for extension "Hotels" and plugin "hotels" can not be determined. Please check for TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in your ext_localconf.php.
Please Guide me
In TYPO3 6.x, you are advised to use namespaced classes and tell the configurePlugin method your vendor name.
As you didnt include any of your controller code, I'll try to sketch it:
At first, make sure, you use a namespaced controller class-remember to set a Vendor name.
Make sure, your actions are named with the *Action suffix
EXT: myext/Classes/Controller/HotelController
namespace MyVendor\MyExt\Controller;
class HotelController {
/**
* #return void
*/
public function listAction(){
}
}
Next, mention the namespace in configurePlugin like this:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'MyVendor.' . $_EXTKEY,
// UpperCamelCase please, refer to [1]
'Hotels',
array('Hotel' => 'list,single,display,update,save,preview,edit')
);
This allows the class locator to resolve the classes correctly.
To verify it, make sure you re-install your extension.
PS: Please use the namespaced classes whenever possible in 6.x. The old Tx_* classes are only aliases and put additional load on your interpreter.
1 - TYPO3 API Docs for ExtensionUtility::configurePlugin()
Update:
There is a multitude of possible errors.
You wired a FlexForm. Did you set the switchableControllerActions appropriately?
One thing I saw more than once: The f:link.action (or f:uri.action respectively) doesnt like to be without an appropriate controller attribute
You clearly missed the namespace concept :) Rename your ControllerClass to HotelController and the file must live in Classes/Controller/HotelController.php, then do the adjustments to configurePlugin() to reflect the vendorName as I described
Try it.
in ext_localconf.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'TYPO3.' . $_EXTKEY,
'hotels',
array(
'Hotel' => 'list,single,display,update,save,preview,edit'
),
// non-cacheable actions
array(
'Hotel' => 'list',
)
);
in ext_tables.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'hotels',
'list of Hotels'
);
$extensionName = \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($_EXTKEY);
$pluginSignature = strtolower($extensionName). '_hotels';
if (TYPO3_MODE === 'BE') {
/**
* Registers a Backend Module
*/
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
'TYPO3.' . $_EXTKEY,
'web', // Make module a submodule of 'web'
'hotels', // Submodule key
'', // Position
array(
'Hotel' => 'list,single,display,update,save,preview,edit'
),
array(
'access' => 'user,group',
'icon' => 'EXT:' . $_EXTKEY . '/ext_icon.gif',
'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_hotels.xlf',
)
);
}
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'Hotels List');
#Clear cache and remove typo3temp data
In my controller I create the Navigation object and passing it to the view
$navigation = new \Zend\Navigation\Navigation(array(
array(
'label' => 'Album',
'controller' => 'album',
'action' => 'index',
'route' => 'album',
),
));
There trying to use it
<?php echo $this->navigation($this->navigation)->menu() ?>
And get the error:
Fatal error: Zend\Navigation\Exception\DomainException: Zend\Navigation\Page\Mvc::getHref cannot execute as no Zend\Mvc\Router\RouteStackInterface instance is composed in Zend\View\Helper\Navigation\AbstractHelper.php on line 471
But navigation which I use in layout, so as it is written here: http://adam.lundrigan.ca/2012/07/quick-and-dirty-zf2-zend-navigation/ works. What is my mistake?
Thank you.
The problem is a missing Router (or to be more precise, a Zend\Mvc\Router\RouteStackInterface). A route stack is a collection of routes and can use a route name to turn that into an url. Basically it accepts a route name and creates an url for you:
$url = $routeStack->assemble('my/route');
This happens inside the MVC Pages of Zend\Navigation too. The page has a route parameter and when there is a router available, the page assembles it's own url (or in Zend\Navigation terms, an href). If you do not provide the router, it cannot assemble the route and thus throws an exception.
You must inject the router in every page of the navigation:
$navigation = new Navigation($config);
$router = $serviceLocator->get('router');
function injectRouter($navigation, $router) {
foreach ($navigation->getPages() as $page) {
if ($page instanceof MvcPage) {
$page->setRouter($router);
}
if ($page->hasPages()) {
injectRouter($page, $router);
}
}
}
As you see it is a recursive function, injecting the router into every page. Tedious! Therefore there is a factory to do this for you. There are four simple steps to make this happen.
STEP ONE
Put the navigation configuration in your module configuration first. Just as you have a default navigation, you can create a second one secondary.
'navigation' => array(
'secondary' => array(
'page-1' => array(
'label' => 'First page',
'route' => 'route-1'
),
'page-2' => array(
'label' => 'Second page',
'route' => 'route-2'
),
),
),
You have routes to your first page (route-1) and second page (route-2).
STEP TWO
A factory will convert this into a navigation object structure, you need to create a class for that first. Create a file SecondaryNavigationFactory.php in your MyModule/Navigation/Service directory.
namespace MyModule\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class SecondaryNavigationFactory extends DefaultNavigationFactory
{
protected function getName()
{
return 'secondary';
}
}
See I put the name secondary here, which is the same as your navigation key.
STEP THREE
You must register this factory to the service manager. Then the factory can do it's work and turn the configuration file into a Zend\Navigation object. You can do this in your module.config.php:
'service_manager' => array(
'factories' => array(
'secondary_navigation' => 'MyModule\Navigation\Service\SecondaryNavigationFactory'
),
)
See I made a service secondary_navigation here, where the factory will return a Zend\Navigation instance then. If you do now $sm->get('secondary_navigation') you will see that is a Zend\Navigation\Navigation object.
STEP FOUR
Tell the view helper to use this navigation and not the default one. The navigation view helper accepts a "navigation" parameter where you can state which navigation you want. In this case, the service manager has a service secondary_navigation and that is the one we need.
<?= $this->navigation('secondary_navigation')->menu() ?>
Now you will have the navigation secondary used in this view helper.
Disclosure: this answer is the same as I gave on this question: https://stackoverflow.com/a/12973806/434223
btw. you don't need to define controller and action if you define a route, only if your route is generic and controller/action are variable segments.
The problem is indeed that the routes can't be resolved without the router. I would expect the navigation class to solve that issue, but obviously you have to do it on your own. I just wrote a view helper to introduce the router with the MVC pages.
Here's how I use it within the view:
$navigation = $this->navigation();
$navigation->addPage(
array(
'route' => 'language',
'label' => 'language.list.nav'
)
);
$this->registerNavigationRouter($navigation);
echo $navigation->menu()->render();
The view helper:
<?php
namespace JarJar\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\View\Helper\Navigation;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Navigation\Page\Mvc;
class RegisterNavigationRouter extends AbstractHelper implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function __invoke(Navigation $navigation)
{
$router = $this->getRouter();
foreach ($navigation->getPages() as $page) {
if ($page instanceof Mvc) {
$page->setRouter($router);
}
}
}
protected function getRouter()
{
$router = $this->getServiceLocator()->getServiceLocator()->get('router');
return $router;
}
}
Don't forget to add the view helper in your config as invokable instance:
'view_helpers' => array(
'invokables' => array(
'registerNavigationRouter' => 'JarJar\View\Helper\RegisterNavigationRouter'
)
),
It's not a great solution, but it works.