SilverStripe 3.1 - Page creating & publishing from the FrontEnd - php

for our company intranet, I created a page with a Form to create an E-Mailing from the frontend (Create a New E-Mailing Page).
The page should be Live after saving the form.
I did it like this, but I think I made a mistake somewhere. Because KW1, KW2, Date and SendDate are only visible on the frontend if I go to the backend and click publish again.
public static $allowed_actions = array(
'MailingForm'
);
public function MailingForm() {
$date = new DateField('EndDate', 'Gültig bis');
$date->setConfig('showcalendar', true);
$sendDate = new DateField('SendDate', 'Versanddatum');
$sendDate->setConfig('showcalendar', true);
$fields = new FieldList(
new TextField('Title', 'Title'),
new TextField('KW1', 'Start KW'),
new TextField('KW2', 'End KW'),
$date,
$sendDate
);
$actions = new FieldList(
new FormAction('createMailing', 'Erstellen')
);
//$validator = new RequiredFields('Title');
return new Form($this, 'MailingForm', $fields, $actions);//, $validator);
}
public function createMailing($data, $form) {
$member = Member::currentUser();
$filter = new URLSegmentFilter();
$page = new Mailing();
$form->saveInto($page);
$page->PublisherID = $member->ID;
$page->AuthorID = $member->ID;
$page->ParentID = $this->ID;
$page->URLSegment = $filter->filter($page->Title);
$page->writeToStage('Stage');
$page->publish('Stage', 'Live');
// EMAIL BEG
$email = new Email();
$email->setTo('mail#mail.de');
$email->setFrom('intranet#mail.de');
$email->setSubject('Neues E-Mailing für '.$this->Title);
$messageBody = "
<p>Neues E-Mailing wurde angelegt und wartet auf Freischaltung</p>
<p><strong>Name:</strong> {$data['Title']}</p>
<p><strong>KWs:</strong> {$data['KW1']} - {$data['KW2']}</p>
<p><strong>Gültig bis:</strong> {$data['EndDate']}</p>
<p><strong>Versanddatum:</strong> {$data['SendDate']}</p>
";
$email->setBody($messageBody);
$email->send();
// EMAIL END
return $this->redirect($this->Parent()->URLSegment.'/'.$this->URLSegment.'/'.$page->URLSegment);
}
If I replace $page->writeToStage('Stage');
$page->publish('Stage', 'Live'); with $page->write() than the page isn't published if i add $page->write() to the other two than i receive this error
Can't find [Title of Page]/[Page ID] in stage Stage
Can someone help me here?
Thank you in advance
To break down the problem again
If I publish the Page with
$page->write();
$page->writeToStage('Stage');
$page->publish('Stage', 'Live');
than all data is submitted correctly but I receive the following error http://www.picbutler.de/bild/301819/erroroirpt.jpg and the page is only saved as live version. In the backend the page is than marked as "deleted from draft". So I think this is the right direction.
If I publish the Page with
$page->writeToStage('Stage');
$page->publish('Stage', 'Live');
I receive no error, the submitted data appears in the backend BUT NOT in the published version. I have to publish the Page again in the backend to make the data visible in frontend.
So any ideas how to fix this?

ok, a million tries later i got it! :)
For everybody else who get stuck on this.
You just need to restore the live page to stage after writing
$page->write();
$page->doRestoreToStage();
That's all :)

Many many thanks for your two lines of codes
$page->write();
$page->doRestoreToStage();
I have been struggling with SiteTree table for a last few days,trying to write a new record to this table.
One important point is never use SiteTree class directly otherwise it won't work
eg $mySiteTree = new SiteTree(); (Bad)
Create a new page extends SiteTree() , say, Mypage
$mypage = new Mypage();
$mypage->Title = 'My Page';
$mypage->URLSegment = 'testing';
$mypage->ShowInMenus = '1';
$mypage->Version = '1';
$mypage->ParentID = '24';
$mypage->write();
$mypage->doRestoreToStage();
Enjoy!!!!

