Joomla throwing error for custom validation rule - php

I'm a beginner to the Joomla and trying to develop a component, but when I try to add rules to my backend panel, I keep getting this error. If anybody can tell me what I'm doing wrong, will be appreciated.
Here's the code for the rule which I've written.
com_mycomponent/models/rules/segment_name.php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* Form Rule class for the Joomla Framework.
*/
class JFormRuleSegmentName extends JFormRule
{
/**
* The regular expression.
*
* #access protected
* #var string
* #since 2.5
*/
protected $regex = '^[^0-9]+$';
}
And this is my form code:
com_mycomponent/models/forms/segment.xml
<?xml version="1.0" encoding="utf-8"?>
<form addrulepath="/administrator/components/com_mycomponent/models/rules">
<fieldset>
<field
name="id"
type="hidden"
/>
<field
name="segment_name"
type="text"
label="COM_MYCOMPONENT_SEGMENT_NAME_LABEL"
description="COM_MYCOMPONENT_SEGMENT_NAME_DESC"
size="40"
class="inputbox"
validate="segment_name"
required="true"
default=""
/>
</fieldset>
</form>
It is not working for me, this is what I get when I try to add or edit a new segment:
Error:
An error has occurred.
0 JForm::validateField() rule segment_name missing.

There are some rules that are not followed
You have used segment_name as file name but you have given SegmentName as class name. Both should match.
Not mandatory but you can use in the rules file
jimport('joomla.form.formrule');
defined('_JEXEC') or die('Restricted access');
// import Joomla formrule library
jimport('joomla.form.formrule');
/**
Form Rule class for the Joomla Framework.
*/
class JFormRuleSegment_rule extends JFormRule
{
In your form the addrule path should be given like this
<form>
<fieldset name="form_name" addrulepath="components/com_mycomponent/models/rules">
----------------fields
</fieldset>
</form>
form_name should be your form name
The suffix of the classname (JFormRule[SUFFIX]) must be the same as the rule file name. https://docs.joomla.org/Server-side_form_validation

Related

Magento2 Custom Widget Not Appearing

I created a module with a Custom Widget. When logging into the admin, going to content->widgets, creating an instance, and setting that instance to appear on the homepage, the widget appears as expected.
I have removed this instance and am now trying to create the widget by going to content->pages, editing the homepage -> content section, and selecting insert widget. I created a new instance of the widget and added some additional text into the homepage -> content section.
When I load the homepage the widget does not appear, though the rest of the text does appear.
The block for the widget is being called ( I tested this with a var_dump and exit).
The template is not being rendered however.
Here is my Block:
<?php
namespace MyNamespace\Slider\Block\Widget;
use Magento\Framework\View\Element\Template;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Block\Product\Context;
class Slider extends Template
{
protected $_template = "Yamazaki_Slider::widget/slider.phtml";
/**
* #var CollectionFactory
*/
protected $_productCollectionFactory;
/**
* #var CollectionFactory
*/
protected $_imageHelper;
/**
* #param Context $context
* #param CollectionFactory $productCollectionFactory
*/
public function __construct(Context $context, CollectionFactory $productCollectionFactory)
{
$this->_imageHelper = $context->getImageHelper();
$this->_productCollectionFactory = $productCollectionFactory;
parent::__construct($context);
}
/**
* Retrieve featured products collection
*/
public function getProducts()
{
$collection = $this->_productCollectionFactory->create();
return $collection->addAttributeToSelect('*')->addAttributeToFilter('is_featured','1');
}
}
and my Template:
<?php $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\ListProduct'); ?>
<?php foreach($this->getProducts() as $product): ?>
<?php $productImage = $imageBlock->getImage($product, 'product_page_image_large'); ?>
<?php echo $productImage->toHtml(); ?>
<?php endforeach ?>
The other files in my module are:
etc/widget.xml:
<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
<widget id="yamazaki_slider" class="MyNamespace\Slider\Block\Widget\Slider">
<label translate="true">My Image Slider</label>
<description>My Image Slider</description>
</widget>
</widgets>
module.xml and registration.php.
I do not have a etc/layout.xml file as I have noticed some widget/modules contain. Do I need this, or any other files?
Also, If I "Hide the Editor" inside content->pages->edit->content I see:
<p>{{widget type="MyNamespace\Slider\Block\Widget\Slider"}}</p>`
If I replace this with
{{block class="MyNamespace\Slider\Block\Widget\Slider" template="widget/slider.phtml"}}
The Content appears as expected
I managed to get the Block to Render
I had to add implements \Magento\Widget\Block\BlockInterface to MyNamespace\Slider\Block\Widget\Slider.
I'm not sure why this rendered, prior to adding the implements, using the first approach and not the second.
Magento is seriously lacking documentation!

Joomla Component: View: Get values from field

I'm new to Joomla, especially to component development. Anyway, here's my question:
site\views\plaingallery\tmpl\default.xml
<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PLAINGALLERY_PLAINGALLERY_VIEW_DEFAULT_TITLE">
<message>
<![CDATA[COM_PLAINGALLERY_PLAINGALLERY_VIEW_DEFAULT_DESC]]>
</message>
</layout>
<fields name="request"
addfieldpath="/administrator/components/com_plaingallery/models/fields">
<fieldset name="request">
<field name="galleryFolder" type="folderlist" default="" recursive="true"
label="Select a folder" directory="images" filter="" exclude="" width="300"
hide_none="true" hide_default="true" stripext="" />
</fieldset>
</fields>
</metadata>
site\views\plaingallery\view.html.php
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla view library
jimport('joomla.application.component.view');
/**
* HTML View class for the PlainGallery Component
*/
class PlainGalleryViewPlainGallery extends JViewLegacy
{
// Overwriting JView display method
function display($tpl = null)
{
// Assign data to the view
$this->msg = 'I am new to Joomla';
// Display the view
parent::display($tpl);
}
}
My question is: How do I access the value from the field[name="galleryFolder"] the user provided in the menu configuration?
Thanks for your help! I really do appreciate it.
This parameter is located in the query variable of the menu item.
You can try this for example:
$app = JFactory::getApplication();
/* Default Page fallback*/
$active = $app->getMenu()->getActive();
if (NULL == $active) {
$active = $app->getMenu()->getDefault();
}
if ( isset($active->query['galleryFolder']) ) {
$galleryFolder = $active->query['galleryFolder'];
}

Joomla3 custom server side form validation rule

I am new to joomla component development(J3 , MVC) and i am trying to create a custom server side form validation rule.
I added validate="machinename" to my forms field and created a the file models\rules\machinename.php
defined('_JEXEC') or die('Restricted access');
jimport('joomla.form.formrule');
class JFormRuleMachinename extends JFormRule
{
protected $regex = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/';
}
I have a empty controller in controllers\field.php
defined('_JEXEC') or die('Restricted access');
// import Joomla controllerform library
jimport('joomla.application.component.controllerform');
class SampleControllerField extends JControllerForm
{
}
and the model is in models\field.php
defined('_JEXEC') or die('Restricted access');
// import Joomla modelform library
jimport('joomla.application.component.modeladmin');
/**
* HelloWorld Model
*/
class SampleModelField extends JModelAdmin
{
public function getTable($type = 'Field', $prefix = 'SampleTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Method to get the record form.
*
* #param array $data Data for the form.
* #param boolean $loadData True if the form is to load its own data (default case), false if not.
* #return mixed A JForm object on success, false on failure
* #since 2.5
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_sample.field', 'field',
array('control' => 'jform', 'load_data' => $loadData));
if (empty($form))
{
return false;
}
return $form;
}
/**
* Method to get the data that should be injected in the form.
*
* #return mixed The data for the form.
* #since 2.5
*/
protected function loadFormData()
{
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_sample.edit.field.data', array());
if (empty($data))
{
$data = $this->getItem();
}
return $data;
}
}
my components name is com_sample and everything was working fine (new,edit,delete) but then i added the validation rule to the form's field and now i am getting a error when submitting the form :
JForm::validateField() rule `machinename` missing.
my best guess is that i have a mistake in naming or the file location but i am not sure and can't find anything with googleing .
so help me pliz ...
Find the solution myself, it seems that you need to add the rules folder pathto the form definition so :
<form addrulepath="/administrator/components/com_sample/models/rules">
this solved my problem .
I was struggling with this problem. I read the error as meaning that Joomla couldn't find the rule file, but when I single-stepped through the core I realised that after loading the rule file, Jommla checks that an appropriately named class is within the rule. I'd introduced a typo to the class name. So my advice to anyone struggling with server-side validation is to check the rule file is where you'd expect, AND that the class name is correct. Obvious I know, but it took me ages to figure.

Accessing custom attributes on a custom field in JFormField

I've created a custom field type in Joomla and need to pass parameters to it. For example, my JForm XML file looks like so:
<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset addfieldpath="/administrator/components/com_gallery/models/fields">
<field name="images"
type="MultiImage"
label="Images"
description=""
imagetable="#__gallery_images"
imagedir="../images/gallery/originals/"
/>
</fieldset>
</form>
And I want to access the imagetable and imagedir attributes within my custom field:
<?php
// No direct access to this file
defined('_JEXEC') or die;
jimport('joomla.form.formfield');
class JFormFieldMultiImage extends JFormField
{
protected $type = 'MultiImage';
public function getInput() {
//this is where i want to access it
$input = $this->imagetable;
return $input;
}
}
I assumed you just used $this->attributename, and when I var_dump($this) I can see the attributes are defined but they are :protected.
I would appreciate some help on this :)
Thanks,
Tom
You are so close! Try this and let me know if it works for you, because it works for me. (Joomla 2.5.6)
echo $this->element['imagedir'];
echo $this->element['imagetable'];

Refactoring a Zend_View_Helper_Action widget, utilizing Zend_Controller_Action_Helper_FlashMessenger, into a model

I've tried to create a login widget that can be included at will in any action that is outside the content of the application that requires login. My thought here was that I wanted a DRY-approach for rendering the login box with any error messages from a previous login attempt. To enable this I utilized the FlashMessenger for saving the result of a failed login-attempt. The widget also uses the Post/Redirect/Get-pattern to avoid the problem of posting data multiple times when using the browser back-button.
Now, the problem is that I would rather not use the Zend_View_Helper_Action since that helper clones the request and creates another run of the dispatch-loop, which is pretty resource intensive. So, by looking at the code below, could you give me some advice on how to refactor the code such that:
The widget can be included in an arbitrary view script
Results from a previous login attempt is rendered
The widget does not invoke a run in the dispatch-loop
Currently, the login widget is rendered by calling, in the view scripts:
echo $this->action('auth', 'login-widget');
AuthController.php:
class AuthController extends Zend_Controller_Action {
// This method is invoked by Zend_View_Helper_Action to render the
// login widget
public function loginWidgetAction () {
$flashMessenger = $this->_helper->flashMessenger->setNamespace('login');
$this->view->messages = $flashMessenger->getMessages();
}
public function loginAction () {
if($this->getRequest()->isPost()) {
$result = Auth::doLogin($this->getRequest()->getPost());
if($result->isValid()) {
$this->_redirect('user');
}
else {
$flashMessenger = $this->_helper->flashMessenger->
setNamespace('login');
foreach($result->getMessages() as $message) {
$flashMessenger->addMessage($message);
}
}
}
// This will be changed to redirect either to the index page,
// or the page the request originated from if available.
$this->_redirect('');
}
[...]
}
/models/Auth.php:
/**
* Model for encapsulating the actions that deals with authentication,
* such as registering and activating users, as well as logging in and
* logging out.
* #todo: Refactor this to remove static methods
*/
class Auth {
/**
*
* #return Zend_Auth_Result
*/
public static function doLogin ($credentials) {
$authAdapter = new Auth_Adapter_DbTable(
Zend_Db_Table::getDefaultAdapter(),
'Users',
'username',
'pwdHash',
'SHA1(CONCAT(?, salt))'
);
$authAdapter->setIdentity($credentials['username']);
$authAdapter->setCredential($credentials['password']);
$auth = Zend_Auth::getInstance();
return $auth->authenticate($authAdapter);
}
[...]
}
/models/Auth/Adapter/DbTable.php:
class Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable {
/**
* authenticate() - defined by Zend_Auth_Adapter_Interface. This method
* is called to attempt an authenication. Previous to this call, this
* adapter would have already been configured with all necessary
* information to successfully connect to a database table and attempt
* to find a record matching the provided identity.
*
* #throws Zend_Auth_Adapter_Exception if answering the authentication
* query is impossible
* #see library/Zend/Auth/Adapter/Zend_Auth_Adapter_DbTable#authenticate()
* #return MedU_Auth_Result
*/
public function authenticate() {
return parent::authenticate();
}
/**
* _authenticateValidateResult() - This method attempts to validate that
* the record in the result set is indeed a record that matched the
* identity provided to this adapter.
*
* Additionally it checks that the user account is activated.
*
* #param array $resultIdentity
* #return MedU_Auth_Result
*/
protected function _authenticateValidateResult($resultIdentity)
{
$result = parent::_authenticateValidateResult($resultIdentity);
if(!$result->isValid()) { return $result; }
$this->_checkAccountIsActivated($resultIdentity);
$this->_checkAccountIsSuspended($resultIdentity);
// Overwrite the username supplied by the user and instead
// use the name supplied upon registration, i.e if the
// user signs in as uSERNAME and registered as Username,
// the identity is Username
$this->_authenticateResultInfo['identity'] =
$resultIdentity[$this->_identityColumn];
return $this->_authenticateCreateAuthResult();
}
protected function _checkAccountIsActivated ($resultIdentity) {
if(!$resultIdentity['activated']) {
$this->_authenticateResultInfo['code'] =
MedU_Auth_Result::FAILURE_NOT_ACTIVATED;
$this->_authenticateResultInfo['messages'] =
array('The account has not yet been activated.
Please click on the link provided in the
activation email.');
}
}
protected function _checkAccountIsSuspended ($resultIdentity) {
if($resultIdentity['suspended']) {
$this->_authenticateResultInfo['code'] =
MedU_Auth_Result::FAILURE_SUSPENDED;
$this->_authenticateResultInfo['messages'] =
array('The account has been suspended.
If you feel this is a mistake,
please contact our support: support#meduniverse.com');
}
}
/**
* _authenticateCreateAuthResult() - This method creates a
* MedU_Auth_Result object from the information that has
* been collected during the authenticate() attempt.
*
* #return MedU_Auth_Result
*/
protected function _authenticateCreateAuthResult()
{
return new MedU_Auth_Result(
$this->_authenticateResultInfo['code'],
$this->_authenticateResultInfo['identity'],
$this->_authenticateResultInfo['messages']
);
}
}
/views/scripts/auth/partials/login-widget.phtml
// The fetchForm-view helper returns a Zend_Form object.
// The form definition (xml) is attached below in the
// code box below this one.
<div class="box">
<h3>Login</h3>
<?php if($this->messages) : ?>
<ul class="errors">
<?php foreach($this->messages as $message) : ?>
<li><?php echo $message ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<div>
<?php echo $this->fetchForm('user', 'login') ?>
</div>
</div>
/application/configs/forms.xml
// Configuration of the Login form. 'user' and 'login' are
// just keys for the view helper to return the correct form
<forms>
<user>
<login>
<action value="/auth/login" />
<method value="post" />
<elements>
<username>
<type value="text"></type>
<options>
<label value="Username" />
<required value="true" />
<validators>
<alnum validator="alnum" />
<strlen validator="StringLength">
<options min="6" max="45" />
</strlen>
</validators>
</options>
</username>
<password>
<type value="password" />
<options>
<label value="Password" />
<required value="true" />
<validators>
<strlen validator="StringLength">
<options min="6" max="20" />
</strlen>
</validators>
</options>
</password>
<submit>
<type value="submit" />
<options>
<label value="Log in" />
</options>
</submit>
</elements>
</login>
As far as I understood your solution, your current call to the Zend_View_Helper_Action helper does nothing more than rendering the login form. Why don't you write your on view helper that retrieves the login-related messages from the flash-messenger and renders the login form?
EDIT:
You can retrieve the flash-messenger from its static broker:
$flashMessenger = Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger');
$flashMessenger->setNamespace('login');
$messages = $flashMessenger->getMessages();
You don't need to instatiate a new flash-messenger in your view helper, you just can retrieve the current instance of it (see 1.). From a design point of view I'd say that it's absolutely feasible to retrieve application components within your view helpers (the Zend_View_Helper_Url for example retrieves the router from the static front-controller). To reduce coupling and to implement a setter-dependency-injection-pattern I'd suggest the following (Zend_View_Helper_Translate uses a similar pattern to retrieve the translator):
class My_View_Helper_Login extends Zend_View_Helper_Abstract
{
// [...]
/**
* #var Zend_Controller_Action_Helper_FlashMessenger
*/
protected $_flash;
/**
* #param Zend_Controller_Action_Helper_FlashMessenger $flash
* #return My_View_Helper_Login Provides a fluent interface
*/
public function setFlashMessenger(Zend_Controller_Action_Helper_FlashMessenger $flash)
{
$this->_flash = $flash;
return $this;
}
/**
* #return Zend_Controller_Action_Helper_FlashMessenger
*/
public function getFlashMessenger()
{
if ($this->_flash === null) {
$this->_flash = Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger');
}
return $this->_flash;
}
/**
*
*/
public function login()
{
$flashMessenger = $this->getFlashMessenger();
$flashMessenger->setNamespace('login');
$messages = $flashMessenger->getMessages();
// [...]
}
}
Not when the flash-messenger provides the functionality you need. If you need to distinguish between error, informational and success messages for example a home-grown solution would perhaps be the better way.
Another addition is that you can use FlashMessenger to store ANY data. So you can do
$flash->addMessage(array('status'=>'error','message'=> 'oops'));
and then in foreach use
foreach($messages as $message){
echo '<div class="message '. $message['status'] .'">' . $message['message'] . '</div>'
}
Maybe you should use ViewHelper to render form and ActionController for authentication?
This frees you from second dispatch-loop.
I can show you some little example, if you want.
P.S. You sure need validators for form? I don`t see any use in your example.

Categories