How to automaticly publish images in silverstripe dataextension - php

I was trying to add an uploadfield to a Custom DataExtension and got the Image field working. However the image i uploaded stays in concept mode, and i have to go to the File tab to publish it. I tried to use the code provided in the Silverstripe documentation but this only seems to work on regular pages. I found a question similar to mine:How to automaticaly publish files uploaded to a dataobject in Silverstripe model admin however this only seems to work on DataObjects.
This is my current code:
<?php
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Assets\Image;
use SilverStripe\Assets\Storage\AssetStore;
use SilverStripe\Versioned\Versioned;
use SilverStripe\ORM\DataExtension;
class CustomSiteConfig extends DataExtension
{
private static $db = [
];
private static $has_one = [
'Logo' => Image::class
];
private static $owns = [
'Logo'
];
private static $extensions = [
Versioned::class,
];
private static $versioned_gridfield_extensions = true;
public function updateCMSFields(FieldList $fields)
{
$fields->addFieldToTab("Root.Header", LiteralField::create("","<h1>Header</h1>"));
$fields->addFieldToTab("Root.Header", UploadField::create('Logo', 'Logo'));
}
}
Does anyone know a solution?

There's currently a bug that prevents "owned" records to be published if the owning dataobject is not versioned.
I think you're experience this bug, since SiteConfig is not versioned and thus won't publish owned files/images when it's being saved.
Until this bug has been resolved, you could use an onAfterWrite hook in your extension to publish the file:
public function onAfterWrite()
{
if ($this->owner->LogoID) {
$this->owner->Logo()->publishSingle();
}
}

Related

Extending Blog Module on Silverstripe

I'm about to extend Silverstripe Module. But I can't figure out what is missing on my simple code.
I need some suggestion to solve what is missing.
namespace {
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
class BlogPostExtension extends DataExtension {
private static $db = [
'Title' => 'Varchar'
];
public function updateCMSFields(FieldList $fields) {
// Add fields here
$fields->addFieldToTab("Root.Gallery", new TextField("Title","Title"));
}
}
}
This what I've added on app.yml. I also doing /dev/build?flush=all. But still nothing works.
SilverStripe\Blog\BlogPost:
extensions:
- Project\Extensions\BlogPostExtension
as wmk pointed out - Title is already part of the fields in the FieldList. If you rename the field to a different name. For example "GalleryTitle" and run dev/build you should have more success.
-- Peter

Unable to upload files in SilverStripe 4

I've created a simple extension to SiteConfig to add a logo uploadfield to the settings section. However, the server returns an error upon uploading a file.
SiteConfig.php
namespace mymodule\siteconfig;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
use SilverStripe\AssetAdmin\Forms\UploadField;
class SiteConfig extends DataExtension {
private static $has_one = array(
'Logo' => 'SilverStripe\\Assets\\File'
);
public function updateCMSFields(FieldList $fields) {
$fields->addFieldToTab('Root.Main', $logo = UploadField::create('Logo', 'Logo upload'));
}
}
Server's error log does not show anything relevant to this error. Whats going on here?
UPDATE
I just tried to upload a file to the Files section in the CMS, got the exact same error.
private static $has_one = [
'LogoImage' => Image::class,
];
public function updateCMSFields(FieldList $fields) {
$fields->addFieldToTab('Root.Main', UploadField::create('LogoImage', 'Logo'));
}

Extending File: can't add field to Root.Main

I want to add a Tag field to all Files in a SilverStripe 3.3.1 site. I'm using Blog v2.4.0 and have upgraded tagfield to v1.2.1.
My FileExtension is configured to extend File:
class FileExtension extends DataExtension
{
private static $many_many = ['FileTags' => 'FileTag'];
public function updateCMSFields(FieldList $fields)
{
$tagField = TagField::create('FileTags', 'Tags', FileTag::get(), $this->owner->FileTags())
->setShouldLazyLoad(true)
->setCanCreate(true);
$fields->push($tagField);
}
}
The FileTag class is:
class FileTag extends DataObject
{
private static $db = ['Title' => 'Varchar(255)'];
private static $belongs_many_many = ['Files' => 'File'];
}
The extension hook I'm attaching to is here, and it provides a standard FieldList as described in the extension documentation.
The problem!
The field shows up correctly, but it's outside of the Root.Main tab and looks like this:
I've tried:
Using addFieldToTab('Root.Main', $field) - it results in [User Error] FieldList::addFieldToTab() Tried to add a tab to object 'FieldList' - 'Root' didn't exist.
As above, using Root and Main
Why doesn't this work the way it is supposed to?
The problem is Folder is a type of file, but Folder does not have a Root.Main tab in its CMS FieldList.
When adding fields to File we need to check that the File type is not Folder:
class FileExtension extends DataExtension {
public function updateCMSFields(FieldList $fields) {
if (!$this->owner instanceof Folder) {
$tagField = TagField::create('FileTags', 'Tags', FileTag::get(), $this->owner->FileTags())
->setShouldLazyLoad(true)
->setCanCreate(true);
$fields->addFieldToTab('Root.Main', $tagField);
}
}
}

