I create a form like this link but when I try to submit these error shows to me
1- how to extend these form to all classes {pages} (I try it in Page & PageController and the form is repeating in my all other pages class)
2- how to fix these errors?
Page.php:
<?php
namespace {
use SilverStripe\CMS\Model\SiteTree;
use project\Subscribe;
class Page extends SiteTree
{
private static $has_many = [
'Subscribes' => Subscribe::class,
];
}
}
PageController.php:
<?php
namespace {
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\EmailField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\RequiredFields;
use project\Subscribe;
class PageController extends ContentController
{
private static $allowed_actions = [
'EmailForm',
];
public function EmailForm()
{
$form = Form::create(
$this,
__FUNCTION__,
FieldList::create(
EmailField::create('Email',''),
),
FieldList::create(
FormAction::create('handleSubscribe','Submit')
->setUseButtonTag(true)
->addExtraClass('button')
),
RequiredFields::create('Email')
)
->addExtraClass('input-group');
foreach($form->Fields() as $field) {
$field->addExtraClass('form-control')
->setAttribute('placeholder', $field->getName().'*');
}
foreach($form->Fields() as $field) {
$field->addExtraClass('form-control')
->setAttribute('placeholder', $field->getName().'*');
}
$data = $this->getRequest()->getSession()->get("FormData.{$form->getName()}.data");
return $data ? $form->loadDataFrom($data) : $form;
}
public function handleSubscribe($data, $form)
{
$session = $this->getRequest()->getSession();
$session->set("FormData.{$form->getName()}.data", $data);
$existing = $this->Subscribes()->filter([
'Subscribe' => $data['Subscribe']
]);
if($existing->exists()) {
$form->sessionMessage('That Email already exists! Spammer!','bad');
return $this->redirectBack();
}
$subscribe = Subscribe::create();
$subscribe->PageID = $this->ID;
$form->saveInto($subscribe);
$subscribe->write();
$session->clear("FormData.{$form->getName()}.data");
$form->sessionMessage('Thanks for your comment!','good');
return $this->redirectBack();
}
}
}
Suscribe.php:
<?php
namespace projet;
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
class Subscribe extends DataObject
{
private static $singular_name = 'Subscribe';
private static $table_name = 'Subscribe';
private static $db = [
'Email' => 'Varchar(100)',
];
private static $has_one = [
'Page' => Page::class,
'Home' => Home::class,
];
private static $summary_fields = array(
'Email' => 'Email',
);
}
Home.php:
<?php
namespace project;
use Page;
use PageController;
class Home extends Page {
private static $singular_name = 'Home';
private static $description = 'Index Page';
private static $table_name = 'Home';
private static $icon = 'app/icon/home.png';
private static $has_many = [
'Subscribes' => Subscribe::class,
];
}
class HomeController extends PageController {
}
How to extend fix the Non-duplicate data & extends to the whole project?
Related
I've been stuck on this for a while now and I can't see where I'm going wrong.
I've made a class that extends the UserDefinedForm so I can have a page that also has a UserDefinedForm on it. The form loads on the page, but it isn't as easy as just saying $Form on the template file, instead I have to make and call the following function:
public function getUserForm() {
$page = UserDefinedForm::get()->byID($this->ID);
$controller = UserDefinedFormController::create($page);
return $controller->Form();
}
So when I call that function on the template it displays the form, however, none of my field rules are applied and when submitting the form it takes me to a blank page with "/finished" appended to the URL: "https://example.com/finished".
Can someone please help me out here, would be much appreciated.
I will put my code down below.
Class extending the UserDefinedForm:
<?php
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\FileHandleField;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Assets\Image;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Forms\DropdownField;
use SilverStripe\UserForms\Model\UserDefinedForm;
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\EditableCustomRule;
class Package extends UserDefinedForm {
private static $db = [
'Date' => 'Text',
'Location' => 'Text',
'Availability' => 'Enum(array("Available","Hidden","Sold Out"))',
'Extras' => 'HTMLText',
'NeedTo' => 'HTMLText',
'Price' => 'Text'
];
private static $has_one =[
'Photo' => Image::class,
];
private static $has_many =[
'FileAttachments' => 'PackageFile'
];
private static $many_many = [
'SacredTexts' => 'ImportantText'
];
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', Injector::inst()->create(FileHandleField::class, 'Photo'));
$fields->addFieldToTab('Root.Main', new TextField('Date', 'Date'));
$fields->addFieldToTab('Root.Main', new TextField('Location', 'Location'));
$fields->addFieldToTab('Root.Main', new TextField('Price', 'Price'));
$fields->addFieldToTab('Root.Main', new HTMLEditorField('Extras', 'Extras'));
$fields->addFieldToTab('Root.Main', new HTMLEditorField('NeedTo', 'What you need to know'));
$fields->addFieldToTab('Root.Main', new DropdownField('Availability', 'Availability', singleton('Package')->dbObject('Availability')->enumValues()));
$fields->addFieldToTab('Root.Main', new GridField('SacredTexts', 'Important Texts', $this->SacredTexts(), GridFieldConfig_RecordEditor::create()),'Date');
$fields->addFieldToTab('Root.Main', new GridField('FileAttachments', 'File Attachments', $this->FileAttachments(), GridFieldConfig_RecordEditor::create()),'Content');
return $fields;
}
/* Look up SS4 docs on SS Sitetree URL parse function and what needs to be namespaced */
function onBeforeWrite () {
parent::onBeforeWrite ();
if($this->Name){
$this->Slug = str_replace(' ','-', strtolower($this->Name));;
}
}
public function ShortContent( $word_limit = 20 ) {
$NoHTML = htmlspecialchars_decode(strip_tags($this->NewsText),ENT_QUOTES);
$words = explode( ' ', $NoHTML );
return implode( ' ', array_slice( $words, 0, $word_limit ) );
}
public function ParentEvent(){
return $this->Parent()->URLSegment;
}
public function getUserForm() {
$page = UserDefinedForm::get()->byID($this->ID);
$controller = UserDefinedFormController::create($page);
return $controller->Form();
}
public function hasUserForm() {
if (count($this->getUserForm()->Fields()) > 1) {
return $this->getUserForm();
}
}
}
I figured it out.
Turns out the class controller I was extending to override wasn't working, instead it was referring to the UserDefinedFormController. I fixed it by copying the following function from the UserDefinedForm class:
public function getControllerName()
{
return UserDefinedFormController::class;
}
and copying it into my extended class from UserDefinedForm and renaming the return statement to the name of the class, for example:
public function getControllerName()
{
return PackageController::class;
}
I get this error with the ATK 9 framework
class App\Modules\Auth\Module contains 1 abstract method and must therefore be declared abstract or implement the remaining methods
calling the below class:
abstract class Module
{
public static $module;
/** #var Atk $atk */
private $atk;
/** #var Menu $menu */
private $menu;
public function __construct(Atk $atk, Menu $menu)
{
$this->atk = $atk;
$this->menu = $menu;
}
protected function getMenu()
{
return $this->menu;
}
protected function getAtk()
{
return $this->atk;
}
abstract public function register();
public function boot()
{
//noop
}
public function registerNode($nodeName, $nodeClass, $actions = null)
{
$this->atk->registerNode(static::$module.'.'.$nodeName, $nodeClass, $actions);
}
public function addNodeToMenu($menuName, $nodeName, $action, $parent = 'main', $enable = null, $order = 0, $navbar = 'left')
{
if ($enable === null) {
$enable = [static::$module.'.'.$nodeName, $action];
}
$this->menu->addMenuItem($menuName, Tools::dispatch_url(static::$module.'.'.$nodeName, $action), $parent, $enable, $order, static::$module, '', $navbar);
}
public function addMenuItem($name = '', $url = '', $parent = 'main', $enable = 1)
{
$this->menu->addMenuItem($name, $url, $parent, $enable, 0, static::$module);
}
}
this is the code i use to call the class Module:
class Module extends \Sintattica\Atk\Core\Module
{
static $module = 'auth';
public function boot()
{
$this->registerNode('users', Users::class, ['admin', 'add', 'edit', 'delete']);
$this->registerNode('groups', Groups::class, ['admin', 'add', 'edit', 'delete']);
$this->registerNode('users_groups', UsersGroups::class);
$this->addMenuItem('auth');
$this->addNodeToMenu('users', 'users', 'admin', 'auth');
$this->addNodeToMenu('groups', 'groups', 'admin', 'auth');
}
}
thanks
You HAVE TO implement register method from \Sintattica\Atk\Core\Module Class in your Client Module Class.
When extending an Abstract class, ALL Abstract methods MUST be implemented in client(child class) code.
GOT THIS ERROR Call to a member function parseCriteria() on null CAK
`
CONTROLLER
class ProductsController extends AppController {
public $components = array('Search.Prg');
public function index() {
// start a standard search
$this->Prg->commonProcess();
// process the URL parameters
$params = $this->Prg->parsedParams();
// generate the Paginator conditions
$conditions = $this->Product->parseCriteria($params);
// add the conditions for paging
$this->Paginator->settings['conditions'] = $conditions;
$this->set('products', $this->Paginator->paginate());
}
}
MODEL
class Product extends AppModel {
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'product' => array(
'type' => 'like',
'field' => 'name'
)
);
}
VIEW
echo $this->Form->create();
echo $this->Form->input('product');
echo $this->Form->end(__('Search'));'
I have the following model:
class Person
{
public $name;
function __Construct( $name )
{
$this->name = $name;
}
}
I have the following controller:
class NavigationController extends Controller
{
public function indexAction()
{
$people = array(
new Person("James"),
new Person("Bob")
);
return $this->render('FrameworkBundle:Navigation:index.html.php', $people);
}
}
How do I get access to the model array in the view. Is there a way to access the model directly or do I have to assign a property like so:?
class NavigationController extends Controller
{
public function indexAction()
{
$people = array(
new Person("James"),
new Person("Bob")
);
return $this->render('FrameworkBundle:Navigation:index.html.php', array( "model" => $people ) );
}
}
View:
<?php
foreach( $model as $person )
{
echo $person->title;
}
?>
The problem with the above will be that it can be changed by a user to
return $this->render( 'FrameworkBundle:Navigation:index.html.php', array( "marybloomingpoppin" => $people ) );
With the example view you used, you already had the correct implementation:
class NavigationController extends Controller
{
public function indexAction()
{
$people = array(
new Person("James"),
new Person("Bob")
);
return $this->render('FrameworkBundle:Navigation:index.html.php', array( "model" => $people ) );
}
}
You mentioned the concern that somebody could change the assignment in the controller, but this is something you always have if somebody changes the name of a variable only in one place and not in all. So I don't think this is an issue.
Having the following class that is extended by other controllers
class Admin_Controller extends Base_Controller
{
static $admin_layout = 'admin.layouts.default';
public function __construct()
{
parent::__construct();
$role_object = User::find(Auth::user()->id)->roles()->get();
$role = $role_object[0]->attributes['name'];
such as:
class Admin_Draws_Controller extends Admin_Controller
{
public $restful = true;
public function __construct()
{
$this->layout = parent::$admin_layout;
parent::__construct();
}
public function get_index()
{
$view = View::make('admin.templates.draws');
$this->layout->content = $view;
}
}
How can I send the $role variable to admin.layouts.default so I can have it when ever the view is loaded?
The point of "global" $role variable is to avoid to have to call it in all of my View::make() like the following:
$view = View::make('admin.templates.articles',
array(
'fields' => $fields,
'data' => $results,
'links' => $links,
'role' => 'role here'. // I don't want to add this where ever I call the View::make
)
);
$this->layout->content = $view;
and just do an echo $role like, in my header.blade.php
I ended up doing the following, which works.
Controller
// Example of variable to set
$this->layout->body_class = 'user-register';
$view = View::make('modules.user.register', array(
'success' => true,
));
$this->layout->content = $view;
My default.layout.php view
<body class="<?php echo isset($body_class) ? $body_class : '' ;?>">
#include('partials.header')
{{ $content }}
#include('partials.footer')
The variable, can be easily used in any other context within the view.