Extending the SilverStripe File class for Video - silverstripe

I am trying to extend the File/Image class to recognize .mp4 files as Video class rather than as File class.
My code is:
VideoExtension.php
class VideoExtension extends DataExtension
{
private static $db = array(
'IsAnimation' => 'Boolean',
'AssociatedStaticPage' => 'Text',
'BarCode' => 'Text'
);
public function updateCMSFields(FieldList $fields)
{
$fields->addFieldToTab('Root.Main', TextField::create('BarCode', 'Bar Code'));
$fields->addFieldToTab('Root.Main', TextField::create('AssociatedStaticPage', 'URL'));
}
}
mysite/_config/config.yml
Name: mysite
After:
- 'framework/*'
- 'cms/*'
---
# YAML configuration for SilverStripe
# See http://doc.silverstripe.org/framework/en/topics/configuration
# Caution: Indentation through two spaces, not tabs
SSViewer:
theme: 'simple'
File:
extensions:
- VideoExtension
With this I get an error. If I change File to Image in the config.yml it works. I want this so I can add custom fields in the Admin section.
Any help is appreciated.

I believe you want to create a class that extends File instead of creating a DataExtension. Something like the following:
class Video extends File {
private static $allowed_extensions = array(
'mpeg', 'mpg', 'mp4', 'm1v', 'mp2', 'mpa', 'mpe', 'ifo',
'vob','avi', 'wmv', 'asf', 'm2v', 'qt', 'ogv', 'webm'
);
private static $db = array(
'IsAnimation' => 'Boolean',
'AssociatedStaticPage' => 'Text',
'BarCode' => 'Text'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', TextField::create('BarCode', 'Bar Code'));
$fields->addFieldToTab('Root.Main', TextField::create('AssociatedStaticPage', 'URL'));
return $fields;
}
}
We then need to set this class to be used for these file extensions by setting the File class_for_file_extension. We can do this is in our mysite/_config/config.yml file:
File:
class_for_file_extension:
'mpeg': 'Video'
'mpg': 'Video'
'mp4': 'Video'
'm1v': 'Video'
'mp2': 'Video'
'mpa': 'Video'
'mpe': 'Video'
'ifo': 'Video'
'vob': 'Video'
'avi': 'Video'
'wmv': 'Video'
'asf': 'Video'
'm2v': 'Video'
'qt': 'Video'
'ogv': 'Video'
'webm': 'Video'

Related

Zend Framework 3 Form Fieldset

