Silverstripe, hide a page after specific date in the future - php

I want to have some kind of pages created with a certain expiration date (trying to apply a date picker from silverstripe documentation didn't work with me).
That date should be in the future, at that date, I want to hide the article.

Take a look at the silverstripe/advancedworkflow module - this supports Embargo/Expiry dates (among other things).

Here is a simple implementation using a CMS controlled ExpiryDate to control whether the page can be viewed or not. This solution is for Silverstripe 3.1.
class Page extends SiteTree {
private static $db = array(
'ExpiryDate' => 'SS_Datetime'
);
public function canView($member = null) {
if ($this->ExpiryDate) {
if ($this->obj('ExpiryDate')->InPast()) {
return false;
}
}
return parent::canView($member);
}
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', $expiryDateField = Datetimefield::create('ExpiryDate', 'Page Expiry Date'), 'Content');
$expiryDateField->getDateField()->setConfig('showcalendar', true);
$expiryDateField->getTimeField()->setConfig('timeformat', 'HH:mm:ss');
return $fields;
}
}

Related

SilverStripe: Latest Blog Posts Content Block

I'm using SheaDawson's blocks module, and I'm trying to create a "latest blog posts" content block. Here is my DataObject:
<?php
class LatestBlogPosts extends Block {
private static $db = array(
'ContainInGrid' => 'Boolean',
'PostCount' => 'Int'
);
static $defaults = array(
"PostCount" => 2
);
function getCMSFields() {
$fields = parent::getCMSFields();
return $fields;
}
public function LatestPosts() {
$blog = DataObject::get("BlogEntry", "", "Date DESC", "", $this->PostCount);
return $blog;
}
}
On the page template it's not displaying any posts. It says it can't find any. When I checked the database the BlogEntry table is empty, even though I have two posts that are published.
How do I fix this issue?
In the latest version of the SilverStripe blog module the blog entry class is named BlogPost. BlogEntry is what the class used to be, but this changed sometime in 2015.
If you are using the latest version of the blog module your blog entries will be created as BlogPosts and that data will be in the BlogPost database table.
Your LatestPosts function should look like this:
public function LatestPosts() {
return BlogPost::get()->sort('Date', 'DESC')->limit($this->PostCount);
}

Silverstripe: Member Profile - Update details on Frontend

I'm trying to allow users to update their details from a frontend 'dashboard' type of page. I've got the form displaying, but when I click 'Update details', the form redirects to a blank page, and the fields haven't changed. Can someone point me in the right direction.
<?php
class MemberProfile extends Page {
private static $description = 'Page that displays the current user\'s profile';
function getCMSFields() {
$fields = parent::getCMSFields();
// we don't want the Content editor for this page type
$fields->removeFieldFromTab('Root.Main', 'Content');
return $fields;
}
}
class MemberProfile_Controller extends Page_Controller {
private static $allowed_actions = array(
'UpdateDetails'
);
public function UpdateDetails() {
$form = Form::create(
$this,
__FUNCTION__,
FieldList::create(
TextField::create('FirstName','First name:')
->setAttribute('value', Member::CurrentUser()->FirstName),
TextField::create('Surname','Last name:')
->setAttribute('value', Member::CurrentUser()->Surname)
),
FieldList::create(
FormAction::create('saveDetails','Update details')
)
);
return $form;
}
public function saveDetails($data,$form) {
$CurrentMember = Member::CurrentMember();
$CurrentMember->FirstName = $data['FirstName'];
$CurrentMember->Surname = $data['Surname'];
$form->saveInto($CurrentMember);
$CurrentMember->write();
return $this->redirectBack();
}
}
My answer would be a dev/build is needed to include the static allowed actions... that is normally what it is for me.
However my main answer would be to use this module for management of user profiles, it allows for many customisations and will save you alot of time....
https://github.com/silverstripe-australia/silverstripe-memberprofiles
"A new page type is added in the CMS called a "Member Profile Page". This allows you to create a page that allows users to register and/or manage their profile. Registration can be enabled or disabled in the "Behaviour" tab."

How to add Custom button and its functionality in Admin Silverstripe?

