Skip to content

Commit

Permalink
EZP-22324: Implemented premium subscriber content
Browse files Browse the repository at this point in the history
A custom location view provider displays a teasing template
if the content is Premium (section id 7 (Premium)), and if the
user doesn't have the subscriber role (id: 6)

section_id and role_id are configured in default_settings.yml.
  • Loading branch information
Bertrand Dunogier committed Nov 19, 2014
1 parent 0a59a6e commit 9c5b83b
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 0 deletions.
61 changes: 61 additions & 0 deletions PremiumContent/PremiumLocationViewProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
/**
* This file is part of the eZ Publish Kernel package
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributd with this source code.
*/
namespace EzSystems\DemoBundle\PremiumContent;

use eZ\Publish\API\Repository\Repository;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\API\Repository\Values\User\Role;
use eZ\Publish\Core\MVC\Symfony\View\ContentView;
use eZ\Publish\Core\MVC\Symfony\View\Provider\Location as LocationViewProvider;

/**
* Returns the premium_content view if it applies to a location and if the user isn't a Premium subscriber.
*/
class PremiumLocationViewProvider implements LocationViewProvider
{
/**
* ID of the section used to mark content as Premium
* @var int
*/
private $premiumSectionId;

/** @var PremiumSubscriptionChecker */
private $subscriptionChecker;

/**
* @var Repository
*/
private $repository;

public function __construct( Repository $repository, PremiumSubscriptionChecker $subscriptionChecker, $premiumSectionId )
{
$this->repository = $repository;
$this->premiumSectionId = $premiumSectionId;
$this->subscriptionChecker = $subscriptionChecker;
}

public function getView( Location $location, $viewType )
{
if ( $viewType !== 'full' )
{
return null;
}

if ( $location->getContentInfo()->sectionId !== $this->premiumSectionId )
{
return null;
}

if ( $this->subscriptionChecker->userIsSubscriber( $this->repository->getCurrentUser() ) )
{
return null;
}

return new ContentView( "eZDemoBundle:$viewType:premium_content.html.twig" );
}
}
57 changes: 57 additions & 0 deletions PremiumContent/PremiumSubscriptionChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
* This file is part of the eZ Publish Kernel package
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributd with this source code.
*/
namespace EzSystems\DemoBundle\PremiumContent;

use eZ\Publish\API\Repository\Values\User\User;
use eZ\Publish\API\Repository\Repository;
use eZ\Publish\API\Repository\Values\User\Role;

class PremiumSubscriptionChecker
{
/**
* ID of the premium subscriber role
*/
private $roleId = 6;

/**
* @var Repository|\eZ\Publish\Core\Repository\Repository
*/
private $repository;

public function __construct( Repository $repository, $subscriberRoleId )
{
$this->repository = $repository;
$this->roleId = $subscriberRoleId;
}

public function userIsSubscriber( User $user )
{
$roleService = $this->repository->getRoleService();
return $this->repository->sudo(
function ( Repository $repository ) use ( $user, $roleService )
{
foreach ( $repository->getUserService()->loadUserGroupsOfUser( $user ) as $group )
{
foreach ( $roleService->getRoleAssignmentsForUserGroup( $group ) as $role )
{
if ( $this->isSubscriberRole( $role->role ) )
{
return true;
}
}
}
return false;
}
);
}

public function isSubscriberRole( Role $role )
{
return $role->id === $this->roleId;
}
}
4 changes: 4 additions & 0 deletions Resources/config/default_settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ parameters:
## Search Page
# Number of results displayed per page in the simple search
ezdemo.search.list.limit: 10

## Premium content
ezdemo.premium_content.section_id: 7
ezdemo.premium_content.role_id: 6
15 changes: 15 additions & 0 deletions Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,18 @@ services:
scope: request # needed as we have the request as a dependency here
tags:
- { name: knp_menu.menu, alias: top } # The alias is what is used to retrieve the menu

ezdemo.premium_content.location_view_provider:
class: EzSystems\DemoBundle\PremiumContent\PremiumLocationViewProvider
arguments:
- @ezpublish.api.repository
- @ezdemo.premium_content.subscription_checker
- %ezdemo.premium_content.section_id%
tags:
- {name: ezpublish.location_view_provider, priority: 30}

ezdemo.premium_content.subscription_checker:
class: EzSystems\DemoBundle\PremiumContent\PremiumSubscriptionChecker
arguments:
- @ezpublish.api.repository
- %ezdemo.premium_content.role_id%
21 changes: 21 additions & 0 deletions Resources/views/full/premium_content.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% extends "eZDemoBundle::pagelayout.html.twig" %}

{% block content %}
<section class="content-view-full">
<article class="class-article row">
<div class="span8">
<div class="attribute-header">
<h1>{{ ez_render_field( content, 'title' ) }}</h1>
</div>

{% if not ez_is_field_empty( content, 'subscriber_teaser' ) %}
<div class="attribute-short">
{{ ez_render_field( content, 'subscriber_teaser' ) }}
</div>
{% endif %}

This article is only available to Premium subscribers.
</div>
</article>
</section>
{% endblock %}
11 changes: 11 additions & 0 deletions doc/specifications/premium_content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Premium content

This feature displays content marked as Premium using a special teaser and informations about the status. It is
an example of what could be used to offer a paywall.

## Implementation
Premium content is identified belonging to section Premium (ID: 7). Subscribers have the Subscriber role (ID: 6).

A standard policy check can't be used here, as it would prevent the content from being returned in searches and lists.
Instead, Anonymous user can read this content, but a custom ViewProvider is used to return a special premium_teaser
template when a premium content is viewed by a non-subscriber.

0 comments on commit 9c5b83b

Please sign in to comment.