How to extend date picker viewhelper of EXT:powermail? - typo3

I need to add a custom validator to the datepicker field. By default, this field comes without any validators.
I've already made the validator settings visible in the TCA of tx_powermail_domain_model_field and added my custom validator as usual.
Now I need the attributes data-parsley-customXXX and data-parsley-error-message added to the HTML input field which is usually done via the the viewhelper in ValidationDataAttributeViewHelper.php:
https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Validation/ValidationDataAttributeViewHelper.php#L342
https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Validation/ValidationDataAttributeViewHelper.php#L348
This is the code I need to extend:
https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Validation/DatepickerDataAttributeViewHelper.php#L32

I found a solution for my problem. As suggested in the comment it's possible to extend the Viewhelper:
ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\In2code\Powermail\ViewHelpers\Validation\DatepickerDataAttributeViewHelper::class] = [
'className' => \Vendor\MyExt\Powermail\ViewHelpers\Validation\DatepickerDataAttributeViewHelper::class
];
myext/Classes/Powermail/ViewHelpers/Validation/DatepickerDataAttributeViewHelper.php
<?php
declare(strict_types=1);
namespace Vendor\MyExt\Powermail\ViewHelpers\Validation;
use In2code\Powermail\Domain\Model\Field;
use In2code\Powermail\Utility\LocalizationUtility;
class DatepickerDataAttributeViewHelper extends \In2code\Powermail\ViewHelpers\Validation\DatepickerDataAttributeViewHelper
{
/**
* Returns Data Attribute Array Datepicker settings (FE + BE)
*
* #return array for data attributes
*/
public function render(): array
{
/** #var Field $field */
$field = $this->arguments['field'];
$additionalAttributes = $this->arguments['additionalAttributes'];
$value = $this->arguments['value'];
$additionalAttributes['data-datepicker-force'] =
$this->settings['misc']['datepicker']['forceJavaScriptDatePicker'];
$additionalAttributes['data-datepicker-settings'] = $this->getDatepickerSettings($field);
$additionalAttributes['data-datepicker-months'] = $this->getMonthNames();
$additionalAttributes['data-datepicker-days'] = $this->getDayNames();
$additionalAttributes['data-datepicker-format'] = $this->getFormat($field);
if ($value) {
$additionalAttributes['data-date-value'] = $value;
}
if ($field->getValidation() && $this->isClientValidationEnabled()) {
$value = 1;
if ($field->getValidationConfiguration()) {
$value = $field->getValidationConfiguration();
}
$additionalAttributes['data-parsley-custom' . $field->getValidation()] = $value;
$additionalAttributes['data-parsley-error-message'] =
LocalizationUtility::translate('validationerror_validation.' . $field->getValidation());
}
$this->addMandatoryAttributes($additionalAttributes, $field);
return $additionalAttributes;
}
}

Related

TYPO3: Extend ctype textmedia with subheader

I want to add the subheader to the ctype 'textmedia' (TYPO3 9.5 & 10.4).
I followed this stackoverflow answer:
TYPO3 8 show layout selection in backend preview for textmedia
to register my Hook
typo3conf/ext/my-extension/Classes/Hooks/PageLayoutView/TextMediaCustomPreviewRenderer.php
Then I added the subheader
<?php
namespace aaa\bbb\Hooks\PageLayoutView;
use \TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface;
use \TYPO3\CMS\Backend\View\PageLayoutView;
/**
* Contains a preview rendering for the page module of CType="textmedia"
*/
class TextMediaCustomPreviewRenderer implements PageLayoutViewDrawItemHookInterface
{
/**
* Preprocesses the preview rendering of a content element of type "textmedia"
*
* #param \TYPO3\CMS\Backend\View\PageLayoutView $parentObject Calling parent object
* #param bool $drawItem Whether to draw the item using the default functionality
* #param string $headerContent Header content
* #param string $subheaderContent Subheader content
* #param string $itemContent Item content
* #param array $row Record row of tt_content
*/
public function preProcess(
PageLayoutView &$parentObject,
&$drawItem,
&$headerContent,
&$subheaderContent,
&$itemContent,
array &$row
) {
if ($row['CType'] === 'textmedia') {
if ($row['bodytext']) {
$itemContent .= $parentObject->linkEditContent($parentObject->renderText($row['bodytext']), $row) . '<br />';
}
if ($row['assets']) {
$itemContent .= $parentObject->linkEditContent($parentObject->getThumbCodeUnlinked($row, 'tt_content', 'assets'), $row) . '<br />';
$fileReferences = BackendUtility::resolveFileReferences('tt_content', 'assets', $row);
if (!empty($fileReferences)) {
$linkedContent = '';
foreach ($fileReferences as $fileReference) {
$description = $fileReference->getDescription();
if ($description !== null && $description !== '') {
$linkedContent .= htmlspecialchars($description) . '<br />';
}
}
$itemContent .= $parentObject->linkEditContent($linkedContent, $row);
unset($linkedContent);
}
}
$drawItem = false;
}
}
}
I get the errror:
Fatal error: Declaration of aaaa\bbb\Hooks\PageLayoutView\TextMediaCustomPreviewRenderer::preProcess(TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$subheaderContent, &$itemContent, array &$row) must be compatible with TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface::preProcess(TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row) in /kunden/1111/rp-hosting/2222/333/typo3cms/projekt1/typo3conf/ext/my-sitepackage/Classes/Hooks/PageLayoutView/TextMediaCustomPreviewRenderer.php on line 23
What do I have to do to make it compatible with
TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface::preProcess(TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row)
You got it a bit wrong. You do not add the subheader in your process() arguments. In general, the arguments must be the same as the class that they extend. You can add the subheader inside the if ($row['CType'] === 'textmedia') {} by adding the value in the itemContent
$itemContent .= $row['subheader'];
Personally i would avoid to do it this way. My preferred choice is to call the StandAlone View and assign a template for preview. Is easier to maintain and program it.

