Silverstipe tutorial - addFieldToTab does not work - silverstripe

I am following silverstripe tutorial number 2: Extending a basic site http://doc.silverstripe.org/framework/en/tutorials/2-extending-a-basic-site
I have downloaded ss3.0.3 and using Windows 7 WAMP 2.1
I have created the ArticlePage and ArticleHolderPage but when I go and create a page of type ArticleHolder there are no date and author fields in the content tab.
My code for the ArticlPage:
class ArticlePage extends Page
{
static $db = array(
'Date'=>'Date',
'Author'=>'Text'
);
public function getCMSFields()
{
$fields = parent::getCMSFields();
$dateField = new DateField('Date');
$dateField = setConfig('showcalendar', true);
$fields->addFieldToTab('Root.Main', $dateField, 'Content');
$fields->addFieldToTab('Root.Main', new TextField('Author'), 'Content');
return $fields;
}
}
Am I doing something wrong?
Thank you

oh, i was too quick with my comment above, just found an error in your code:
$dateField = setConfig('showcalendar', true);
should read
$dateField->setConfig('showcalendar', true);

Related

What I am doing wrong with twitter API?

I am making a widget using https://github.com/j7mbo/twitter-api-php.
My widget is working fine there is no problem in my widget.
So what's the problem:
Inside my TwitterWidget Class whichi is extending WP_Widget inside the widget( $args, $instance ). I have make a function inside :
Here is it:
function get_Connection_With_Twitter_API( $scr_name, $cons_key, $cons_secret, $acce_token_key, $acce_token_secret ) {
$settings = array(
'oauth_access_token' => $acce_token_key,
'oauth_access_token_secret' => $acce_token_secret,
'consumer_key' => $cons_key,
'consumer_secret' => $cons_secret
);
$url = 'https://api.twitter.com/1.1/followers/ids.json';
$getfield = '?screen_name='.$scr_name;
$requestMethod = 'GET';
$twitter = new TwitterAPIExchange($settings);
echo $twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest();
// $twitter = new TwitterAPIExchange($settings);
// return $twitter->buildOauth($url, $requestMethod)
// ->setPostfields($postfields)
// ->performRequest();
}
$connection = get_Connection_With_Twitter_API( $instance['twitter_username'], $instance['twitter_consumerkey'], $instance['twitter_consumersecret'], $instance['twitter_accesstoken'], $instance['twitter_accesstokensecret'] );
I am getting this message:
{"errors":[{"code":89,"message":"Invalid or expired token."}]}
What I am doing wrong.
I assume you have your access tokens and you are being careful not displaying them here, and you have created a new app on the twitter account. On that light, I strongly suggest you change the permission of your app to "Read, Write and Direct Message".
For the perfect and most simple and well documented api, I suggest Twit.

Upload photo without form (API)

I'm making an app mobile and I need to upload a photo from my camera via my API. But when doctrine try to INSERT INTO, he isn't happy because my name field is null. So the name generate by my entity is missing.
I don't understand where the code block. My web app uses already the same entity photo and everything works fine.
My Api controller:
<?php
/**
* #throws AccessDeniedException
* #return array
* #FOSRest\View()
*/
public function apiUploadAction()
{
$photo = new Photo;
$photo->setUser($this->getUser());
$photo->setFile = new UploadedFile(
$_FILES["file"]["tmp_name"],
$_FILES["file"]["name"],
$_FILES["file"]["type"],
$_FILES["file"]["size"],
$_FILES["file"]["error"],
$test = false
);
$em = $this->getDoctrine()->getManager();
$em->persist($photo);
$em->flush();
$apiResponse = array(
"code" => true,
"style" => "success",
/*********** SCREENSHOT COMES FROM HERE ***********/
"message" => $_FILES["file"]["tmp_name"]." ".$_FILES["file"]["name"]." ".$_FILES["file"]["type"]." ".$_FILES["file"]["size"]." ".$_FILES["file"]["error"],
);
$view = View::create();
$view->setFormat('json');
$view->setData($apiResponse);
return $this->get('fos_rest.view_handler')->handle($view);
}
The $apiResponse.message (screenshot):
As you can see symfony has the image so the problem don't come from my app mobile. new UploadedFile(); is the right way ? To upload without form.
Here is the solution :
Replace :
$photo->setFile = new UploadedFile(
$_FILES["file"]["tmp_name"],
$_FILES["file"]["name"],
$_FILES["file"]["type"],
$_FILES["file"]["size"],
$_FILES["file"]["error"],
$test = false
);
by
$photo->setFile($this->getRequest()->files->get('file'));