Hy,
I'm really new to Zend-Framework 3 and I'm practicing OOP, I can't find a simple explanation/tutorial on making a Zend Form with a fieldset and legend. Basically I'm trying to create this in HTML:
<form name="my_name">
<fieldset>
<legend>My legend value</legend>
<input type="checkbox" name="name_1" value="value_1">Value 1</input>
<input type="checkbox" name="name_2" value="value_2">Value_2</input>
<input type="checkbox" name="name_3" value="value_3">Value_3</input>
</fieldset>
<input type="button" value="Get values" id="btn"/>
</form>
I checked the official documentation about Zend Forms and Collections and Fieldsets, but it's really confusing me. Any help would be greatly appreciated.
First, I am sorry as it is going to be a bit long one. But this would describe the form in action. So be patient please!
Assuming you are known to ZF3 default Application module. Some folders are created in the Application module for separation of each element. You need to create them as follows.
Let's get started by creating your fieldsets first. Zend\Form\Fieldset component represents a reusable set of elements and is dependent on Zend\From\Form component. This means you need to attach this to Zend\Form\Form.
module/Application/src/Form/Fieldset/YourFieldset.php
<?php
namespace Application\Form\Fieldset;
use Zend\Form\Element;
use Zend\Form\Fieldset;
class YourFieldset extends Fieldset
{
public function __construct($name = null)
{
parent::__construct('your-fieldset');
$this->add([
'name' => 'name_1',
'type' => Element\Checkbox::class,
'options' => [
'label' => 'Value 1',
'use_hidden_element' => true,
'checked_value' => 'yes',
'unchecked_value' => 'no',
],
'attributes' => [
'value' => 'no',
],
]);
// Creates others as your needs
}
}
Now we would create the form using Zend\From\Form attaching the fieldset created from Zend\From\Fieldset.
module/Application/src/Form/YourForm.php
<?php
namespace Application\Form;
use Application\Form\Fieldset\YourFieldset;
use Zend\Form\Form;
class YourForm extends Form
{
public function __construct($name = null)
{
parent::__construct('your-form');
$this->add([
// This name will be used to fetch each checkbox from
// the CheckboxFieldset::class in the view template.
'name' => 'fieldsets',
'type' => YourFieldset::class
]);
$this->add([
'name' => 'submit',
'attributes' => [
'type' => 'submit',
'value' => 'Get Values',
'class' => 'btn btn-primary'
],
]);
}
}
Our from is almost ready. We need to make it serviceable if we want it to be used in any action of a controller. So let's do that.
Update your module config file. If service_manager key does not exist then add the following snippet of code, otherwise, update only factories and aliases key as the following.
Fix namespaces in module config file.
module/Application/config/module.config.php
'service_manager' => [
'factories' => [
// Form service
Form\YourForm::class => Zend\ServiceManager\Factory\InvokableFactory::class,
// Other services
],
'aliases' => [
// Make an alias for the form service
'YourForm' => Form\YourForm::class,
],
],
Now the form is ready to be used. This needs to be injected into our controller. As I am working on Application module, I would inject the form into the IndexController::class's constructor. Then we would be using that form inside IndexController::fieldsetAction() method.
module/Application/src/Controller/IndexController.php
<?php
namespace Application\Controller;
use Zend\Form\FormInterface;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
protected $YourForm;
public function __construct(FormInterface $YourForm)
{
$this->YourForm = $YourForm;
}
public function fieldsetAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel(['form' => $this->YourForm]);
if (! $request->isPost()) {
return $viewModel;
}
$this->YourForm->setData($request->getPost());
if (! $this->YourForm->isValid()) {
return $viewModel;
}
$data = $this->YourForm->getData()['fieldsets'];
echo '<pre>';
print_r($data);
echo '</pre>';
return $viewModel;
}
}
As this controller is taking argument in its constructor, we need to create a factory for this controller (a factory creates other objects).
module/Application/src/Factory/Controller/IndexControllerFactory.php
<?php
namespace Application\Factory\Controller;
use Application\Controller\IndexController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// We get form service via service manager here
// and then inject controller's constructor
$YourForm = $container->get('YourForm');
return new IndexController($YourForm);
}
}
Once again, we need to update the module config file. We would add this time the factory under controllers key as follows
'controllers' => [
'factories' => [
Controller\IndexController::class => Factory\Controller\IndexControllerFactory::class,
],
],
At the end, echo the form in the view template as follows:
module/Application/view/application/index/fieldset.phtml
<h1>Checkbox Form</h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url());
// Here is the catch, remember this name from the CheckboxForm::class
$fieldset = $form->get('fieldsets');
$name_1 = $fieldset->get('name_1');
$name_2 = $fieldset->get('name_2');
$name_3 = $fieldset->get('name_3');
$submit = $form->get('submit');
$submit->setAttribute('class', 'btn btn-primary');
$form->prepare();
echo $this->form()->openTag($form);
?>
<fieldset>
<legend>My legend value</legend>
<?= $this->formElement($name_1) ?>
<?= $this->formLabel($name_1) ?>
<?= $this->formElement($name_2) ?>
<?= $this->formLabel($name_2) ?>
<?= $this->formElement($name_3) ?>
<?= $this->formLabel($name_3) ?>
<?= $this->formSubmit($submit) ?>
</fieldset>
<?php
echo $this->form()->closeTag();
Hope this would help you!
Actually the example you are looking for is in "collections" part of zend form. Its not the exact one but kinda like.
Here you are a little example. I ignored namespaces and hope so there's no typo :)
class myFieldset extends Fieldset {
public function init(){
$this
->add([
'name' => 'name_1,
'type' => 'text',
])
->add([
'name' => 'name_2,
'type' => 'text',
])
->add([
'name' => 'name_3,
'type' => 'text',
]);
}
}
class MyForm extends Form {
public function init(){
$this->add([
'type' => myFieldset,
'name' => 'fieldset'
])->add([
'type' => 'button',
'name' => 'action'
]);
}
}
And in view file;
<?=$this-form($form);?>

Drupal 8 Twig removes all style tags from variable during rendering

How to retain all content of a variable which was added during preprocess_page.
e.g. style tags also needs to be added while variable rendering in twig files.
class MaisexpertBlock extends BlockBase {
public function build() {
return array(
//'#cache' => array('max-age' => 0),
'#type' => 'inline_template',
'#template' => '{{ somecontent | raw }}',
'#context' => array('somecontent' => 'Your content with <html></html> code'),
);
}
}

How to wrap field in custom markup?

