Skip to content
This repository has been archived by the owner on Jan 10, 2021. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: nglasl/silverstripe-mediawesome
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.0.1
Choose a base ref
...
head repository: nglasl/silverstripe-mediawesome
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Feb 5, 2015

  1. 1
    Copy the full SHA
    7bb4f21 View commit details
  2. Updated the current release.

    Nathan Glasl committed Feb 5, 2015
    Copy the full SHA
    712a4f8 View commit details

Commits on Feb 17, 2015

  1. Copy the full SHA
    78a8026 View commit details
  2. Updated the current release.

    Nathan Glasl committed Feb 17, 2015
    Copy the full SHA
    37ec74e View commit details

Commits on Feb 19, 2015

  1. Minor updates to notification CSS.

    Nathan Glasl committed Feb 19, 2015
    Copy the full SHA
    a548a43 View commit details
  2. Updating the documentation with the packagist reference.

    Nathan Glasl committed Feb 19, 2015
    Copy the full SHA
    9e12464 View commit details

Commits on Mar 20, 2015

  1. Minor tweaks to templating, allowing for extension.

    Nathan Glasl committed Mar 20, 2015
    Copy the full SHA
    79d0e9f View commit details

Commits on Mar 23, 2015

  1. Updates to the data object management interface, and implementation o…

    …f a media category.
    Nathan Glasl committed Mar 23, 2015
    Copy the full SHA
    daaabab View commit details
  2. Updating a comment.

    Nathan Glasl committed Mar 23, 2015
    Copy the full SHA
    4de5af6 View commit details
  3. Updating the media holder filters to support categories.

    Nathan Glasl committed Mar 23, 2015
    Copy the full SHA
    36e82bf View commit details

Commits on Mar 24, 2015

  1. Updating a media holder to allow category and tag filtering at the sa…

    …me time.
    Nathan Glasl committed Mar 24, 2015
    Copy the full SHA
    314f89a View commit details
  2. Copy the full SHA
    3f4d800 View commit details
  3. Minor update to class definitions.

    Nathan Glasl committed Mar 24, 2015
    Copy the full SHA
    22dec8c View commit details
  4. Updating the current release.

    Nathan Glasl committed Mar 24, 2015
    Copy the full SHA
    d94e7ce View commit details

Commits on Mar 25, 2015

  1. Updated the documentation to reflect the latest changes.

    Nathan Glasl committed Mar 25, 2015
    Copy the full SHA
    49b35cb View commit details

Commits on Apr 20, 2015

  1. Cleaning up a class definition.

    Nathan Glasl committed Apr 20, 2015
    Copy the full SHA
    a114bb5 View commit details
  2. Updating the current release.

    Nathan Glasl committed Apr 20, 2015
    Copy the full SHA
    aab68e2 View commit details

Commits on Apr 28, 2015

  1. Copy the full SHA
    094d8c2 View commit details
  2. Updating class definitions and correcting some issues.

    Nathan Glasl committed Apr 28, 2015
    Copy the full SHA
    ec97e62 View commit details
  3. Updating class definitions and correcting some issues.

    Nathan Glasl committed Apr 28, 2015
    Copy the full SHA
    f790712 View commit details
  4. Corrected an issue regarding updated media page URLs.

    Nathan Glasl committed Apr 28, 2015
    Copy the full SHA
    1088326 View commit details
  5. Corrected an issue regarding updated media page URLs.

    Nathan Glasl committed Apr 28, 2015
    Copy the full SHA
    d6bd789 View commit details

Commits on Apr 29, 2015

  1. Updating class definitions.

    Nathan Glasl committed Apr 29, 2015
    Copy the full SHA
    7f03640 View commit details
  2. Implemented validation around media page URL segments, otherwise they…

    … may conflict with formatting.
    Nathan Glasl committed Apr 29, 2015
    Copy the full SHA
    99dab59 View commit details
  3. Improvements to URL formatting performance.

    Nathan Glasl committed Apr 29, 2015
    Copy the full SHA
    b8022e0 View commit details
  4. Updating the branch alias and documentation to reflect the latest rel…

    …ease.
    Nathan Glasl committed Apr 29, 2015
    Copy the full SHA
    4826651 View commit details
  5. Minor update to the documentation.

    Nathan Glasl committed Apr 29, 2015
    Copy the full SHA
    08a0f65 View commit details

Commits on Apr 30, 2015

  1. Improvements to URL formatting performance.

    Nathan Glasl committed Apr 30, 2015
    Copy the full SHA
    84d84d8 View commit details

Commits on May 1, 2015

  1. Copy the full SHA
    9a49489 View commit details

Commits on May 22, 2015

  1. Minor consistency updates.

    Nathan Glasl committed May 22, 2015
    Copy the full SHA
    adf760e View commit details

