Skip to content

Commit

Permalink
feature/beta project post (#584)
Browse files Browse the repository at this point in the history
* create subscriptions menu for project dashboard (#555)

authored-by: David Igón <davidbenabarre@platoniq.net>

* Add subscriptions

* Add subscriptions to project dashboard

* Update database code

* Update dashboard subscription form

* Start updating subscriptions dashboard to add new subscription

* Basic subscription form on dashboard

* CRUD for subscriptions on project dashboard

* Add support for subscriptions via stripe payments

* Fix Stripe integration details

* Make stripe subscriptions be enabled via rewards

* Remove legacy integration

* Remove javascript related to previous subscription model

* Fix stripe integration PR comments

* Use abstract payment in stripe payment method

* add migrations for privacy seetings in project posts with rewards

* allow limiting access to project posts

* add PostRewardAccess model

* add form to handle project post privacy settings with invests to rewards

* add missing copies for project's post privacy

* add library to handle access to project posts based on rewards

* fix check if user has invest to reward based on if it's subscribable or not

* limit visible content of project post if it has a restricted access

* add missing copy

* add missing use of translation copy

* improve use of if else in postprivacyaccess library

* rework of sql to check if user has donation to rewards that grant access to post

* add InvestRepository

---------

Co-authored-by: David Igón <david.igon@riseup.net>
Co-authored-by: David Igón <davidbenabarre@platoniq.net>
  • Loading branch information
3 people authored Nov 23, 2023
1 parent 8671ed6 commit c9715e6
Show file tree
Hide file tree
Showing 24 changed files with 776 additions and 65 deletions.
47 changes: 47 additions & 0 deletions Resources/templates/responsive/dashboard/project/privacy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php $this->layout('dashboard/project/layout') ?>

<?php $this->section('dashboard-content') ?>

<div class="dashboard-content">
<div class="inner-container">
<h2><?= $this->ee($this->post->title) ?></h2>
<p><?= $this->text('dashboard-menu-projects-updates-privacy') ?></p>
<a href="/dashboard/project/<?= $this->project->id ?>/updates/<?= $this->post->id ?>/privacy/new" class="btn btn-cyan spacer-bottom-20"><i class="fa fa-plus"></i> <?= $this->text('form-add-button') ?></a>

<?php if($this->rewards): ?>
<table class="-footable table">
<thead>
<tr>
<th data-type="number" data-breakpoints="xs">#</th>
<th><?= $this->text('regular-title') ?></th>
<th style="min-width: 140px"><?= $this->text('regular-actions') ?></th>
</tr>
</thead>
<tbody>
<?php
foreach($this->rewards as $reward):
?>
<tr>
<td><?= $reward->getReward()->id ?></td>
<td><?= $reward->getReward()->reward ?></td>
<td>
<div class="btn-group">
<a class="btn btn-default" title="<?= $this->text('regular-delete') ?>" href="/project/<?= $this->project->id ?>/updates/<?= $this->post->id ?>/delete/<?= $reward->getReward()->id ?>"><i class="fa fa-trash"></i></a>
</div>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>

<?= $this->insert('partials/utils/paginator', ['total' => $this->total, 'limit' => $this->limit]) ?>

<?php else: ?>
<blockquote>
<?= $this->text('dashboard-project-blog-privacy-empty') ?>
</blockquote>
<?php endif ?>
</div>
</div>

<?php $this->replace() ?>
12 changes: 12 additions & 0 deletions Resources/templates/responsive/dashboard/project/privacy/new.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php $this->layout('dashboard/project/layout') ?>

<?php $this->section('dashboard-content') ?>


<section class="container">
<h2><?= $this->text('dashboard-project-privacy-add-new-restriction', $this->post->title) ?></h2>

<?= $this->form_form($this->raw('form')) ?>
</section>

<?php $this->replace() ?>
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<div class="btn-group">
<a class="btn btn-default" title="<?= $this->text('regular-view') ?>" target="_blank" href="/project/<?= $this->project->id ?>/updates/<?= $post->getSLug() ?>#updates"><i class="icon icon-preview"></i></a>
<a class="btn btn-default" title="<?= $this->text('regular-edit') ?>" href="/dashboard/project/<?= $this->project->id ?>/updates/<?= $post->getSlug() ?>"><i class="icon icon-edit"></i></a>
<a class="btn btn-default" title="<?= $this->text('regular-privacy') ?>" href="/dashboard/project/<?= $this->project->id ?>/updates/<?= $post->getSlug() ?>/privacy"><i class="fa fa-key"></i></a>
<?php
if($this->languages) {
echo $this->insert('dashboard/partials/translate_menu', ['no_title' => true, 'btn_class' => 'btn-default', 'base_link' => '/dashboard/project/' . $this->project->id . '/updates/' . $post->getSlug() . '/', 'translated' => $post->getLangsAvailable(), 'percentModel' => $post]);
Expand Down
88 changes: 65 additions & 23 deletions Resources/templates/responsive/project/updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,33 +47,75 @@
<?php endif; ?>
</div>

<?php if($update->post): ?>
<div class="col-sm-9 col-xs-8 content">
<a class="pronto" data-pronto-target="#project-tabs" href="<?= '/project/'.$this->project->id.'/updates/'.$update->post->getSlug() ?>">
<h2><?= $update->post->title ?></h2>
</a>

<?php if (!empty($update->post->media->url)) :
$embed = $update->post->media->getEmbedCode();
if (!empty($embed)) : ?>
<div class="embed-responsive embed-responsive-16by9 spacer-20">
<?= $embed; ?>
</div>
<?php if($update->post):
$post = $update->post;
$user = $this->get_user();
if (!$user)
$canAccess = $post->userCanAccessPost();
else
$canAccess = $post->userCanAccessPost($user);

if ($canAccess) :
?>
<div class="col-sm-9 col-xs-8 content">
<a class="pronto" data-pronto-target="#project-tabs" href="<?= '/project/'.$this->project->id.'/updates/'.$update->post->getSlug() ?>">
<h2><?= $update->post->title ?></h2>
</a>

<?php if (!empty($update->post->media->url)) :
$embed = $update->post->media->getEmbedCode();
if (!empty($embed)) : ?>
<div class="embed-responsive embed-responsive-16by9 spacer-20">
<?= $embed; ?>
</div>
<?php endif; ?>
<?php endif; ?>
<?php endif; ?>

<?php if($update->post->text): ?>
<div class="description spacer-20">
<?= $this->markdown($this->text_truncate($this->text_plain($update->post->text), 250)) ?>
<a class="pronto" data-pronto-target="#project-tabs" href="<?= '/project/'.$this->project->id.'/updates/'.$update->post->getSlug() ?>"><span class="read-more">[<?= $this->text('regular-read_more') ?>]</span></a>
</div>
<?php endif ?>
<?php if($update->post->num_comments): ?>
<div class="comments spacer-20">
<?= sprintf("%02d", $update->post->num_comments).' '.$this->text('blog-coments-header') ?>
<?php if($update->post->text): ?>
<div class="description spacer-20">
<?= $this->markdown($this->text_truncate($this->text_plain($update->post->text), 250)) ?>
<a class="pronto" data-pronto-target="#project-tabs" href="<?= '/project/'.$this->project->id.'/updates/'.$update->post->getSlug() ?>"><span class="read-more">[<?= $this->text('regular-read_more') ?>]</span></a>
</div>
<?php endif ?>
<?php if($update->post->num_comments): ?>
<div class="comments spacer-20">
<?= sprintf("%02d", $update->post->num_comments).' '.$this->text('blog-coments-header') ?>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<article class="col-sm-9 col-xs-8 content">
<h2>
<a class="pronto"
data-pronto-target="#project-tabs"
href="<?= '/project/'.$this->project->id.'/updates/'.$update->post->getSlug() ?>">
<?= $update->post->title ?>
</a>
</h2>

<strong>
<i class="fa fa-2x fa-lock"></i>
<?= $this->t('project-updates-access-restricted'); ?>
</strong>

<?php
$postRewardAccessList = $post->getRewardsThatCanAccessPost();
if ($postRewardAccessList):
?>
<ul>
<?php foreach($postRewardAccessList as $postRewardAccess):
$reward = $postRewardAccess->getReward();
?>
<li>
<a href="<?= "#reward-$reward->id" ?>">
<?= $reward->reward ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</article>
<?php endif; ?>
</div>
<?php else: ?>
<div class="col-sm-9 col-xs-8 milestone-content">

Expand Down
30 changes: 30 additions & 0 deletions Resources/templates/responsive/project/updates_post.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php $this->layout('project/layout') ?>
<?php $this->section('main-content') ?>

<?php if ($this->canUserAccess): ?>
<div class="widget post">
<h2 class="title"><?= $this->post->title ?></h2>
<div class="date"><?= $this->post->fecha ?></div>
Expand Down Expand Up @@ -105,5 +106,34 @@

</div>
<!-- End widget -->
<?php else: ?>
<div class="widget post">
<h2 class="title"><?= $this->post->title ?></h2>
<div class="date"><?= $this->post->fecha ?></div>

<strong>
<i class="fa fa-2x fa-lock"></i>
<?= $this->t('project-updates-access-restricted') ?>
</strong>

<?php
$postRewardAccessList = $this->post->getRewardsThatCanAccessPost();
if ($postRewardAccessList):
?>
<ul>
<?php foreach($postRewardAccessList as $postRewardAccess):
$reward = $postRewardAccess->getReward();
?>
<li>
<a href="<?= "#reward-$reward->id" ?>">
<?= $reward->reward ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>

</div>
<?php endif; ?>

<?php $this->replace() ?>
61 changes: 61 additions & 0 deletions db/migrations/20231030152314_goteo_create_post_reward_access.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
/**
* Migration Task class.
*/
class GoteoCreatePostRewardAccess
{
public function preUp()
{
// add the pre-migration code here
}

public function postUp()
{
// add the post-migration code here
}

public function preDown()
{
// add the pre-migration code here
}

public function postDown()
{
// add the post-migration code here
}

/**
* Return the SQL statements for the Up migration
*
* @return string The SQL string to execute for the Up migration.
*/
public function getUpSQL()
{
// return sql query to create table that links post with reward to grant access to the post content
return "
ALTER TABLE `post` ADD COLUMN `access_limited` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `allow`;
CREATE TABLE `post_reward_access` (
`post_id` bigint(20) unsigned NOT NULL,
`reward_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`post_id`, `reward_id`),
FOREIGN KEY (`post_id`) REFERENCES `post` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`reward_id`) REFERENCES `reward` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
";
}

/**
* Return the SQL statements for the Down migration
*
* @return string The SQL string to execute for the Down migration.
*/
public function getDownSQL()
{
return "
DROP TABLE `post_reward_access`;
ALTER TABLE `post` DROP COLUMN `access_limited`;
";
}

}
57 changes: 57 additions & 0 deletions src/Goteo/Controller/Dashboard/ProjectDashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
use Goteo\Library\Forms\Model\ProjectOverviewForm;
use Goteo\Library\Forms\Model\ProjectPersonalForm;
use Goteo\Library\Forms\Model\ProjectPostForm;
use Goteo\Library\Forms\Model\ProjectPostPrivacyForm;
use Goteo\Library\Forms\Model\ProjectRewardsForm;
use Goteo\Library\Forms\Model\ProjectStoryForm;
use Goteo\Library\Text;
use Goteo\Model\Blog;
use Goteo\Model\Blog\Post as BlogPost;
use Goteo\Model\Blog\Post\PostRewardAccess;
use Goteo\Model\Call;
use Goteo\Model\Footprint;
use Goteo\Model\Invest;
Expand All @@ -43,6 +45,7 @@
use Goteo\Model\Node;
use Goteo\Model\Project;
use Goteo\Model\Project\Account;
use Goteo\Model\Project\Conf;
use Goteo\Model\Project\Cost;
use Goteo\Model\Project\Image as ProjectImage;
use Goteo\Model\Project\Reward;
Expand Down Expand Up @@ -90,6 +93,7 @@ static function createProjectSidebar(Project $project, $zone = '', &$form = null
['text' => '<i class="fa fa-2x fa-sliders"></i> 6. ' . Text::get('project-campaign'), 'link' => $prefix . '/campaign', 'id' => 'campaign', 'class' => $validation->campaign == 100 ? 'ok' : 'ko'],
['text' => '<i class="icon icon-2x icon-supports"></i> ' . Text::get('dashboard-menu-projects-supports'), 'link' => $prefix . '/supports', 'id' => 'supports'],
];

Session::addToSidebarMenu('<i class="icon icon-2x icon-projects"></i> ' . Text::get('project-edit'), $steps, 'project', null, 'sidebar' . ($admin ? ' admin' : ''));
}

Expand Down Expand Up @@ -425,6 +429,59 @@ public function updatesEditAction($pid, $uid, Request $request) {
]);
}

public function updatesPrivacyAction(Request $request, string $pid, string $uid): Response
{
$project = $this->validateProject($pid, 'updates');
if($project instanceOf Response) return $project;

$post = BlogPost::getBySlug($uid);

$filters = ['post' => $post->id];
$total = PostRewardAccess::count($filters);
$postRewardAccessList = PostRewardAccess::getList($filters, 0, $total);

return $this->viewResponse('dashboard/project/privacy', [
'rewards' => $postRewardAccessList,
'total' => $total,
'post' => $post,
'project' => $project
]);

}

public function updatesPrivacyAddAction(Request $request, string $pid, string $uid): Response
{
$project = $this->validateProject($pid, 'updates');
if($project instanceOf Response) return $project;

$post = BlogPost::getBySlug($uid);

$formOptions = [
'project' => $project,
'post' => $post,
];

$processor = $this->getModelForm(ProjectPostPrivacyForm::class, new PostRewardAccess(), [], $formOptions);
$processor->createForm();
$form = $processor->getBuilder()->getForm();

$form->handleRequest($request);
if ($form->isSubmitted() && $request->isMethod(Request::METHOD_POST)) {
try {
$processor->save($form);
return $this->redirect("/dashboard/project/{$project->id}/updates/privacy/{$post->id}");
} catch(FormModelException $e) {
Message::error($e->getMessage());
}
}

return $this->viewResponse('dashboard/project/privacy/new', [
'form' => $form->createView(),
]);

}


public function costsAction($pid, Request $request) {
$project = $this->validateProject($pid, 'costs');
if($project instanceOf Response) return $project;
Expand Down
5 changes: 5 additions & 0 deletions src/Goteo/Controller/ProjectController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Goteo\Controller\Dashboard\ProjectDashboardController;
use Goteo\Core\Controller;
use Goteo\Core\DB;
use Goteo\Library\PostPrivacyAccess;
use Goteo\Library\Text;
use Goteo\Library\Worth;
use Goteo\Model\Blog;
Expand Down Expand Up @@ -277,7 +278,11 @@ protected function view(Request $request, $project, $show, $post = null) {
case 'updates':
//if is an individual post page
if ($post) {
/** @var BlogPost $pob */
$pob = BlogPost::getBySlug($post, Lang::current(), $project->lang);

$viewData['canUserAccess'] = PostPrivacyAccess::canAccess($user, $pob);

if($pob->slug && $post != $pob->slug) {
return $this->redirect("/project/{$project->id}/updates/{$pob->slug}");
}
Expand Down
Loading

0 comments on commit c9715e6

Please sign in to comment.