Related

Symfony does not find a recently persisted entity - Doctrine/Symfony

I am trying to do a simple operation: create 2 entries; on each creation, first check if the entity exists, create it, if it does not, and then do the adjustment. In some cases (on first such operation) we need to create the entity in the first entry and work with it in the second. Unfortunately, this does not happen and we end up with two entries that are useless. After this initial issue, everything works as expected (i.e. on next iteration the entity is properly found).
Here is the code for the entries:
// Create first entry
$debitCode = 'bank';
$creditCode = 'equity';
// Create entry
$accountEntry = new AccountEntry();
$accountEntry->setAmount($amount);
$debitAccount = $unit->getAccountByType($debitCode);
if (!$debitAccount) {
// Create debit account
$debitAccountType = $em->getRepository('App:AccountType')->findOneBy(['code' => $debitCode]);
$debitAccount = new Account();
$debitAccount->setType($debitAccountType);
$em->persist($debitAccount);
}
$debitAccount->debit($amount);
$accountEntry->setDebitAccount($debitAccount);
$creditAccount = $unit->getAccountByType($creditCode);
if (!$creditAccount) {
// Create credit account
$creditAccountType = $em->getRepository('App:AccountType')->findOneBy(['code' => $creditCode]);
$creditAccount = new Account();
$creditAccount->setType($creditAccountType);
$em->persist($creditAccount);
}
$creditAccount->credit($amount);
$accountEntry->setCreditAccount($creditAccount);
$em->persist($accountEntry);
$em->flush();
// Create second entry
$debitCode2 = 'accountsPayable';
$creditCode2 = 'bank';
$accountEntry2 = new AccountEntry();
$accountEntry2->setAmount($amount);
$debitAccount = $unit->getAccountByType($debitCode2);
if (!$debitAccount) {
// Create debit account
$debitAccountType = $em->getRepository('App:AccountType')->findOneBy(['code' => $debitCode2]);
$debitAccount = new Account();
$debitAccount->setUnit($unit);
$debitAccount->setType($debitAccountType);
$em->persist($debitAccount);
}
$debitAccount->debit($amount);
$accountEntry2->setDebitAccount($debitAccount);
$creditAccount = $unit->getAccountByType($creditCode2);
if (!$creditAccount) {
// Create credit account
$creditAccountType = $em->getRepository('App:AccountType')->findOneBy(['code' => $creditCode2]);
$creditAccount = new Account();
$creditAccount->setUnit($unit);
$creditAccount->setType($creditAccountType);
$em->persist($creditAccount);
}
$creditAccount->credit($amount);
$accountEntry2->setCreditAccount($creditAccount);
$em->persist($accountEntry2);
$em->flush;
And here is the getAccountByType function:
/**
* Get Account by type of account.
*/
public function getAccountByType($code)
{
$filter = function ($account) use ($code) {
if ($account->getType()->getCode() == $code) {
return $account;
}
};
$accounts = $this->accounts->filter($filter)->getValues();
return isset($accounts[0]) ? $accounts[0] : null;
}
And, of course, 30 minutes after I posted the question, I found the answer myself (despite having been banging my head against the wall for a couple of days before posting).
Basically, we need to refresh the $unit entity after persisting/flushing the initial entry:
$em->refresh($unit);
Otherwise, the getAccountByType method apparently does not take into account the changes. So, it appears that entity methods do not take into account flushed changes to the database, if the entity is not refreshed. Probably basic stuff, but I did not know that. I hope this will save someone lots of trouble.

Prestashop Controller - Change the current store on Multistore