drupal 7 modify taxonomy page with hook_alter_menu

i want to change or modify all taxonomy pages i write this piece of code in template.php in my bartik theme but some weird things happens.
the $term argument in second function "bartik_term_page" is null.
what is missing?
and it sometimes an error like this
it gives an error.
Warning: Parameter 1 to bartik_term_page() expected to be a reference, value given in menu_execute_active_handler() (line path\includes\menu.inc).
function bartik_menu_alter(&$menu) {
$menu['taxonomy/term/%']['page callback'] = 'bartik_term_page';
$menu['taxonomy/term/%']['access arguments'] = array('access content');
}
function bartik_term_page(&$term){
$voc = taxonomy_vocabulary_load($term->vid);
var_dump( $term ); die();
// here you generate the actual content of the page
// could be done e.g. with an entityfieldquery as follows
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->fieldCondition('field_category', 'tid', $term->tid);
$result = $query->execute();
if (!empty($result['node'])) {
$build['content']['nodes'] = node_view_multiple(node_load_multiple(array_keys($result['node'])), 'teaser'); // output the node teasers. you can control the markup of the 'teaser' view mode with a template in the theme folder
} else {
$build['content']['status']['#markup'] = t('No results found for term ID !tid.', array('!tid' => $term->tid));
}
return $build;
}
You're actually introducing a new router item there instead of overriding the existing one.
The path for the taxonomy page is taxonomy/term/%taxonomy_term, so...
function bartik_menu_alter(&$menu) {
$menu['taxonomy/term/%taxonomy_term']['page callback'] = 'bartik_term_page';
$menu['taxonomy/term/%taxonomy_term']['access arguments'] = array('access content');
}
Clear caches and you should be good to go.
Add the following line after the 'page callback' line in your bartik_menu_alter() function:
$menu['taxonomy/term/%']['page arguments'] = array(3);
This tells Drupal where to find the parameter in your URL (it's the third component).

Silverstripe 3 -Multiple Gridfields on one Page

i want to add multiple gridfields to one pagetype.
At the moment I'm doing it like this
$gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(),
new GridFieldAddNewButton('toolbar-header-right'),
new GridFieldSortableHeader(),
new GridFieldDataColumns(),
new GridFieldPaginator(10),
new GridFieldEditButton(),
new GridFieldDeleteAction(),
new GridFieldDetailForm()
);
$sliderField = new GridField('Slides', 'Slider', $this->Slides(), $gridFieldConfig);
$fields->addFieldToTab('Root.Slider', $sliderField);
$categoryField = new GridField('ShopCategories', 'Kategorien', $this->ShopCategories(), $gridFieldConfig);
$fields->addFieldToTab('Root.Shop Kategorien', $categoryField);
It works but the problem is that i got the same "add blablabla object" title for both.
How can i fix this without using multiple gridFieldConfigs?
Thx in Advance
It seems that if you use the same config, the details are shared by both. However, there are a few default configs set-up you could use instead.
GridFieldConfig_RelationEditor
GridFieldConfig_RecordEditor
GridFieldConfig_RecordViewer
GridFieldConfig_Base
All of which extend the gridfield config.
So you could do this, for instance:
$sliderField = new GridField(
'Slides',
'Slider',
$this->Slides(),
GridFieldConfig_RelationEditor::create()
);
If you wish to create your own custom config you can write a class that extends GridFieldConfig in the same manner:
class GridFieldConfig_Custom extends GridFieldConfig {
/**
*
* #param int $itemsPerPage - How many items per page should show up
*/
public function __construct($itemsPerPage=null) {
$this->addComponent(new GridFieldToolbarHeader());
$this->addComponent(new GridFieldAddNewButton('toolbar-header-right'));
$this->addComponent(new GridFieldSortableHeader());
$this->addComponent(new GridFieldDataColumns());
$this->addComponent(new GridFieldPaginator(10));
$this->addComponent(new GridFieldEditButton());
$this->addComponent(new GridFieldDeleteAction());
$this->addComponent(new GridFieldDetailForm());
}
}
And then:
$sliderField = new GridField(
'Slides',
'Slider',
$this->Slides(),
GridFieldConfig_Custom::create());
$categoryField = new GridField(
'ShopCategories',
'Kategorien',
$this->ShopCategories(),
GridFieldConfig_Custom::create());
the problem is that the config object is tied to the gridfield as soon as you add it.
that means that you need 2 config objects, currently you only have one.
you can either create a second one, or clone the first one:
$gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(),
new GridFieldAddNewButton('toolbar-header-right'),
new GridFieldSortableHeader(),
new GridFieldDataColumns(),
new GridFieldPaginator(10),
new GridFieldEditButton(),
new GridFieldDeleteAction(),
new GridFieldDetailForm()
);
$gridFieldConfig2 = clone $gridFieldConfig;
$sliderField = new GridField('Slides', 'Slider', $this->Slides(), $gridFieldConfig);
$fields->addFieldToTab('Root.Slider', $sliderField);
$categoryField = new GridField('ShopCategories', 'Kategorien', $this->ShopCategories(), $gridFieldConfig2);
$fields->addFieldToTab('Root.Shop Kategorien', $categoryField);