How to inserting data from install.xml file into mysql database in moodle

In moodle site (use moodle Version 2.6.3), I have generated install.xml file by XMLDB editor, but it's use only to create table in database during plugin installation. I want to insert some default rows in the table also.
Any body can help me how to edit in install.xml file for insert data
To add data after an install, create a file called yourplugin/db/install.php with
UPDATE: added xml parser
defined('MOODLE_INTERNAL') || die;
require_once($CFG->libdir . '/xmlize.php');
function xmldb_yourpluginname_install() {
global $CFG, $OUTPUT, $DB;
// Your add data code here.
$xmltext = file_get_contents('import.xml');
$records = parse_xml($xmltext, 'records', 'record');
foreach ($records as $record) {
$DB->insert_record('yourtablename', $record);
}
}
/**
* Converts XML text into an array of stdclass objects.
*
* #param type $text - xmltext
* #param type $elementnames - plural name of elements
* #param type $elementname - name of element
* #return array|boolean - array of record objects
*/
function parse_xml($text, $elementnames, $elementname) {
// Seems that xmlize needs a lot of memory.
ini_set('memory_limit', '256M');
// Ensure content is UTF-8.
$content = xmlize($text, 1, 'UTF-8');
$records = array();
if (!empty($content[$elementnames]['#'][$elementname])) {
$rows = $content[$elementnames]['#'][$elementname];
foreach ($rows as $row) {
$fields = $row['#'];
$row = new stdClass();
foreach ($fields as $fieldname => $fieldvalue) {
$row->$fieldname = $fieldvalue[0]['#'];
}
$records[] = $row;
}
return $records;
}
return false;
}

ZF2 - Show just one error on forms

I can't seem to get ZF2 to show just one error message for failed form validation messages.
For example, an EmailAddress validator can pass back up to 7 messages and typically shows the following if the user has made a typo:
oli.meffff' is not a valid hostname for the email address
The input appears to be a DNS hostname but cannot match TLD against known list
The input appears to be a local network name but local network names are not allowed
How can I override the error to show something a little more friendly, such as "Please enter a valid email address" instead of specifics like the above?
OK, managed to come up with a solution for this. Instead of using the same string as the error for all validator failures as Sam suggested above, I have overridden the error messages in the InputFilter for the elements and then used a custom form error view helper to show only the first message.
Here is the helper:
<?php
namespace Application\Form\View\Helper;
use Traversable;
use \Zend\Form\ElementInterface;
use \Zend\Form\Exception;
class FormElementSingleErrors extends \Zend\Form\View\Helper\FormElementErrors
{
/**
* Render validation errors for the provided $element
*
* #param ElementInterface $element
* #param array $attributes
* #throws Exception\DomainException
* #return string
*/
public function render(ElementInterface $element, array $attributes = array())
{
$messages = $element->getMessages();
if (empty($messages)) {
return '';
}
if (!is_array($messages) && !$messages instanceof Traversable) {
throw new Exception\DomainException(sprintf(
'%s expects that $element->getMessages() will return an array or Traversable; received "%s"',
__METHOD__,
(is_object($messages) ? get_class($messages) : gettype($messages))
));
}
// We only want a single message
$messages = array(current($messages));
// Prepare attributes for opening tag
$attributes = array_merge($this->attributes, $attributes);
$attributes = $this->createAttributesString($attributes);
if (!empty($attributes)) {
$attributes = ' ' . $attributes;
}
// Flatten message array
$escapeHtml = $this->getEscapeHtmlHelper();
$messagesToPrint = array();
array_walk_recursive($messages, function ($item) use (&$messagesToPrint, $escapeHtml) {
$messagesToPrint[] = $escapeHtml($item);
});
if (empty($messagesToPrint)) {
return '';
}
// Generate markup
$markup = sprintf($this->getMessageOpenFormat(), $attributes);
$markup .= implode($this->getMessageSeparatorString(), $messagesToPrint);
$markup .= $this->getMessageCloseString();
return $markup;
}
}
It's just an extension of FormElementErrors with the render function overridden to include this:
// We only want a single message
$messages = array(current($messages));
I then insert the helper into my application using the solution I posted to my issue here.