Situation
I have a custom module that is using hook_field_formatter_info() to add an "fancy" option to the image field in the manage display of a content type. When this option is chosen I want to be able to surround the ENTIRE field in custom divs and markup. I want the solution to be a hook in my custom module and not a template override.
Process
A user wants the display of an image field to be the "fancy" option. They check it in the drop down and click save from the content types Manage Display admin page. Now on that content type node there should be custom markup surrounding the entire field even if there are multiple images, the new markup should surround ALL the images and not each individual image.
hook_field_formatter_view
hook_field_formatter_view seems to demand it's output be an array and I can't seem to be able to wrap the output in a div.
Template overrides
I can't just make a field.tpl.php for the specific field because like I initially mentioned I need to be able to switch themes and the module still work like normal. Unless there is a way to get my module to override any field where said field has hook_field_formatter_info() set specifically.
/**
* Implements hook_field_formatter_view().
*/
function bootstrap_modal_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
foreach ($items as $delta => $item) {
if ($index === NULL || $index === $delta) {
$element[$delta] = array(
'#theme' => 'bootstrap_modal_image_formatter',
'#item' => $item,
'#entity_type' => $entity_type,
'#entity' => $entity,
'#node' => $entity, // Left for legacy support.
'#field' => $field,
'#display_settings' => $display['settings'],
'#delta' => $delta,
);
}
}
// $element = '<div id="CUSTOMDIVSTUFF">' . $element . '</div>';
return $element;
}
And here is the #theme function:
function theme_bootstrap_modal_image_formatter($variables) {
$item = $variables['item'];
$entity_type = $variables['entity_type'];
$entity = $variables['entity'];
$field = $variables['field'];
$settings = $variables['display_settings'];
$image = array(
'path' => $item['uri'],
'alt' => isset($item['alt']) ? $item['alt'] : '',
'title' => isset($item['title']) ? $item['title'] : '',
'style_name' => $settings['bootstrap_modal_node_style'],
);
if (isset($item['width']) && isset($item['height'])) {
$image['width'] = $item['width'];
$image['height'] = $item['height'];
}
if (isset($item['attributes'])) {
$image['attributes'] = $item['attributes'];
}
// Allow image attributes to be overridden.
if (isset($variables['item']['override']['attributes'])) {
foreach (array('width', 'height', 'alt', 'title') as $key) {
if (isset($variables['item']['override']['attributes'][$key])) {
$image[$key] = $variables['item']['override']['attributes'][$key];
unset($variables['item']['override']['attributes'][$key]);
}
}
if (isset($image['attributes'])) {
$image['attributes'] = $variables['item']['override']['attributes'] + $image['attributes'];
}
else {
$image['attributes'] = $variables['item']['override']['attributes'];
}
}
$entity_title = entity_label($entity_type, $entity);
if ($style_name = $settings['bootstrap_modal_image_style']) {
$path = image_style_url($style_name, $image['path']);
}
else {
$path = file_create_url($image['path']);
}
$caption = 'some value';
$gallery_id = 'some value';
return theme('bootstrap_modal_imagefield', array('image' => $image, 'path' => $path, 'title' => $caption, 'gid' => $gallery_id));
}
Been working on this for days, I'm drowning here.
This is possible via HOOK_process_field(). Use this hook to define a new template file for your field by adding it to theme_hook_suggestions array (place the template file in your module directory, because you wanted to change the theme -as you mentioned-). More info about field template suggestions.
Then, you will need to add the module path to drupal theme registry, so it picks up the template file. Demo.
I found out it was:
function bootstrap_modal_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array(
'#prefix' => '<div class="wrapper">',
'#suffix' => '</div>',
);

extend wordpress core class in functions.php

I am trying to extend a wordpress core class inside my theme's functions.php, & the class I am trying to extend is WP_Customize_Image_Control from class wp-customize-control.php in wp-includes.
It already extends "WP_Customize_Upload_Control".
I would like to allow the .svg mime-type to be uploaded within the theme customizer.
in my theme's functions.php I am adding these lines:
class WP_Customize_Image_Control_SVG extends WP_Customize_Image_Control {
public $extensions = array( 'jpg', 'jpeg', 'gif', 'png', 'svg' );
};
but sadly this breaks everything.
Any help, hints or tips appreciated.
You are close.
/* Extend the Image Control */
class WP_Customize_Image_Control_SVG extends WP_Customize_Image_Control
{
public function __construct( $manager, $id, $args = array() )
{
parent::__construct( $manager, $id, $args );
$this->remove_tab('uploaded');
$this->extensions = array( 'jpg', 'jpeg', 'gif', 'png', 'svg' );
}
}
This goes inside your "customize_register" action
Just make sure you're registering this one instead of the normal image control.

Silverstripe 3: has_one image in Widget error

I'm creating a few widgets for a project I'm working on and it seems widgets do not have access to any of the other classes from outside the widget. I've tried adding a has_one static for both image and SiteTree classes (see example below for image example) and I am getting the same error when I try and add the cms field: Fatal error: Call to a member function FormAction() on a non-object in /..../sapphire/forms/FormField.php on line 139
<?php
class AdBoxWidget extends Widget{
static $title = "";
static $cmsTitle = "Ad Box Widget";
static $description = "Ad Box widget. To add an image, Title and Link";
static $db = array(
"Title" => "Text",
"Link" => "Text",
"AdLinkText" => "Text"
);
static $defaults = array(
"Title" => 'Ad Title',
"Link" => 'http://',
"AdLinkText" => 'Click here for more info',
);
static $has_one = array(
'AdImage' => 'Image'
);
function getCMSFields(){
return new FieldList(
new TextField("Title", "Ad Title"),
new TextField("Link", "Ad Link"),
new TextField("AdLinkText", "Text for Link"),
new UploadField("AdImage", "Ad image")
);
}
function getAd(){
$output = new ArrayList();
$output->push(
new ArrayData(
array(
"Title" => $this->Title,
"Link" => $this->Link,
"AdLinkText" => $this->AdLinkText
)
)
);
return $output;
}
}
To prevent a situation like this you could make a DataObject out of one Ad.
Provide a ModelAdmin to edit the Ad DataObjects.
In your widget you could just have a has_one with a DropDownField to select the ad for the widget.
This wont solve the actual problem with the widget module but it works around.

Resources