TYPO3: Extension to run PHP code - php

This is more like a basic question:
How do I get an extension (by Extension Builder) to run a simple PHP code without adding a domain model and actions?

In general, there are 3 options:
Create a content element which is answered here: With fluid_styled_content, how to create custom content elements in TYPO3 7.5 and 7 LTS?
Create a plugin which is from the "old" kind, former called "pi_base".
Create a plugin based on extbase.
I would still go with option number 3 and therefore you still will need an action. Having actions is good because of you add a 2nd variant, you can just use a 2nd action and there is not much additional code you need.
Having such an extension is fairly easy. One example I did lately was this extension: https://github.com/sup7even/mailchimp
In general you need:
ext_localconf.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Sup7even.' . $_EXTKEY,
'Registration',
array(
'Form' => 'index,response,ajaxResponse'
),
array(
'Form' => 'index,response,ajaxResponse'
)
);
ext_tables.php
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
'Sup7.' . $_EXTKEY,
'Registration',
'Mailchimp'
);
And the RegistrationController. By default, the first action will be called which is in this case index, therefore you need an indexAction and the Template must be Templates/Registration/Index.html.

Related

Creating a FrontEnd Plugin in Typo3 7.6

I know there are multiple Threads with a similar Question but I hope that someone can give me an individual solution.
So I am working on an Existing Typo3 7.6.23 Project with already multiple plugins running, I tried to copy every instance that I could find to replicate a plugin and customize it for my use. That didn't work. I couldn't see the Plugin in the Dropdown List.
Then I tried to follow the steps from this link.
(1) registerPlugin
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
$_EXTKEY,
'DocumentService',
'DokumentenService'
);
(2) configurePlugin
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'TYPO3.' . $_EXTKEY, 'DocumentService', array(
'Example' => 'showDocumentService',
),
// non-cacheable actions
array(
'Example' => '',
)
);
I should be able to select the Plugin in the Backend Dropdown List. But it just does not appear in my Plugins List in the Content Element where I need it.
I even created a Template in the Right Folder and created an Action for it in the Controller..
I'm stuck here and would love to hear a solution as soon as possible.
You are writing about about a service.... Ist the extension just a typo3 Service, you won't be able to select it as extension in the backend...
Have a look at "ext_localconf..."
Is there a \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addService(...
Then the extension could be just a service.
Here is a working sample from Aimeos Webshop. Please note you have to change the name of the plugin, you should not use TYPO3. or Aimeos. for the plugin name instead choose your own name.
configurePlugin example from https://github.com/aimeos/aimeos-typo3/blob/2018.04/ext_localconf.php#L27, this configures your plugin for the frontend:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Aimeos.' . $_EXTKEY,
'locale-select',
array( 'Locale' => 'select' ),
array( 'Locale' => 'select' )
);
registerPlugin example https://github.com/aimeos/aimeos-typo3/blob/2018.04/ext_tables.php#L60, this shows your plugin in the backend:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
'Aimeos.' . $_EXTKEY,
'locale-select',
'Aimeos Shop - Locale selector'
);
And here is the entry point of the action https://github.com/aimeos/aimeos-typo3/blob/2018.04/Classes/Controller/LocaleController.php#L27
The Extension Builder can help you to setup a new TYPO3 extension and is available for TYPO3 v7.6 too see https://extensions.typo3.org/extension/extension_builder/.
And finally here is the documentation on writing extensions for TYPO3 v7.6 https://docs.typo3.org/m/typo3/reference-coreapi/7.6/en-us/ExtensionArchitecture/Index.html.

ZF2 'unable to render template' when shifting module names in the array in app config

Good day.
I've just started learning ZF2, replicated the Album example step-by-step, and then decided to make it a bit more interesting by adding user registration, and then make the two work together in some way, so i added a new 'Auth' module.
So, when i only had one module in the module list (aside from the Application module) in application.config.php, it was all fine, but when i added the Auth module to the list like so:
'modules' => array('Application', 'Album','Auth',)
i got the following error when trying to access any views from the album module which was working absolutely fine prior to this change:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "album/album/index"; resolver could not resolve to a file
But when i changed the order in which the modules are presented in this array like so:
'modules' => array('Application', 'Auth','Album',)
not a single view (and it has only one) from the Auth module could be rendered, while the Album module was fine.
Zend\View\Renderer\PhpRenderer::render: Unable to render template "auth/user/index"; resolver could not resolve to a file
Both of these views exist at these locations, but the renderer doesn't see them for some reason.
You can see the project's contents here.
Thank you for any tips in advance.
Looks like you copy pasted the the view manager config for Auth module.config.php.
This should be auth rather than album for your templates to work correctly.
'view_manager' => array(
'template_path_stack' => array(
'auth' => __DIR__ . '/../view',
),
),

Zend Framework 2 - Translation and text domain in views