Jomsocial Extra Field

I am trying to create extra fields on the Jomsocial Groups Create New Group page, its suggested on the Jomsocial docs that the best way is to creat a plugin to do this.
As I have never created such a complex plugin do anyone have a working example to start with?
Here is the code that I have tried with
<?php
defined('_JEXEC') or die('Restricted access');
if (! class_exists ( 'plgSpbgrouppostcode' )) {
class plgSpbgrouppostcode extends JPlugin {
/**
* Method construct
*/
function plgSystemExample($subject, $config) {
parent::__construct($subject, $config);
// JPlugin::loadLanguage ( 'plg_system_example', JPATH_ADMINISTRATOR ); // only use if theres any language file
include_once( JPATH_ROOT .'/components/com_community/libraries/core.php' ); // loading the core library now
}
function onFormDisplay( $form_name )
{
/*
Add additional form elements at the bottom privacy page
*/
$elements = array();
if( $form_name == 'jsform-groups-forms' )
{
$obj = new CFormElement();
$obj->label = 'Labe1 1';
$obj->position = 'after';
$obj->html = '<input name="custom1" type="text">';
$elements[] = $obj;
$obj = new CFormElement();
$obj->label = 'Labe1 2';
$obj->position = 'after';
$obj->html = '<input name="custom2" type="text">';
$elements[] = $obj;
}
return $elements;

Overwrite Zend_Config and access parents nodes

I want to overwrite Zend_Config method __set($name, $value), but I have same problem.
$name - return current key of overwrite config value, eg:
$this->config->something->other->more = 'crazy variable'; // $name in __set() will return 'more'
Because every node in config is new Zend_Config() class.
So - how from overwritten __set() metod get access to the parents nodes names?
My application:
I must overwrite same config value in controller, but to have controll about the overwritting, and do not allow to overwrite other config variables, I want to specify in same other config variable, an tree-array of overwriting allowed config keys.
Zend_Config is read only unless you have set $allowModifications to true during construction.
From the Zend_Config_Ini::__constructor() docblock:-
/** The $options parameter may be provided as either a boolean or an array.
* If provided as a boolean, this sets the $allowModifications option of
* Zend_Config. If provided as an array, there are three configuration
* directives that may be set. For example:
*
* $options = array(
* 'allowModifications' => false,
* 'nestSeparator' => ':',
* 'skipExtends' => false,
* );
*/
public function __construct($filename, $section = null, $options = false)
This means that you would need to do something like this:-
$inifile = APPLICATION_PATH . '/configs/application.ini';
$section = 'production';
$allowModifications = true;
$config = new Zend_Config_ini($inifile, $section, $allowModifications);
$config->resources->db->params->username = 'test';
var_dump($config->resources->db->params->username);
Result
string 'test' (length=4)
In response to comment
In that case you can simply extend Zend_Config_Ini and override the __construct() and __set() methods like this:-
class Application_Model_Config extends Zend_Config_Ini
{
private $allowed = array();
public function __construct($filename, $section = null, $options = false) {
$this->allowed = array(
'list',
'of',
'allowed',
'variables'
);
parent::__construct($filename, $section, $options);
}
public function __set($name, $value) {
if(in_array($name, $this->allowed)){
$this->_allowModifications = true;
parent::__set($name, $value);
$this->setReadOnly();
} else { parent::__set($name, $value);} //will raise exception as expected.
}
}
Always there is another way :)
$arrSettings = $oConfig->toArray();
$arrSettings['params']['dbname'] = 'new_value';
$oConfig= new Zend_Config($arrSettings);