Commits on May 25, 2015

  1. Updating some class definitions.

    Nathan Glasl committed May 25, 2015
    Copy the full SHA
    2f91b7f View commit details

Commits on Jun 4, 2015

  1. Copy the full SHA
    bda217e View commit details
  2. Copy the full SHA
    d43ef69 View commit details

Commits on Jul 7, 2015

  1. Copy the full SHA
    19d4265 View commit details
  2. Copy the full SHA
    bbd946f View commit details

Commits on Jul 9, 2015

  1. Refactoring any validation.

    Nathan Glasl committed Jul 9, 2015
    Copy the full SHA
    141090f View commit details
  2. Refactoring any validation.

    Nathan Glasl committed Jul 9, 2015
    Copy the full SHA
    f3c7b31 View commit details
  3. Copy the full SHA
    0258e6c View commit details
  4. Copy the full SHA
    1b2a5d3 View commit details

Commits on Jul 12, 2015

  1. Updating the documentation images.

    Nathan Glasl committed Jul 12, 2015
    Copy the full SHA
    a7d6e7a View commit details
  2. Updating the documentation images.

    Nathan Glasl committed Jul 12, 2015
    Copy the full SHA
    adc4a99 View commit details
  3. Updating the documentation images.

    Nathan Glasl committed Jul 12, 2015
    Copy the full SHA
    99ad1aa View commit details
  4. Updating the documentation images.

    Nathan Glasl committed Jul 12, 2015
    Copy the full SHA
    b7638a6 View commit details
  5. Updating the documentation to reflect the latest release.

    Nathan Glasl committed Jul 12, 2015
    Copy the full SHA
    df2674c View commit details

Commits on Jul 15, 2015

  1. Updating the documentation images.

    Nathan Glasl committed Jul 15, 2015
    Copy the full SHA
    1e6e42f View commit details
  2. Updating the documentation to reflect the latest release.

    Nathan Glasl committed Jul 15, 2015
    Copy the full SHA
    01399a0 View commit details

Commits on Jul 16, 2015

  1. FIX Ensure parent exists when generating links

    Prevents issues when the parent node is null during link generation (eg
    generating live link where parent is still unpublished)
    Marcus Nyeholt committed Jul 16, 2015
    Copy the full SHA
    d9031fe View commit details

Commits on Jul 29, 2015

  1. Merge pull request #2 from nyeholt/master

    FIX Ensure parent exists when generating links
    Nathan committed Jul 29, 2015
    Copy the full SHA
    383046d View commit details
  2. Updating some minor class definitions.

    Nathan Glasl committed Jul 29, 2015
    Copy the full SHA
    e18fb54 View commit details
  3. Updating the documentation to reflect the latest release.

    Nathan Glasl committed Jul 29, 2015
    Copy the full SHA
    0258a06 View commit details
12 changes: 12 additions & 0 deletions .upgrade.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mappings:
MediaHolderController: 'nglasl\mediawesome\MediaHolderController'
MediaPageController: 'nglasl\mediawesome\MediaPageController'
SiteConfigMediaPermissionExtension: 'nglasl\mediawesome\SiteConfigMediaPermissionExtension'
MediaAttribute: 'nglasl\mediawesome\MediaAttribute'
MediaPageAttribute: 'nglasl\mediawesome\MediaPageAttribute'
MediaTag: 'nglasl\mediawesome\MediaTag'
MediaType: 'nglasl\mediawesome\MediaType'
MediaHolder: 'nglasl\mediawesome\MediaHolder'
MediaPage: 'nglasl\mediawesome\MediaPage'
MediawesomeFunctionalTests: 'nglasl\mediawesome\tests\FunctionalTests'
MediawesomeUnitTests: 'nglasl\mediawesome\tests\UnitTests'
88 changes: 50 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# [mediawesome](https://github.com/nglasl)
# [mediawesome](https://packagist.org/packages/nglasl/silverstripe-mediawesome)

_The current release is **1.0.1**_
_The current release is **4.0.6**_

A module for SilverStripe which will allow creation of dynamic media holders/pages
with CMS customisable types and attributes (blogs, events, news, publications).
> This module allows creation of dynamic media holders/pages with CMS customisable types and attributes (blogs, events, news, publications), including versioning.
## Requirement

* SilverStripe 3.1.X
* SilverStripe 3.1 → **4.0**