I have a multistore environment on a prestashop. I created a module with a controller to change store if postal code is not correct. The problem comes when I use Tools::redirect($newUrlToRedirect); it redirects to my current store, and I need it redirects to another store. This is my code:
class cartportkeyDeriverModuleFrontController extends ModuleFrontController {
public function init(){
//I am in the url http://localhost/shopgroup/shopnameCART/quick-order and
//check the postal code, then clicking a link I go to the URL
//http://localhost/shopgroup/shopnameNEW/index.php?fc=module&module=cartportkey&controller=deriver&id_cart=XXX&id_shop=YYY
parent::init();
$id_cart = (int)Tools::getValue('id_cart');
$id_shop = (int)Tools::getValue('id_shop');
$this->context->cookie->id_cart = $id_cart;
$link_order = $this->context->link->getPageLink('order');
$testShop = Context::getContext()->shop;
//HERE I OBTAIN THE storeOLD instead storeNEW so I am redirecting again to storeOLD
$testShop = json_decode(json_encode($testShop), true);
$newUrlToRedirect = "http://".$testShop['domain'].$testShop['physical_uri'].$testShop['virtual_uri'].'quick-order';
//print $newUrlToRedirect;
$cart = new Cart(33);
$cart->delete();
Tools::redirect($newUrlToRedirect);
}
public function initContent() {
parent::initContent();
}
}
I had put some clarifications in the code as comments. The question is, how can I change the active store??
I have found my own answer. Instead of getting the context in $testShop = Context::getContext()->shop;
Change that line for:
$testShop = new Shop($id_shop);
$testShop->getContext();
Everything fine. Thanks!

Codeigniter show error page instead Exception error