SilverStripe GridField: too many versions of DataObject get created

TL;DR When creating/saving a versioned DataObject with relation to some page, two entries are created in the corresponding versions table (instead of one).
I'm trying to version some DataObject and have the Versioned extension applied as follows:
class Testobject extends DataObject {
static $has_one = array(
'Page' => 'Page'
);
static $extensions = array(
"Versioned('Stage', 'Live')",
);
Testobjects are being managed in a GridField on some page like so:
class PageContent extends Page {
public static $has_many = array(
"Testobjects" => "TestObject"
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$config = GridFieldConfig_RelationEditor::create();
$gridField = new GridField(
'Testobjects',
'Testobject',
$this->Testobjects(),
$config);
$fields->addFieldToTab('Root.Main', $gridField);
}
Now, whenever i add or save some Testobject in the GridField's EditForm, two new entries show up in the Testobject_versions table. For comparsion, when i save a page in the SiteTree, only one entry in the corresponding versions table is created.
As there will we thousands of these DataObjects on a page, i'm worried about this duplication filling up my database. Is there a way to get around this?
Further recognitions:
On creation of a new Testobject, the first entry in the versions table has it's PageID field set to 0, the second entry has set the actual PageID of the corresponding page.
If I replace $this->Testobjects() in the GridField construction by Testobject::get(), only one entry shows up in the versions table.
onBeforeWrite is called twice when using $this->Testobjects()
So it seems setting the relation to the page happens after a first 'write()', then another 'write()' is called. But where in the code does this happen?
If you're editing your page/testobject in the main section of the CMS (# '/admin/pages'), you can try this somewhat hackish trick in your TestObject class
public function getCMSFields(){
$fields = parent::getCMSFields();
$fields->push( new HiddenField('PageID','PageID', Controller::curr()->CurrentPageID());
return $fields;
}
This is not ideal for the following reasons:
hard to test with unit test controller
awareness of the controller in the model is bad
IMHO
But it can be a reasonable fix if it works for you

Resources