**This repository is no longer supported, however this module is still supported [here](https://github.com/symbiote/silverstripe-mediawesome).**

## Getting Started

* Place the module under your root project directory.
* [Place the module under your root project directory.](https://packagist.org/packages/nglasl/silverstripe-mediawesome)
* `/dev/build`
* Create a media holder.
* Configure the media type.
@@ -23,54 +24,61 @@ _The current release is **1.0.1**_

These are the default media types and their respective attributes.

```php
array(
'Blog' => array(
'Author'
),
'Event' => array(
'Start Time',
'End Time',
'Location'
),
'News' => array(
'Author'
),
'Publication' => array(
'Author'
)
);
```yaml
nglasl\mediawesome\MediaPage:
type_defaults:
Blog:
- 'Author'
Event:
- 'End Date'
- 'Time'
- 'End Time'
- 'Location'
News:
- 'Author'
Publication:
- 'Author'
```
Apply custom default media types with respective attributes, or additional attributes to existing default types.
Apply custom default media types and/or respective attributes.
```php
MediaPage::customise_defaults(array(
'Media Type' => array(
'Attribute'
)
));
```yaml
nglasl\mediawesome\MediaPage:
type_defaults:
Type:
- 'Attribute'
```
These may also be added through the CMS, depending on the current user permissions.
![types](https://raw.githubusercontent.com/nglasl/silverstripe-mediawesome/master/client/images/mediawesome-types.png)
* Select a media holder.
* Select `Media Types`
* Select `Manage ALL Media`
* Select `Types and Attributes`

### Dynamic Media Attributes

These may be customised through the CMS, depending on the current user permissions.

![attributes](https://raw.githubusercontent.com/nglasl/silverstripe-mediawesome/master/client/images/mediawesome-attributes.png)

* Select a media holder.
* Select `Media Types`
* Select `Manage ALL Media`
* Select `Types and Attributes`
* Select the respective type.

These will be applied to new and existing media pages of the respective type.
These attributes will appear on media pages of the respective type, and are versioned.

### Media Tags
![versioning](https://raw.githubusercontent.com/nglasl/silverstripe-mediawesome/master/client/images/mediawesome-attribute-versioning.png)

### Media Categories and Tags

![categories-and-tags](https://raw.githubusercontent.com/nglasl/silverstripe-mediawesome/master/client/images/mediawesome-categories-and-tags.png)

* Select a media holder.
* Select `Media Tags`
* Select `Manage ALL Media`
* Select `Categories and Tags`

### CMS Permissions

@@ -83,14 +91,18 @@ Customisation of media types and their respective attributes will be restricted.

### Filtering Media Pages

A media holder request may have optional date/tag filters, which are extendable by developers.
A media holder request may have optional date, category and tag filters, which are extendable by developers.

Retrieve the date filter form in the media holder template:
The following on the media holder template allows a user to select a date, and then see media pages for and prior to that date:

```php
$DateFilterForm
```

It is also possible to represent the date in a `year/month/day/media` URL format.

![URL-formatting](https://raw.githubusercontent.com/nglasl/silverstripe-mediawesome/master/client/images/mediawesome-URL-formatting.png)

### Smart Templating

Custom media type templates may be defined for your media holder/page:
@@ -109,4 +121,4 @@ To see examples, look at the default templates:

## Maintainer Contact

Nathan Glasl, nathan@silverstripe.com.au
Nathan Glasl, nathan@symbiote.com.au
32 changes: 0 additions & 32 deletions _config.php

This file was deleted.

8 changes: 4 additions & 4 deletions _config/extensions.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
name: mediawesome-extensions
---
SiteConfig:
nglasl\mediawesome\MediaPageAttribute:
extensions:
- 'SiteConfigMediaPermissionExtension'
Page:
- 'SilverStripe\Versioned\Versioned'
SilverStripe\SiteConfig\SiteConfig:
extensions:
- 'PageChildrenExtension'
- 'nglasl\mediawesome\SiteConfigMediaPermissionExtension'
7 changes: 7 additions & 0 deletions _config/routes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
name: mediawesome-routes
---
nglasl\mediawesome\MediaHolderController:
url_handlers:
'': 'index'
'$URL': 'handleURL'
16 changes: 16 additions & 0 deletions _config/types.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
name: mediawesome-types
---
nglasl\mediawesome\MediaPage:
type_defaults:
Blog:
- 'Author'
Event:
- 'End Date'
- 'Time'
- 'End Time'
- 'Location'
News:
- 'Author'
Publication:
- 'Author'
8 changes: 8 additions & 0 deletions _config/upgrade.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: mediawesome-upgrade
---
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
MediaTag: 'nglasl\mediawesome\MediaTag'
MediaType: 'nglasl\mediawesome\MediaType'
MediaHolder: 'nglasl\mediawesome\MediaHolder'
14 changes: 14 additions & 0 deletions client/css/mediawesome.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

/**
* The mediawesome specific styling.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

p.mediawesome.notification {
background: #FFA84C;
padding: 10px;
border: 1px solid #FF7400;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
File renamed without changes
Binary file added client/images/mediawesome-URL-formatting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/images/mediawesome-attributes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/images/mediawesome-categories-and-tags.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/images/mediawesome-types.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
229 changes: 0 additions & 229 deletions code/dataobjects/MediaAttribute.php

This file was deleted.

81 changes: 0 additions & 81 deletions code/dataobjects/MediaTag.php

This file was deleted.

209 changes: 0 additions & 209 deletions code/dataobjects/MediaType.php

This file was deleted.

18 changes: 0 additions & 18 deletions code/extensions/PageChildrenExtension.php

This file was deleted.

255 changes: 0 additions & 255 deletions code/pages/MediaHolder.php

This file was deleted.

351 changes: 0 additions & 351 deletions code/pages/MediaPage.php

This file was deleted.

29 changes: 21 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nglasl/silverstripe-mediawesome",
"description": "A module for SilverStripe which will allow creation of dynamic media holders/pages with CMS customisable types and attributes (blogs, events, news, publications).",
"type": "silverstripe-module",
"description": "This module allows creation of dynamic media holders/pages with CMS customisable types and attributes (blogs, events, news, publications), including versioning.",
"type": "silverstripe-vendormodule",
"keywords": [
"silverstripe",
"media",
@@ -14,16 +14,29 @@
"license": "BSD-3-Clause",
"authors": [{
"name": "Nathan Glasl",
"email": "nathan@silverstripe.com.au"
"email": "nathan@symbiote.com.au"
}],
"require": {
"silverstripe/cms": "3.1.*",
"silverstripe/framework": "3.1.*"
"silverstripe/cms": "~4.0",
"silverstripe/framework": "~4.0"
},
"autoload": {
"psr-4": {
"nglasl\\mediawesome\\": [
"src/controllers/",
"src/extensions/",
"src/objects/",
"src/pages/"
],
"nglasl\\mediawesome\\tests\\": "tests/"
}
},
"extra": {
"installer-name": "mediawesome",
"branch-alias": {
"dev-master": "1.0.x-dev"
}
"dev-master": "4.0.x-dev"
},
"expose": [
"client"
]
}
}
35 changes: 0 additions & 35 deletions css/mediawesome.css

This file was deleted.

500 changes: 500 additions & 0 deletions src/controllers/MediaHolderController.php

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions src/controllers/MediaPageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace nglasl\mediawesome;

/**
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class MediaPageController extends \PageController {

/**
* Determine the template for this media page.
*/

public function index() {

// Use a custom media type page template if one exists.

$type = $this->data()->MediaType();
$templates = array();
if($type->exists()) {
$templates[] = 'MediaPage_' . str_replace(' ', '', $type->Title);
}
$templates[] = 'MediaPage';
$templates[] = 'Page';
$this->extend('updateTemplates', $templates);
return $this->renderWith($templates);
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
<?php

namespace nglasl\mediawesome;

use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\OptionsetField;
use SilverStripe\Forms\ReadonlyField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Security\Permission;

/**
* Mediawesome extension which allows permission configuration for customisation of media.
* @author Nathan Glasl <nathan@silverstripe.com.au>
* This allows permission configuration for customisation of media.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class SiteConfigMediaPermissionExtension extends DataExtension {
@@ -25,7 +33,6 @@ public function updateCMSFields(FieldList $fields) {
'ADMIN' => 'Administrators and developers',
'SITETREE_EDIT_ALL' => 'Content authors'
);
Requirements::css(MEDIAWESOME_PATH . '/css/mediawesome.css');

// Confirm that the current CMS user has permission.

@@ -46,6 +53,10 @@ public function updateCMSFields(FieldList $fields) {
$permissions
));
}

// Allow extension customisation.

$this->owner->extend('updateSiteConfigMediaPermissionExtensionCMSFields', $fields);
}

}
162 changes: 162 additions & 0 deletions src/objects/MediaAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<?php

namespace nglasl\mediawesome;

use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Permission;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\Versioned\Versioned;

/**
* This is a CMS attribute for a media type.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class MediaAttribute extends DataObject {

private static $table_name = 'MediaAttribute';

private static $db = array(
'Title' => 'Varchar(255)',
'OriginalTitle' => 'Varchar(255)'
);

private static $has_one = array(
'MediaType' => MediaType::class
);

private static $belongs_many_many = array(
'MediaPages' => MediaPage::class . '.MediaAttributes'
);

public function canView($member = null) {

return true;
}

public function canEdit($member = null) {

return $this->checkPermissions($member);
}

public function canCreate($member = null, $context = array()) {

return $this->checkPermissions($member);
}

public function canDelete($member = null) {

// Determine whether this is being used.

$current = Versioned::get_stage();
foreach(singleton(Versioned::class)->getVersionedStages() as $stage) {
Versioned::set_stage($stage);
if($this->MediaPages()->exists() && $this->MediaPages()->where('MediaPageAttribute.Content IS NOT NULL')->exists()) {
return false;
}
}
Versioned::set_stage($current);

// Determine whether this is user created.

$config = MediaPage::config();
$type = $this->MediaType()->Title;
return !isset($config->type_defaults[$type]) || !in_array($this->OriginalTitle, $config->type_defaults[$type]);
}

/**
* Determine access for the current CMS user from the site configuration permissions.
*
* @parameter <{CURRENT_MEMBER}> member
* @return boolean
*/

public function checkPermissions($member = null) {

// Retrieve the current site configuration permissions for customisation of media.

$configuration = SiteConfig::current_site_config();
return Permission::check($configuration->MediaPermission, 'any', $member);
}

public function getCMSFields() {

$fields = parent::getCMSFields();
$fields->removeByName('OriginalTitle');
$fields->removeByName('MediaTypeID');
$fields->removeByName('MediaPages');

// Allow extension customisation.

$this->extend('updateMediaAttributeCMSFields', $fields);
return $fields;
}

/**
* Confirm that the current attribute is valid.
*/

public function validate() {

$result = parent::validate();

// Confirm that the current attribute has been given a title.

if($result->isValid() && !$this->Title) {
$result->addError('"Title" required!');
}

// Allow extension customisation.

$this->extend('validateMediaAttribute', $result);
return $result;
}

public function onBeforeWrite() {

parent::onBeforeWrite();

// Set the original title of the current attribute for use in templates.

if(!$this->OriginalTitle) {
$this->OriginalTitle = $this->Title;
}
}

public function onAfterWrite() {

parent::onAfterWrite();

// This needs to appear on media pages of the respective type.

foreach(MediaPage::get()->filter('MediaTypeID', $this->MediaTypeID) as $page) {
$page->MediaAttributes()->add($this);
}
}

public function onAfterDelete() {

parent::onAfterDelete();

// Clean up the pages associated with this.

$current = Versioned::get_stage();
foreach(singleton(Versioned::class)->getVersionedStages() as $stage) {
Versioned::set_stage($stage);
MediaPageAttribute::get()->filter('MediaAttributeID', $this->ID)->removeAll();
}
Versioned::set_stage($current);
}

/**
* Retrieve a class name of the current attribute for use in templates.
*
* @return string
*/

public function getTemplateClass() {

return strtolower($this->OriginalTitle);
}

}
73 changes: 73 additions & 0 deletions src/objects/MediaPageAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace nglasl\mediawesome;

use SilverStripe\Forms\DateField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\ORM\DataObject;

/**
* This is essentially the versioned join between `MediaPage` and `MediaAttribute`, since each page will have different content for an attribute.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class MediaPageAttribute extends DataObject {

private static $table_name = 'MediaPageAttribute';

private static $db = array(
'Content' => 'HTMLText'
);

private static $has_one = array(
'MediaPage' => MediaPage::class,
'MediaAttribute' => MediaAttribute::class
);

private static $summary_fields = array(
'Title',
'Content'
);

public function canDelete($member = null) {

return false;
}

public function getTitle() {

return $this->MediaAttribute()->Title;
}

public function getCMSFields() {

$fields = parent::getCMSFields();
$fields->removeByName('MediaPageID');
$fields->removeByName('MediaAttributeID');

// Determine the field type.

if(strrpos($this->getTitle(), 'Date')) {

// The user expects this to be a date attribute.

$fields->replaceField('Content', DateField::create(
'Content'
));
}
else {

// This is most commonly a simple attribute, so a HTML field only complicates things for the user.

$fields->replaceField('Content', TextareaField::create(
'Content'
));
}

// Allow extension customisation.

$this->extend('updateMediaPageAttributeCMSFields', $fields);
return $fields;
}

}
69 changes: 69 additions & 0 deletions src/objects/MediaTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace nglasl\mediawesome;

use SilverStripe\ORM\DataObject;

/**
* This is a CMS tag for a media page.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class MediaTag extends DataObject {

private static $table_name = 'MediaTag';

private static $db = array(
'Title' => 'Varchar(255)'
);

private static $default_sort = 'Title';

public function canView($member = null) {

return true;
}

public function canEdit($member = null) {

return true;
}

public function canCreate($member = null, $context = array()) {

return true;
}

public function canDelete($member = null) {

return false;
}

/**
* Confirm that the current tag is valid.
*/

public function validate() {

$result = parent::validate();

// Confirm that the current tag has been given a title and doesn't already exist.

$this->Title = strtolower($this->Title);
if($result->isValid() && !$this->Title) {
$result->addError('"Title" required!');
}
else if($result->isValid() && MediaTag::get_one(MediaTag::class, array(
'ID != ?' => $this->ID,
'Title = ?' => $this->Title
))) {
$result->addError('Tag already exists!');
}

// Allow extension customisation.

$this->extend('validateMediaTag', $result);
return $result;
}

}
127 changes: 127 additions & 0 deletions src/objects/MediaType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

namespace nglasl\mediawesome;

use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer;
use SilverStripe\Forms\ReadonlyField;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Permission;
use SilverStripe\SiteConfig\SiteConfig;

/**
* This is a CMS type/category of media.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class MediaType extends DataObject {

private static $table_name = 'MediaType';

private static $db = array(
'Title' => 'Varchar(255)'
);

private static $has_many = array(
'MediaAttributes' => MediaAttribute::class
);

private static $default_sort = 'Title';

public function canView($member = null) {

return true;
}

public function canEdit($member = null) {

return true;
}

public function canCreate($member = null, $context = array()) {

return $this->checkPermissions($member);
}

public function canDelete($member = null) {

// Determine whether this is being used, and whether this is user created.

$config = MediaPage::config();
return
!MediaHolder::get()->filter('MediaTypeID', $this->ID)->exists()
&& !isset($config->type_defaults[$this->Title]);
}

/**
* Determine access for the current CMS user from the site configuration permissions.
*
* @parameter <{CURRENT_MEMBER}> member
* @return boolean
*/

public function checkPermissions($member = null) {

// Retrieve the current site configuration permissions for customisation of media.

$configuration = SiteConfig::current_site_config();
return Permission::check($configuration->MediaPermission, 'any', $member);
}

public function getCMSFields() {

$fields = parent::getCMSFields();
if($this->Title) {

// Display the title as read only.

$fields->replaceField('Title', ReadonlyField::create(
'Title'
));

// Allow customisation of media type attributes, depending on the current CMS user permissions.

$fields->removeByName('MediaAttributes');
$configuration = ($this->checkPermissions() === false) ? GridFieldConfig_RecordViewer::create() : GridFieldConfig_RecordEditor::create();
$fields->addFieldToTab('Root.Main', GridField::create(
'MediaAttributes',
'Custom Attributes',
$this->MediaAttributes(),
$configuration
)->setModelClass(MediaAttribute::class));
}

// Allow extension customisation.

$this->extend('updateMediaTypeCMSFields', $fields);
return $fields;
}

/**
* Confirm that the current type is valid.
*/

public function validate() {

$result = parent::validate();

// Confirm that the current type has been given a title and doesn't already exist.

if($result->isValid() && !$this->Title) {
$result->addError('"Title" required!');
}
else if($result->isValid() && MediaType::get_one(MediaType::class, array(
'ID != ?' => $this->ID,
'Title = ?' => $this->Title
))) {
$result->addError('Type already exists!');
}

// Allow extension customisation.

$this->extend('validateMediaType', $result);
return $result;
}

}
132 changes: 132 additions & 0 deletions src/pages/MediaHolder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

namespace nglasl\mediawesome;

use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\Forms\ReadonlyField;

/**
* Displays media holder/page children, with optional date/tag filters.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class MediaHolder extends \Page {

private static $table_name = 'MediaHolder';

private static $db = array(
'URLFormatting' => "Enum('y/MM/dd/, y/MM/, y/, -', 'y/MM/dd/')"
);

private static $has_one = array(
'MediaType' => MediaType::class
);

private static $allowed_children = array(
MediaHolder::class,
MediaPage::class
);

private static $default_child = MediaPage::class;

private static $description = '<strong>Holds:</strong> Blogs, Events, News, Publications <strong>or Custom Media</strong>';

private static $icon = 'nglasl/silverstripe-mediawesome: client/images/holder.png';

public function getCMSFields() {

$fields = parent::getCMSFields();

// Display the media type as read only if media page children exist.

($this->getMediaPageChildren()->exists() && $this->MediaType()->exists()) ?
$fields->addFieldToTab('Root.Main', ReadonlyField::create(
'Media',
'Media Type',
$this->MediaType()->Title
), 'Title') :
$fields->addFieldToTab('Root.Main', DropdownField::create(
'MediaTypeID',
'Media Type',
MediaType::get()->map()->toArray()
), 'Title');

// Allow customisation of the media URL format.

$formats = array(
'y/MM/dd/' => 'year/month/day/media',
'y/MM/' => 'year/month/media',
'y/' => 'year/media',
'-' => 'media'
);
$fields->insertBefore(DropdownField::create(
'URLFormatting',
'URL Formatting',
$formats
)->setDescription('The <strong>media</strong> URL format'), 'Content');

// Allow customisation of media types, depending on the current CMS user permissions.

$fields->findOrMakeTab('Root.ManageMedia.TypesAttributes', 'Types and Attributes');
$fields->findOrMakeTab('Root.ManageMedia')->setTitle('Manage ALL Media');
$fields->addFieldToTab('Root.ManageMedia.TypesAttributes', GridField::create(
'TypesAttributes',
'Types and Attributes',
MediaType::get(),
GridFieldConfig_RecordEditor::create()
)->setModelClass(MediaType::class));

// Allow customisation of media categories and tags.

$fields->findOrMakeTab('Root.ManageMedia.CategoriesTags', 'Categories and Tags');
$fields->addFieldToTab('Root.ManageMedia.CategoriesTags', GridField::create(
'CategoriesTags',
'Categories and Tags',
MediaTag::get(),
GridFieldConfig_RecordEditor::create()->removeComponentsByType(GridFieldDeleteAction::class)
)->setModelClass(MediaTag::class));

// Allow extension customisation.

$this->extend('updateMediaHolderCMSFields', $fields);
return $fields;
}

public function onBeforeWrite() {

parent::onBeforeWrite();

// Apply the first media type by default.

if(!$this->MediaTypeID) {
$existing = MediaType::get()->first();
$this->MediaTypeID = $existing->ID;
}
}

/**
* Retrieve any `MediaHolder` children of this `MediaHolder`.
*
* @return data list
*/

public function getMediaHolderChildren() {

return $this->AllChildren()->filter('ClassName', MediaHolder::class);
}

/**
* Retrieve any `MediaPage` children of this `MediaHolder`.
*
* @return data list
*/

public function getMediaPageChildren() {

return $this->AllChildren()->filter('ClassName', MediaPage::class);
}

}
478 changes: 478 additions & 0 deletions src/pages/MediaPage.php

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions templates/Layout/MediaHolder.ss
Original file line number Diff line number Diff line change
@@ -3,19 +3,19 @@
<div class='media-holder-content'>{$Content}</div>
<% if $AllChildren %>
<div class='media-holder-children'>
<% if $CheckMediaHolder %>
<% loop $CheckMediaHolder %>
<% if $MediaHolderChildren %>
<% loop $MediaHolderChildren %>
<div class='media-holder'>
<h4><a href='{$Link}'><strong>{$Title}</strong></a></h4>
<h2><a href='{$Link}'><strong>{$Title}</strong></a></h2>
<div>{$Content.Summary}</div>
<br>
</div>
<% end_loop %>
<% else %>
<% loop $PaginatedChildren %>
<div class='media-page'>
<h4><a href='<% if $ExternalLink %>{$ExternalLink}<% else_if not $Content && $Attachments.count == 1 %>$Attachments.first.Link<% else %>{$Link}<% end_if %>'<% if $ExternalLink %> target='_blank'<% end_if %>><strong>{$Title}</strong></a></h4>
<p class='media-date'><em>{$Date.Format('M j, Y')}</em></p>
<h2><a href='<% if $ExternalLink %>{$ExternalLink}<% else_if not $Content && $Attachments.count == 1 %>$Attachments.first.Link<% else %>{$Link}<% end_if %>'<% if $ExternalLink %> target='_blank'<% end_if %>><strong>{$Title}</strong></a></h2>
<p class='media-date'><em>{$Date.Format('MMM d, y')}</em></p>
<% if $Abstract %>
<div class='media-abstract'>{$Abstract}</div>
<% end_if %>
23 changes: 16 additions & 7 deletions templates/Layout/MediaPage.ss
Original file line number Diff line number Diff line change
@@ -2,14 +2,21 @@
<h1>{$Title}</h1>
<% if $Images.first %>
<p class='media-page-main-image'>
<span><a href='$Images.first.Link'>{$Images.first.CroppedImage(200, 200)}</a></span>
<span><a href='$Images.first.Link'>{$Images.first.Fill(200, 200)}</a></span>
</p>
<% end_if %>
<div class='media-page-date'><em>{$Date.Nice}</em></div>
<% if $Categories %>
<h2 class='media-page-categories'>
<% loop $Categories %>
<span><a href='{$Up.getParent.Link}?category={$Title.URLATT}'>{$Title}</a></span>
<% end_loop %>
</h2>
<% end_if %>
<div class='media-page-date'><em>{$Date.Format('MMM d, y')}</em></div>
<div class='media-page-attributes'>
<% loop $MediaAttributes %>
<% if $Content %>
<div class='media-page-attribute {$TemplateClass}'><em><strong>{$Title}: </strong>{$Content}</em></div>
<% if $Join.Content %>
<div class='media-page-attribute {$TemplateClass}'><em><strong>{$Title}: </strong>{$Join.Content}</em></div>
<% end_if %>
<% end_loop %>
<br>
@@ -19,21 +26,23 @@
<p class='media-page-images'>
<% loop $Images %>
<% if not $first %>
<span><a href='{$Link}'>{$CroppedImage(100, 100)}</a></span>
<span><a href='{$Link}'>{$Fill(100, 100)}</a></span>
<% end_if %>
<% end_loop %>
</p>
<% end_if %>
<% if $Attachments %>
<div class='media-page-attachments'><em><strong>Attachments:</strong></em>
<div class='media-page-attachments'>
<em><strong>Attachments:</strong></em>
<% loop $Attachments %>
<div><a href='{$Link}'>{$Title}</a></div>
<% end_loop %>
</div>
<br>
<% end_if %>
<% if $Tags %>
<div class='media-page-tags'><em><strong>Tags:</strong></em>
<div class='media-page-tags'>
<em><strong>Tags:</strong></em>
<% loop $Tags %>
<span><a href='{$Up.getParent.Link}?tag={$Title.URLATT}'><em>{$Title}</em></a></span>
<% end_loop %>
73 changes: 73 additions & 0 deletions tests/FunctionalTests.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace nglasl\mediawesome\tests;

use nglasl\mediawesome\MediaHolder;
use nglasl\mediawesome\MediaPage;
use nglasl\mediawesome\MediaType;
use SilverStripe\Dev\FunctionalTest;

/**
* The mediawesome specific functional testing.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class FunctionalTests extends FunctionalTest {

protected $usesDatabase = true;

protected $requireDefaultRecordsFrom = array(
MediaPage::class
);

public function testURLs() {

$this->logInWithPermission();

// Instantiate a media page with a random type.

$holder = MediaHolder::create(
array(
'ClassName' => MediaHolder::class,
'Title' => 'Holder',
'URLFormatting' => 'y/MM/dd/',
'MediaTypeID' => MediaType::get()->first()->ID
)
);
$holder->writeToStage('Stage');
$holder->publishRecursive();
$first = MediaPage::create(
array(
'Title' => 'First',
'ParentID' => $holder->ID
)
);
$first->writeToStage('Stage');
$first->publishRecursive();

// This should match "holder/year/month/day/media".

$this->assertEquals(count(explode('/', trim($first->Link(), '/'))), 5);

// Determine whether the page is accessible.

$response = $this->get($first->Link());
$this->assertEquals($response->getStatusCode(), 200);

// Update the URL format.

$holder->URLFormatting = '-';
$holder->writeToStage('Stage');
$holder->publishRecursive();

// This should match "holder/media".

$this->assertEquals(count(explode('/', trim($first->Link(), '/'))), 2);

// Determine whether the page remains accessible.

$response = $this->get($first->Link());
$this->assertEquals($response->getStatusCode(), 200);
}

}
106 changes: 106 additions & 0 deletions tests/UnitTests.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace nglasl\mediawesome\tests;

use nglasl\mediawesome\MediaAttribute;
use nglasl\mediawesome\MediaHolder;
use nglasl\mediawesome\MediaPage;
use nglasl\mediawesome\MediaType;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Versioned\Versioned;

/**
* The mediawesome specific unit testing.
* @author Nathan Glasl <nathan@symbiote.com.au>
*/

class UnitTests extends SapphireTest {

protected $usesDatabase = true;

protected $requireDefaultRecordsFrom = array(
MediaPage::class
);

public function testMediaAttributes() {

// Instantiate some media pages with a random type.

$type = MediaType::get()->first();
$holder = MediaHolder::create(
array(
'Title' => 'Holder',
'MediaTypeID' => $type->ID
)
);
$holder->writeToStage('Stage');
$holder->publishRecursive();
$first = MediaPage::create(
array(
'Title' => 'First',
'ParentID' => $holder->ID
)
);
$first->writeToStage('Stage');
$first->publishRecursive();
$second = MediaPage::create(
array(
'Title' => 'Second',
'ParentID' => $holder->ID
)
);
$second->writeToStage('Stage');
$second->publishRecursive();

// Determine whether a media page has the respective media attributes.

$attribute = $first->MediaAttributes()->first();
$expected = $type->MediaAttributes()->first();
$this->assertEquals($attribute->ID, $expected->ID);
$this->assertEquals($attribute->getJoin()->Content, null);

// Update the media attribute content.

$first->MediaAttributes()->add($attribute, array(
'Content' => 'Changed'
));

// Determine whether this change is reflected by the first page.

$attribute = $first->MediaAttributes()->first();
$this->assertEquals($attribute->getJoin()->Content, 'Changed');

// Confirm this change is not reflected by the second page.

$attribute = $second->MediaAttributes()->first();
$this->assertEquals($attribute->ID, $expected->ID);
$this->assertEquals($attribute->getJoin()->Content, null);

// The attributes are versioned, so make sure this change wasn't published.

Versioned::set_stage('Live');
$first = MediaPage::get()->byID($first->ID);
$attribute = $first->MediaAttributes()->first();
$this->assertEquals($attribute->getJoin()->Content, null);
$first->publishRecursive();

// Confirm this change is now published.

$attribute = $first->MediaAttributes()->first();
$this->assertEquals($attribute->getJoin()->Content, 'Changed');

// Determine whether a new media attribute appears on the page.

$count = $first->MediaAttributes()->count();
$new = MediaAttribute::create(
array(
'Title' => 'New',
'MediaTypeID' => $type->ID
)
);
$new->write();
$this->assertEquals($first->MediaAttributes()->count(), $count + 1);
Versioned::set_stage('Stage');
}

}