Skip to content

Commit

Permalink
Initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
martinheise committed Jan 10, 2024
0 parents commit cf474ce
Show file tree
Hide file tree
Showing 44 changed files with 2,444 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# For more information about the properties used in this file,
# please see the EditorConfig documentation:
# http://editorconfig.org

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[{*.yml,package.json,*.js,*.scss}]
indent_size = 2
indent_style = space
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/tests export-ignore
/.gitattributes export-ignore
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
.phpunit.result.cache
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Contributing
12 changes: 12 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Copyright (c) 2023 Martin Heise <[email protected]>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
123 changes: 123 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# SilverStripe Download Codes

An extension for SilverStripe for generating download codes to give frontend users special access to protected files. A typical use case would be the download of digital music albums via codes provided with the LP version or sold separately.

## Requirements

Requires Silverstripe 5.x, still works with Silverstripe 4 – see respective branches `4` and `5`


## Installation and setup

Install with composer:

composer require mhe/silverstripe-download-codes ^1.0

Perform `dev/build` task

Add a page of type “Download Page” to your site. This will provide a form where users can redeem their code. You might want to deactivate the “Show in menus” setting and only communicate the URL together with the download codes.


### Recommended extensions

These extensions will improve the experience, but are optional:

- [bummzack/sortablefile](https://packagist.org/packages/bummzack/sortablefile): Support for sortable UploadFields, to sort Download Package files
- [colymba/gridfield-bulk-editing-tools](https://packagist.org/packages/colymba/gridfield-bulk-editing-tools): Support for bulk actions in Admin area
- PHP with enabled [ext/zip](https://www.php.net/manual/en/book.zip.php): Providing download packages as zip


## Backend usage

The administration of download codes is done in the Admin area “Download Codes”.

Basically you will create a Download Package with the desired files, create or generate Download Codes connected to this package, and provide these codes to users / customers in some way.


### Download Packages

A download package is a collection of files and common metadata that is provided as one code protected download.

The downloadable files should be protected against public access either directly or by inherited access from their parent folder. The admin grid view will give a warning if unprotected files are part of a package.

*Fields:*

- _Title_: Name of the package – can be displayed to users to describe the whole download – e.g. name of a music album
- _Preview Image_: Image representing thre whole download – e.g. a LP cover
- _Files_: The actual downloadable content files
- _Provide ZIP download_: Allow users to download all package files as ZIP


### Download Codes

A download code represents the download permission for a specific package.

A download code can either be limited (meant to be used be exactly one user) or un-limited (meant to be sent to multiple persons, e.g. for some marketing event)

Standard CSV export is enabled, which often will be helpful to distribute generated codes.

*Fields:*

- _Code_: The actual code you will send to a user / customer
- _Expiration Date_: (optional) The code can’t be redeemed after this date
- _Active_: If false, the code can’t be redeemed. Is set automatically to false when the usage_limit was reached (only for limited codes)
- _Limited_: Limited usage by one user
- _Distributed_: Mark the code as distributed to users / customers, to keep track of required codes
- _Package_: The download package handled by this code
- _Usage count_: (readonly) count of successful redemptions
- _Note_: Arbitrary note for internal use

#### Tab Redemptions

Read-only list of successful redemptions with dates of creation and their expiration

#### Action “Generate Codes”

With this action a bigger number of codes can be create/prepared in one step. The desired number will be created, filled with common settings, the Code field will be set each to unique value according to configured length and characters. (see „Configuration options“ below)

*Dialog Fields:*

- _Quantitiy_: number of download codes to generate
- _Expiration Date_: (optional) Set for all generated codes
- _Limited_: (optional) Set for all generated codes
- _Package_: (required) Set for all generated codes
- _Note_: Arbitrary note for internal use

#### Batch actions

Perform actions on multiple selection Download codes: (requires [colymba/gridfield-bulk-editing-tools](https://packagist.org/packages/colymba/gridfield-bulk-editing-tools))

- Delete
- Mark as distributed
- Remove distributed mark


## Configuration

The following templates are included providing the basic funcionality. You can adjust them via a theme or project templates to adjust the layout to your needs.

### Templates

- `Mhe/DownloadCodes/Model/Layout/DLPage_redeem.ss`: Layout of the DownloadPage containing the main code redemption form
- `Mhe/DownloadCodes/Model/Layout/DLPage.ss`: Displayed after successful entering of a valid code, containing the actual links to downloadable files

### Configuration options via Silverstripe YAML configuration

#### Mhe\DownloadCodes\Model\DLCode

- _autogenerate_chars_: string containing valid characters for auto generated codes (default: "ABCDEFGHIJAKLMNOPQRSTUVWXYZ0123456789")
- _autogenerate_length_: length of auto generated codes (default: 8)
- _strip_whitespace_: if true strips whitespace from user input for codes (default: false)
- _case_sensitive_: user’s code input needs to match the case of the valid code (default: true), otherwise matches case-insensitive
- _usage_limit_: number of attempts a regular code can be redeemed (default: 5). The actual file download after redemption (in case of download problems etc) is not limited by this.

#### Mhe\DownloadCodes\Model\DLRedemption

- _validity_days_: number of days a code redemption with the unique URL part will be valid and can be used for download


## Available Backend Permissions

- _Access to 'Download Codes' section_: view download codes and packages
- _Edit download packages_: create, edit, delete download packages
- _Edit download codes_: create, edit, delete download codes
1 change: 1 addition & 0 deletions _config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php
4 changes: 4 additions & 0 deletions _config/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
Name: download-codes
Before: 'app'
---
9 changes: 9 additions & 0 deletions _config/dlcache.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
Name: dlcache
---
SilverStripe\Core\Injector\Injector:
Psr\SimpleCache\CacheInterface.DLPackage_Generated:
factory: SilverStripe\Core\Cache\CacheFactory
constructor:
namespace: "DLPackage_Generated"

15 changes: 15 additions & 0 deletions client/dist/css/admin.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.grid-field__table {
position:relative;
}

.grid-field__row-validation span:before {
margin-right: 0.5em;
}

.grid-field__row-validation .font-icon-check-mark-circle {
color: green
}

.grid-field__row-validation .font-icon-cancel-circled {
color: red
}
46 changes: 46 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "mhe/silverstripe-download-codes",
"description": "Create download codes for protected files in SilverStripe",
"type": "silverstripe-vendormodule",
"keywords": [
"silverstripe",
"CMS",
"downloads",
"file"
],
"license": "BSD-3-Clause",
"authors": [
{
"name": "Martin Heise",
"email": "[email protected]"
}
],
"require": {
"php": "^8.0",
"silverstripe/framework": "^4.0 || ^5.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"suggest": {
"bummzack/sortablefile": "Support for sortable UploadFields, e.g. for Download Package files",
"colymba/gridfield-bulk-editing-tools": "Support for bulk actions in Admin",
"ext/zip": "Support for DownloadPackages as zip"
},
"autoload": {
"psr-4": {
"Mhe\\DownloadCodes\\": "src/",
"Mhe\\DownloadCodes\\Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
},
"expose": [
"client/dist"
]
},
"minimum-stability": "dev",
"prefer-stable": true
}
69 changes: 69 additions & 0 deletions lang/de.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
de:
Mhe\DownloadCodes\Controller\DLCodeAdmin:
FORM_Quantity: Anzahl
GENERATE_CODES: 'Codes erzeugen'
MENUTITLE: 'Download-Codes'
Mhe\DownloadCodes\Controller\MarkDistributedHandler:
ACTION_LABEL: 'Als verteilt markieren'
Mhe\DownloadCodes\Controller\UnmarkDistributedHandler:
ACTION_LABEL: 'Verteilt-Markierung entfernen'
Mhe\DownloadCodes\Forms\DLRequestForm:
ACTION_submitcode: Einlösen
FIELD_Code: Code
Mhe\DownloadCodes\Forms\GridField\RowValidation:
ColumnTitle: 'Prüfung'
DefaultMessage: 'Zu prüfen'
Mhe\DownloadCodes\Model\DLCode:
ADMIN_TABNAME: 'Download-Codes'
EDIT_ALL_HELP: 'Download-Codes verwalten'
EDIT_ALL_NAME: 'Download-Codes bearbeiten'
ERROR_Unique_Code: 'Code wird bereits verwendet'
PLURALNAME: 'Download-Codes'
PLURALS:
one: 'Ein Download-Code'
other: '{count} Download-Codes'
SINGULARNAME: 'Download-Code'
db_Active: Aktiv
db_Code: Code
db_Distributed: Verteilt
db_Expires: 'Ablaufdatum'
db_Limited: Limitiert
db_Note: Notiz
db_UsageCount: 'Anzahl Verwendungen'
has_many_Redemptions: Einlösungen
has_one_Package: Paket
Mhe\DownloadCodes\Model\DLPackage:
ADMIN_TABNAME: 'Download-Pakete'
DESCRIPTION: 'Bündel von downloadbaren Dateien'
EDIT_ALL_HELP: 'Download-Pakete verwalten'
EDIT_ALL_NAME: 'Download-Pakete bearbeiten'
FILES_COUNT: 'Anzahl Dateien'
FILES_FIRST_TITLE: 'Erster Datei-Titel'
PLURALNAME: 'Download-Pakete'
PLURALS:
one: 'Ein Download-Paket'
other: '{count} Download-Pakete'
SINGULARNAME: 'Download-Paket'
db_EnableZip: 'ZIP-Download ermöglichen'
db_Title: 'Titel'
has_one_PreviewImage: 'Vorschau-Bild'
many_many_Files: 'Dateien'
UnprotectedFiles: 'Ungeschützte Dateien'
Mhe\DownloadCodes\Model\DLPage:
DESCRIPTION: 'Seite mit einem Formular, mit dem Nutzer ihre Download-Codes einlösen können'
PLURALNAME: 'Download-Seiten'
PLURALS:
one: 'Eine Download-Seite'
other: '{count} Download-Seiten'
SINGULARNAME: 'Download-Seite'
Mhe\DownloadCodes\Model\DLRedemption:
PLURALNAME: 'Download-Einlösungen'
PLURALS:
one: 'Eine Download-Einlösung'
other: '{count} Download-Einlösungen'
SINGULARNAME: 'Download-Einlösungen'
db_Created: 'Erstellt'
db_Expires: 'Ablaufdatum'
db_URLSecret: 'URL Secret'
has_one_Code: 'Code'

66 changes: 66 additions & 0 deletions lang/en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
en:
Mhe\DownloadCodes\Controller\DLCodeAdmin:
FORM_Quantity: Quantity
GENERATE_CODES: 'Generate Codes'
MENUTITLE: 'Download Codes'
Mhe\DownloadCodes\Controller\MarkDistributedHandler:
ACTION_LABEL: 'Mark as distributed'
Mhe\DownloadCodes\Controller\UnmarkDistributedHandler:
ACTION_LABEL: 'Remove distributed mark'
Mhe\DownloadCodes\Forms\DLRequestForm:
ACTION_submitcode: Redeem
FIELD_Code: Code
Mhe\DownloadCodes\Forms\GridField\RowValidation:
ColumnTitle: 'Validation'
DefaultMessage: 'To validate'
Mhe\DownloadCodes\Model\DLCode:
EDIT_ALL_HELP: 'Manage download codes.'
EDIT_ALL_NAME: 'Edit download codes'
ERROR_Unique_Code: 'Code is already in use'
PLURALNAME: 'Download Codes'
PLURALS:
one: 'A Download Code'
other: '{count} Download Codes'
SINGULARNAME: 'Download Code'
db_Active: Active
db_Code: Code
db_Distributed: Distributed
db_Expires: 'Expiration Date'
db_Limited: Limited
db_Note: Note
db_UsageCount: 'Usage Count'
has_many_Redemptions: Redemptions
has_one_Package: Package
Mhe\DownloadCodes\Model\DLPackage:
DESCRIPTION: 'Set of downloadable files'
EDIT_ALL_HELP: 'Manage download packages.'
EDIT_ALL_NAME: 'Edit download packages'
FILES_COUNT: 'Number of files'
FILES_FIRST_TITLE: 'First file title'
PLURALNAME: 'Download Packages'
PLURALS:
one: 'A Download Package'
other: '{count} Download Packages'
SINGULARNAME: 'Download Package'
db_EnableZip: 'Provide ZIP download'
db_Title: 'Title'
has_one_PreviewImage: 'Preview Image'
many_many_Files: 'Files'
UnprotectedFiles: 'Unprotected files'
Mhe\DownloadCodes\Model\DLPage:
DESCRIPTION: 'Page with a form where users can redeem their download codes'
PLURALNAME: 'Download Pages'
PLURALS:
one: 'A Download Page'
other: '{count} Download Pages'
SINGULARNAME: 'Download Page'
Mhe\DownloadCodes\Model\DLRedemption:
PLURALNAME: 'Download Redemptions'
PLURALS:
one: 'A Download Redemption'
other: '{count} Download Redemptions'
SINGULARNAME: 'Download Redemption'
db_Created: 'Created'
db_Expires: 'Expiry date'
db_URLSecret: 'URL Secret'
has_one_Code: 'Code'
11 changes: 11 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="SilverStripe">
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>

<!-- base rules are PSR-12 -->
<rule ref="PSR12" >
<!-- Current exclusions -->
<!--<exclude name="PSR1.Files.SideEffects.FoundWithSymbols" />-->
<!--<exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps" />-->
</rule>
</ruleset>
Loading

0 comments on commit cf474ce

Please sign in to comment.