I'm currently working on translating an existing Zend Framework 2 project that is spread around multiple modules.
My understanding of the translate functionality of ZF2, is that you can have as many translation files, providing each are 'namespaced' to a different text_domain. This works fine in practice, with each module having the following in their module.config.php file:
...
'translator' => array (
'locale' => 'en_US',
'translation_file_patterns' => array (
array (
'type' => 'phparray',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s_default.php',
'text_domain' => 'ExampleModule'
),
),
),
...
Which adds a ../language/*_default.php file to the translation list with a text_domain of ExampleModule. All good so far.
Now, the translator itself needs to know which text_domain to pick a translation from and will use default if one isn't provided.
So, inside and at the top of all of my view *.phtml files, I have:
$this->plugin('translate')->setTranslatorTextDomain('ExampleModule');
$this->formLabel()->setTranslatorTextDomain('ExampleModule');
$this->formText()->setTranslatorTextDomain('ExampleModule');
Which tells all proceeding $this->translate() blocks and form elements which text_domain to use.
This is great, and works fine, but it doesn't sit well with the DRY principle in that I have similar code at the top of every view. I attempted to extend the ViewModel class so I can pick a different ViewModel class in the controller and have the above code already baked in, but the plugins aren't available at that stage.
How would I include the above code on every/most views without having to type it each time?
After searching endlessly, I found that the default renderer - PhpRenderer - can be accessed via the onBootstrap method of Module.php (reference).
As the view scripts are rendered by PhpRenderer the $this variable points to PhpRenderer (reference). This means that you can attach the code I needed to Module.php as below:
// Get the default ViewRenderer (PhpRenderer) and setup the correct text domain for derivative plugins
$viewRenderer = $e->getApplication()->getServiceManager()->get('ViewRenderer');
$viewRenderer->plugin('translate')->setTranslatorTextDomain('ExampleModule');
$viewRenderer->formLabel()->setTranslatorTextDomain('ExampleModule');
$viewRenderer->formText()->setTranslatorTextDomain('ExampleModule');
As the current namespace matches the text_domain I need, the above can be simplified by swapping 'ExampleModule' with __NAMESPACE__.
EDIT: If you're looking for a different text_domain per module; you'll need in just one Module.php:
$viewRenderer = $e->getApplication()->getServiceManager()->get('ViewRenderer');
$eventManager->getSharedManager()->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) use ($viewRenderer) {
$controller = $e->getTarget();
$controllerClass = get_class($controller);
$moduleNamespace = substr($controllerClass, 0, strpos($controllerClass, '\\'));
$viewRenderer->plugin('translate')->setTranslatorTextDomain($moduleNamespace);
$viewRenderer->formLabel()->setTranslatorTextDomain($moduleNamespace);
$viewRenderer->formText()->setTranslatorTextDomain($moduleNamespace);
}, 100);

Can the process of creating an module in zf2 be shortend?

I am looking at a few tutorials and to just create 1 module you have to modify a bunch of configuration files in order to make the controllers, models, and views work. I see this as impossible to try and remember it all or comprehend what it is I’m doing. Is there an alternative method that creates these for me? so that i don’t have to write it all out every time i create a controller, or a module etc. I honestly don’t see how this is faster. I come from a codeigniter background so making this switch has me banging my head against the wall multiple times trying to comprehend.
I've been using ZF2 for a few months now, and I've found that writing a class to generate that config for you is helpful.
There is no tool out there to do that for you. But if you follow the following approach, you should come right quite quickly:
class Configurator {
public static function route($name, $url, $controller, $action='index') {
return array(
'router' => array(
...
),
);
}
# Other static configuring methods
...
}
Then in your config you use the Configurator like this:
use Configurator;
return array_merge_recursive(
array(
'view_manager' => array(
...
),
),
# Other top-level config
...
Configurator::route('home', '/', 'Application\Controller\Index'),
Configurator::route('other', '/other', 'Application\Controller\Other')
);
Your config is deep-merged by array_merge_recursive, utimately producing the config you want with your own custom-built generators. You're at liberty to configure whole sets of config with one method, so you can create a resource configurator which sets up the controller invokables, the routes, and anything else required in one method.
array_merge_recursive FTW!
Enjoy! :)

Zend Translate custom language

Depending on the user role, I need to show different texts in my Zend project.
For normal users I'm using the "en" language.
For new users I want something like "en_new".
However, the language "en_new" always reverts to just "en".
I'm using the locale_directory scan system to automatically detect languages.
The translate adapter calls Zend_Locale::findLocale() internally in addTranslation() (at least in ZF 1.1x). This in turn checks whether the locale is on a whitelist. Yours is not, obviously. I didn't dig too deep into the code, but it's quite probable that the next step is to revert from en_xxx to just en which is what happens in your case.
See the sources:
library/Zend/Translate/Adapter.php - addTranslation method
library/Zend/Locale.php - findLocale method
I am currently evaluating something similar, for some users I want some texts to be differently translated. And I also ran into the problem to not be able to create a custom locale value.
Tough what I found out in my tests seems to solve/work around the problem.
See also here: Combining multiple translation sources
What I am doing is to just add a custom translation to my default ones.
$translateDef = new Zend_Translate(
array(
'adapter' => 'gettext',
'content' => 'locale/default/',
'locale' => 'auto',
'scan' => Zend_Translate::LOCALE_DIRECTORY
)
);
$translateCust = new Zend_Translate(
array(
'adapter' => 'gettext',
'content' => 'locale/custom/',
'locale' => 'auto',
'scan' => Zend_Translate::LOCALE_DIRECTORY
)
);
$translateDef->addTranslation(array(
'content' => $translateCust
)
);
And the folder structure looks like this:
locale/
default/
de
en
custom/
de
en
So when doing the addTranslation it seems to overvwrites the existing ones, so for your new users, you could add custom folder with the proper translations.
For my tests this worked so far, but haven't evaluated it in depth yet.

Categories