this is my code
public function movieInfo($movieId = null) {
// get the data
$movie = $this->repository->load($movieId);
$this->set_title(null);
$data = $this->includes;
$content_data = array(
'movie' => $movie,
);
$data['content'] = $this->load->view('movie/movie_info', $content_data, true);
$this->load->view($this->template, $data);
}
when i browse to http://tmdb.instaplace.me/movie/movieinfo/76341 it shows my page
but when i browse to http://tmdb.instaplace.me/movie/movieinfo/0
it shows a uncaught exception page when error reporting is set to development otherwise it shows a blank page
instead of showing blank page or uncaught exception on development i want to show a page that says "The id does not exist" for example or a 404 page
but my problem is i can't figure it out how to do that, i am using this
php-tmdb wrapper
the $movieId variable is the id from themoviedb.org to find the movie based on the id
if( ! $movie = $this->repository->load($movieId) ){
$this->_showMovieNotFoundFor($movieId) ; }
else{ $this->_showFound($movie) ; }
edit in response to question ====
you have to create the _show methods yourself. the idea is that you are just checking if a movie came back from the database or not. in the controller the simpler you can make your methods the easier it is to maintain. and unless a method in a controller has to be public, always make them private. in codeigniter you can just put an underscore before the method name to make it private. so the code
if( ! $movie = $this->repository->load($movieId)
so if the $movie did NOT come back from database - then go to
$this->_showMovieNotFoundFor($movieId) ;
i included $movieId in case its needed for the error message.
otherwise you got $movie from database so go to
$this->_showFound($movie) ;
where if we just paste your code its going to be something like
function _showFound($movie){
$this->set_title(null);
$data = $this->includes;
$content_data = array(
'movie' => $movie,
);
$data['content'] = $this->load->view('movie/movie_info', $content_data, true);
$this->load->view($this->template, $data);
}

How to catch a calendar item created event using push notifications?

I'm trying to fire an event when I create a calendar item (appointment) in exchange, using PHP-EWS. Currently, I am able to fire an event when an email is sent:
$subscribe_request = new \EWSType_SubscribeType();
$pushSubscription = new \EWSType_PushSubscriptionRequestType();
$pushSubscription->StatusFrequency = 1;
$pushSubscription->URL = 'http://someserver/log.php';
$folderIDs = new \EWSType_NonEmptyArrayOfBaseFolderIdsType();
$eventTypes = new \EWSType_NonEmptyArrayOfNotificationEventTypesType();
$folderIDs->DistinguishedFolderId = new \EWSType_DistinguishedFolderIdType();
$folderIDs->DistinguishedFolderId->Id = \EWSType_DistinguishedFolderIdNameType::INBOX;
$eventTypes->EventType = "NewMailEvent";
$pushSubscription->FolderIds = $folderIDs;
$pushSubscription->EventTypes = $eventTypes;
$subscribe_request->PushSubscriptionRequest = $pushSubscription;
return $this->ews->Subscribe($subscribe_request);
log.php
class ewsService {
public function SendNotification($arg) {
file_put_contents("C:\\exchangelogs\\log_".time().".txt", print_r($arg,1));
$result = new EWSType_SendNotificationResultType();
$result->SubscriptionStatus = 'OK';
//$result->SubscriptionStatus = 'Unsubscribe';
return $result;
}
}
$opts = array();
$server = new SoapServer(
'NotificationService.wsdl',
array('uri' => 'http://someserver/log.php'));
$server->setObject($service = new ewsService());
$server->handle();
Every minute a 'Keep alive message' is sent and the SendNotification function is called. The same thing happens when a mail is sent (using outlook or whatever).
This all works fine.
However, now I want to do the same when a calendar item is created, such as an appointment. I tried changing the DistinguishedFolderIdNameType to CALENDAR and the EventType to CreatedEvent, but I receive no message when an appointment is created.
Any help is greatly appreciated.

Silverstripe: I can't handle sub-URLs of a Form object. Subsites module

Bit of a long shot but can anyone shed any light on this?
I have recently installed the subsites module to run multiple sites from a single installation and am now getting the error: "I can't handle sub-URLs of a Form object." when I try to add descriptions/titles to image gallery objects. I have removed the subsites to verify that it is this which is causing the issue. I am using 2.4
I can upload images fine, however it is when trying to save a description from the popup that the issue arises.
I have tried with the default fields too and this still gives the same error.
My code:
<?php
class Gallery extends Page {
public static $db = array(
'SummaryText'=>'Text',
'GalleryText'=>'Text'
);
static $has_many = array(
'Photos' => 'GalleryPhoto'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$manager = new ImageDataObjectManager(
$this, // Controller
'Photos', // Source name
'GalleryPhoto', // Source class
'Image' // File name on DataObject
);
$manager->uploadFolder = $this->URLSegment;
$fields->addFieldToTab('Root.Content.Main', new TextField('SummaryText', 'Summary Text (Appears in the section preview)'), 'Content');
$fields->addFieldToTab('Root.Content.Main', new TextField('GalleryText', 'Gallery Text (entering anything in here will overwrite any image Titles and Descriptions)'), 'Content');
$fields->addFieldsToTab("Root.Content.Gallery", array($manager));
$fields->removeFieldFromTab('Root.Content', 'StyledText');
$fields->removeFieldFromTab('Root.Content', 'Column2');
$fields->removeFieldFromTab('Root.Content', 'Content');
return $fields;
}
}
..
<?php
class GalleryPhoto extends Photo {
public static $db = array(
'HTMLDescription'=>'HTMLText'
);
static $has_one = array(
'Gallery' => 'Gallery'
);
public function getCMSFields(){
$fields = parent::getCMSFields();
$fields->removebyname('Description');
$fields->removebyname('Title');
$fields->replaceField('HTMLDescription', new SimpleTinyMCEField('HTMLDescription'));
return $fields;
}
}
Unfortunately "I can't handle sub-URLs of a Form object." is a pretty generic error message and from my experience rather tricky to debug.
To be honest, the Subsites module isn't that great in my opinion, it works, but its not that nice and not really compatible with other modules I guess.
I could imagine that the reason for your error is because silverstripe forgets the SubsiteID inside the popup and because of that SilverStripe can no longer find the current Page you are editing (because it adds a filter WHERE SubsiteID = x to every query of Pages you make)
one place to start debuging would be hooking into Subsite::currentSubsiteID() and see if it remembers the SubsiteID when you are in the popup
also, what is the exact url that gets called when you get the error message?
I just had the same error, searched for hours. It was a problem with /framework/control/Session.php

Categories