Changing widget assets path at runtime

I have a widget that uses assets. The asset look like this:
class publicHeaderNavbarAsset extends AssetBundle {
public $sourcePath = '#app/components/#device';
public $css = [
'styles.css'
];
public $js = [];
public $depends = [];
}
I also have a (bootstrapped) component, defined like that:
class Aliases extends Component {
public function init() {
Yii::setAlias('#device', Utils::device());
}
}
Utils::device() is a function that parses the UA of the device and returns mobile, tablet or desktop, depending on the device type.
The problem is that Yii2 doesn't seem to be converting #device to the value it has. I first thought that it could be my fault, but then I changed the sourcePath to:
public $sourcePath = '#app/components/#app';
just to see if that will trigger an error with a duplicated path (basepath/componenets/basepath), but it didn't.
Is there a way I can change the sourcePath of my asset at runtime? Or maybe make Yii2 parse all the aliases in sourcePath?
Look at the getAlias function http://www.getyii.com/doc-2.0/api/yii-baseyii.html#getAlias()-detail
It will basically not match your second alias in the string you have given it.
You can try setting
Yii::setAlias('#device', '#app/components/' . Utils::device());
and
public $sourcePath = '#device';
This should work as you should be able to set an alias based on another alias
http://www.yiiframework.com/doc-2.0/guide-concept-aliases.html#defining-aliases

How do I manage assets in Yii2?

For example, I created a new page, and I'd like to use, for example, backbone.js, custom css file and some collection of images. Where should I declare all this stuff in Yii2? I found the AppAsset.php module, but this is only for css/js files and I haven't noticed any changes when my css/js files and path were declared there:
class AppAsset extends AssetBundle {
public $basePath = '#webroot';
public $baseUrl = '#web';
public $css = [
'css/site.css',
'js/jquery.mobile-1.4.2.min.css',
];
public $js = [
'js/jsquery-2.1.0.min.js',
'js/jquery.mobile-1.4.2.min.js',
'js/script.js',
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
What am I doing wrong?
It took me a while to figure it out, but below is the relevant part of the Yii2 source code
if ($this->sourcePath !== null && !isset($this->basePath, $this->baseUrl)) {
list ($this->basePath, $this->baseUrl) = $am->publish($this->sourcePath, $this->publishOptions);
}
So Yii2 will publish assets only if $sourcePath is set, and $basePath and $baseUrl are not set(!). The latter tripped me up, and it looks like the same goes for you.
So I have this AppAsset, which duly publishes
use yii\web\AssetBundle;
class AppAsset extends AssetBundle
{
public $sourcePath = '#app/assets/app';
public $css = [
'css/openbook.css',
'fontello/css/fontello.css',
'fontello/css/animation.css'
];
public $js = [
'js/plug.openbook.js',
'js/plug.interpret.js',
'js/plug.drop.message.js'
];
public $depends = [
// 'yii\web\YiiAsset',
// 'yii\bootstrap\BootstrapAsset',
];
}
Of course, I have in the main layout
use frontend\assets\AppAsset;
...
AppAsset::register($this);
to use this AppAsset or any other you should register it in the view
use app\assets\AppAsset;
AppAsset::register($this);
At first, you should create SomeAsset class in your app/assets/ folder with your new js and css files.
You can extend your AppAsset overloading its properties.
Next use this in SomeController
use Yii;
use app\assets\SomeAsset;
and in actionSome like this:
SomeAsset::register(Yii::$app->view);
From personal experience, assets are one of the parts of Yii that I found extremely frustrating.
It is hard to reliably find out where the file is going to be and the switching back and forth with debug mode on and off will create further frustration.
I suggest scrapping the asset handling and just keep all your JS files in a folder, then it can be included like this:
Yii::app()->clientScript->registerScriptFile('/js/jquery.jeditable.mini.js');

Categories