How to add Custom button and its functionality in Admin Silverstripe?
Please tell me solution.
Custom Button add only in one menu.
Like #wmk mentioned in the comments, you can just take the framework code for GridFieldPrintButton as a base and go from there. SilverStripe also have a basic tutorial for creating a custom ActionProvider.
Rather than rehash the tutorial here, I will provide you a very basic custom action provider that you can copy and extend to do what you need. While you don't note the exact result you are wanting from the button, I will provide just a very generic class.
This code is a stripped down version of the GridFieldPrintButton that #wmk mentioned. It supports both the button itself invoking the custom code as well as the URL.
I've noted in the code a reference that I have kept to "grid-print-button", this is to make your button sit nicely next to the print rather than likely sitting on another line (as it did in my testing on an older 3.1 site I built).
class GridFieldCustomButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler {
protected $targetFragment;
protected $someCustomConstructData;
//TargetFragment is just for positioning control of the HTML fragment
//SomeCustomConstructData is just an example of providing some default options into your butotn
public function __construct($targetFragment = "after", $someCustomConstructData = null) {
$this->targetFragment = $targetFragment;
$this->someCustomConstructData = $someCustomConstructData;
}
//Generate the HTML fragment for the GridField
public function getHTMLFragments($gridField) {
$button = new GridField_FormAction(
$gridField,
'custom',
'Custom Action',
'custom',
null
);
return array(
//Note: "grid-print-button" is used here to match the styling of the buttons in ModelAdmin
$this->targetFragment => '<p class="grid-print-button">' . $button->Field() . '</p>',
);
}
public function getActions($gridField) {
return array('myCustomAction');
}
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == 'myCustomAction') {
return $this->handleMyCustomAction();
}
}
//For accessing the custom action from the URL
public function getURLHandlers($gridField) {
return array(
'myCustomAction' => 'handleMyCustomAction',
);
}
//Handle the custom action, for both the action button and the URL
public function handleMyCustomAction($gridField, $request = null) {
//Do your stuff here!
}
}
Continuing on from the discussion in the comments, you will need to modify your custom ModelAdmin to add new components to its GridField.
class MyCustomAdmin extends ModelAdmin
{
private static $managed_models = array(
'MyCustomObject'
);
private static $url_segment = 'custom-admin';
private static $menu_title = 'All Custom Objects';
public function getEditForm($ID = null, $Fields = null)
{
$form = parent::getEditForm($ID, $Fields);
$fields = $form->Fields();
$gridField = $fields->fieldByName('MyCustomObject');
$gridFieldConfig = $gridField->getConfig();
$gridFieldConfig->addComponent(new GridFieldCustomButton());
return $form;
}
}
Specifically, the line $gridFieldConfig->addComponent(new GridFieldCustomButton()) does the work, taking your custom button as I have shown above and added it to the ModelAdmin. You can also specify where it should go in the GridField too by providing "buttons-before-left" as the first argument in the GridFieldCustomButton constructor.
eg. $gridFieldConfig->addComponent(new GridFieldCustomButton("buttons-before-left"))
More information regarding GridField fragments can be found in the SilverStripe developer documentation.

Cakephp View caching based on custom key

In my project we display custom widgets on our customers pages. The widgets themselves do not change very often, so I feel view caching could be extremely useful here.
But every widget is different based on which company in our system is requesting it.
My question is using the cache helper...or any other method, can I cache the widget based on the company id?
<?php
App::uses('AppController', 'Controller');
class widgetController extends AppController {
public $helpers = array( 'Cache' );
public $cacheAction = array(
'iframeForm' => 3600,
);
public $uses = array('Company');
public function index( $company_id ) {
//... Load up a ton of data
$this->layout = 'widget';
$this->set( compact(/* Set a ton of data */) );
}
}
Is it possible to cache the index view based on the company id so that:
/widget/index/1
is served one copy from cache, but:
/widget/index/2
will get a different copy from the cache?
We are currently running on cake 2.3 and php5.3 we have plans to move to cake2.4 and php 5.5 if that would offer us any help.
I would do something like this:
Controller:
public function index( $company_id ) {
//... Load up a ton of data
$this->Model->getStuff($company_id);
$this->layout = 'widget';
$this->set( compact(/* Set a ton of data */) );
}
In model:
public function getStuff( $company_id ) {
if(($modelData = Cache::read('modelDataCompanyID_'. $company_id)) == null)
{
$modelData = $this->find('all',array('conditions' =>
array('Model.company_id' => $company_id)));
Cache::write('modelDataCompanyID_'. $company_id, $modelData);
}
return $modeData;
}
}
Is this what you want?

How to Retrieve Image Files from Database Using Yii Framework?

Our Yii Framework application has the following defined as part of the UserProfileImages model:
public function getProfileImages($param, $user_id) {
if(isset($param['select']) && $param['select']=='all'){
$profile_images = UserProfileImages::model()->findAllByAttributes( array( 'user_id'=>$user_id) );
} else {
$profile_images = UserProfileImages::model()->findByAttributes( array( 'user_id'=>$user_id) );
}
return $profile_images;
}
How would I wire up the above snippet to a widget in my view to return all the images for a given user?
Bonus Question: Which image rotator do you suggest to render the above?
In your view file, add something like this, assuming that your controller specified $user_id:
$this->widget('UserProfileImagesWidget', array(
"userProfileImages" => UserProfileImages::getProfileImages(
array("select" => "all"),
$user_id
),
"user_id" => $user_id
));
Depending on your MVC philosophy, you could also retrieve the userProfileImages data in the controller and pass that data to your view.
Define a widget like this:
class UserProfileImagesWidget extends CWidget {
public $user_id;
public $userProfileImages = array();
public function run() {
$this->render("userProfileImage");
}
}
Finally, in the userProfileImages.php view file, you can do something like this:
if(!empty($this->userProfileImages)) {
// Your display magic
// You can access $this->user_id
}
As a side note: You might want to change the order of your parameters in getProfileImages. If $user_id is the first parameter, you can leave out $params completely in case you don't want to specify any.

Categories