├── .gitignore
├── .travis.yml
├── Controller
└── VoteController.php
├── DependencyInjection
├── Configuration.php
└── MsalsasVotingExtension.php
├── Entity
├── Click.php
├── ClickRepository.php
├── ReferenceClicks.php
├── ReferenceClicksRepository.php
├── ReferenceVotes.php
├── ReferenceVotesRepository.php
├── Vote
│ └── AbstractVote.php
├── VoteNegative.php
├── VotePositive.php
└── VoteRepository.php
├── LICENSE
├── MsalsasVotingBundle.php
├── README.md
├── Resources
├── config
│ ├── doctrine
│ │ ├── Click.orm.xml
│ │ ├── ReferenceClicks.orm.xml
│ │ ├── ReferenceVotes.orm.xml
│ │ ├── VoteNegative.orm.xml
│ │ └── VotePositive.orm.xml
│ ├── routing
│ │ └── msalsas_voting.xml
│ └── services.xml
├── doc
│ ├── clicks_or_views.rst
│ ├── configuration_reference.rst
│ ├── index.rst
│ ├── publish.rst
│ └── screenshot-1.png
├── public
│ ├── css
│ │ └── msalsas_voting_styles.css
│ └── js
│ │ ├── msalsas_voting_bottomBar.js
│ │ └── msalsas_voting_shakeIt.js
├── translations
│ ├── messages.en.yml
│ └── messages.es.yml
└── views
│ └── msalsas_voting_widget.html.twig
├── Service
├── Clicker.php
└── Voter.php
├── Tests
├── DependencyInjection
│ └── MsalsasVotingExtensionTest.php
├── Entity
│ ├── ClickTest.php
│ ├── ReferenceClicksTest.php
│ ├── ReferenceVotesTest.php
│ ├── VoteNegativeTest.php
│ └── VotePositiveTest.php
├── Mock
│ ├── AnonymousUserMock.php
│ ├── ClickMock.php
│ ├── UserMock.php
│ ├── VoteNegativeMock.php
│ └── VotePositiveMock.php
├── Service
│ ├── AbstractServiceTest.php
│ ├── ClickerTest.php
│ └── VoterTest.php
└── bootstrap.php
├── composer.json
└── phpunit.xml.dist
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.lock
2 | vendor
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | sudo: false
3 | cache:
4 | directories:
5 | - $HOME/.composer/cache/files
6 | - $HOME/symfony-bridge/.phpunit
7 |
8 | env:
9 | global:
10 | - PHPUNIT_FLAGS="-v"
11 | - SYMFONY_PHPUNIT_DIR="$HOME/symfony-bridge/.phpunit"
12 |
13 | matrix:
14 | fast_finish: true
15 | include:
16 | # Minimum supported dependencies with the latest and oldest PHP version
17 | - php: 7.2
18 | env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
19 |
20 | # Test the latest stable release
21 | - php: 7.1
22 | - php: 7.2
23 | env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text"
24 |
25 | # Latest commit to master
26 | - php: 7.2
27 | env: STABILITY="dev"
28 |
29 | allow_failures:
30 | # Dev-master is allowed to fail.
31 | - env: STABILITY="dev"
32 |
33 | before_install:
34 | - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
35 | - if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi;
36 | - if ! [ -v "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi;
37 |
38 | install:
39 | # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
40 | - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
41 | - composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
42 | - ./vendor/bin/simple-phpunit install
43 |
44 | script:
45 | - composer validate --strict --no-check-lock
46 | # simple-phpunit is the PHPUnit wrapper provided by the PHPUnit Bridge component and
47 | # it helps with testing legacy code and deprecations (composer require symfony/phpunit-bridge)
48 | - ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
--------------------------------------------------------------------------------
/Controller/VoteController.php:
--------------------------------------------------------------------------------
1 | voter = $voter;
29 | }
30 |
31 | public function votePositive($id, Request $request)
32 | {
33 | if (!$request->isXmlHttpRequest()) {
34 | throw new AccessDeniedException();
35 | }
36 |
37 | try {
38 | $votesCount = $this->voter->votePositive($id);
39 | } catch (AccessDeniedException $e) {
40 | return $this->json($e->getMessage(), 403);
41 | } catch (\Exception $e) {
42 | return $this->json($e->getMessage(), 403);
43 | }
44 |
45 | return $this->json($votesCount);
46 | }
47 |
48 | public function voteNegative($id, Request $request)
49 | {
50 | if (!$request->isXmlHttpRequest()) {
51 | throw new AccessDeniedException();
52 | }
53 |
54 | $reason = $request->getContent();
55 | if (!$reason || !is_string($reason) || !in_array($reason, $this->voter->getNegativeReasons())) {
56 | throw new AccessDeniedException();
57 | }
58 |
59 | try {
60 | $votesCount = $this->voter->voteNegative($id, $reason);
61 | } catch (AccessDeniedException $e) {
62 | return $this->json($e->getMessage(), 403);
63 | } catch (\Exception $e) {
64 | return $this->json($e->getMessage(), 403);
65 | }
66 |
67 | return $this->json($votesCount);
68 | }
69 | }
--------------------------------------------------------------------------------
/DependencyInjection/Configuration.php:
--------------------------------------------------------------------------------
1 | root('msalsas_voting');
29 | $rootNode->children()
30 | ->scalarNode('user_provider')
31 | ->isRequired()
32 | ->defaultValue('\App\Entity\User')
33 | ->end()
34 | ->arrayNode('negative_reasons')
35 | ->isRequired()
36 | ->scalarPrototype()
37 | ->defaultValue([
38 | 'msalsas_voting.negative_reasons.irrelevant',
39 | 'msalsas_voting.negative_reasons.old',
40 | 'msalsas_voting.negative_reasons.tiredness',
41 | 'msalsas_voting.negative_reasons.sensationalist',
42 | 'msalsas_voting.negative_reasons.spam',
43 | 'msalsas_voting.negative_reasons.duplicated',
44 | 'msalsas_voting.negative_reasons.microblogging',
45 | 'msalsas_voting.negative_reasons.erroneous',
46 | 'msalsas_voting.negative_reasons.plagiarism',
47 | ])
48 | ->end()
49 | ->end()
50 | ->integerNode('anonymous_percent_allowed')
51 | ->isRequired()
52 | ->defaultValue(2)
53 | ->min(1)
54 | ->end()
55 | ->integerNode('anonymous_min_allowed')
56 | ->isRequired()
57 | ->defaultValue(50)
58 | ->min(1)
59 | ->end()
60 | ->end();
61 |
62 | return $builder;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/DependencyInjection/MsalsasVotingExtension.php:
--------------------------------------------------------------------------------
1 | load('services.xml');
27 | $config = $this->processConfiguration(new Configuration(), $configs);
28 | $container->setParameter('msalsas_voting.negative_reasons', $config['negative_reasons']);
29 | $container->setParameter('msalsas_voting.anonymous_percent_allowed', $config['anonymous_percent_allowed']);
30 | $container->setParameter('msalsas_voting.anonymous_min_allowed', $config['anonymous_min_allowed']);
31 | }
32 |
33 | public function prepend(ContainerBuilder $container)
34 | {
35 | $configs = $container->getExtensionConfig($this->getAlias());
36 | $config = $this->processConfiguration(new Configuration(), $configs);
37 |
38 | $doctrineConfig = [];
39 | $doctrineConfig['orm']['resolve_target_entities']['Msalsas\VotingBundle\Entity\Vote\UserInterface'] = $config['user_provider'];
40 | $doctrineConfig['orm']['mappings'][] = array(
41 | 'name' => 'MsalsasVotingBundle',
42 | 'is_bundle' => true,
43 | 'type' => 'xml',
44 | 'prefix' => 'Msalsas\VotingBundle\Entity'
45 | );
46 | $container->prependExtensionConfig('doctrine', $doctrineConfig);
47 |
48 | $twigConfig = [];
49 | $twigConfig['globals']['msalsas_voting_voter'] = "@msalsas_voting.voter";
50 | $twigConfig['globals']['msalsas_voting_clicker'] = "@msalsas_voting.clicker";
51 | $twigConfig['paths'][__DIR__.'/../Resources/views'] = "msalsas_voting";
52 | $twigConfig['paths'][__DIR__.'/../Resources/public'] = "msalsas_voting.public";
53 | $container->prependExtensionConfig('twig', $twigConfig);
54 | }
55 |
56 | public function getAlias()
57 | {
58 | return 'msalsas_voting';
59 | }
60 | }
--------------------------------------------------------------------------------
/Entity/Click.php:
--------------------------------------------------------------------------------
1 | id;
45 | }
46 |
47 | /**
48 | * @param int $id
49 | */
50 | public function setId(int $id)
51 | {
52 | $this->id = $id;
53 | }
54 |
55 | /**
56 | * @return null|UserInterface
57 | */
58 | public function getUser()
59 | {
60 | return $this->user;
61 | }
62 |
63 | /**
64 | * @param null|UserInterface $user
65 | */
66 | public function setUser($user)
67 | {
68 | $this->user = $user;
69 | }
70 |
71 | /**
72 | * @return int
73 | */
74 | public function getReference(): int
75 | {
76 | return $this->reference;
77 | }
78 |
79 | /**
80 | * @param int $reference
81 | */
82 | public function setReference(int $reference)
83 | {
84 | $this->reference = $reference;
85 | }
86 |
87 | /**
88 | * @return string
89 | */
90 | public function getUserIP(): string
91 | {
92 | return $this->userIP;
93 | }
94 |
95 | /**
96 | * @param string $userIP
97 | */
98 | public function setUserIP(string $userIP)
99 | {
100 | $this->userIP = $userIP;
101 | }
102 |
103 | }
--------------------------------------------------------------------------------
/Entity/ClickRepository.php:
--------------------------------------------------------------------------------
1 | reference;
33 | }
34 |
35 | /**
36 | * @param int $reference
37 | */
38 | public function setReference(int $reference)
39 | {
40 | $this->reference = $reference;
41 | }
42 |
43 | /**
44 | * @return int
45 | */
46 | public function getClicks(): int
47 | {
48 | return $this->clicks;
49 | }
50 |
51 | /**
52 | * @param int $clicks
53 | */
54 | public function setClicks(int $clicks)
55 | {
56 | $this->clicks = $clicks;
57 | }
58 |
59 | public function addClick()
60 | {
61 | $this->clicks++;
62 | }
63 | }
--------------------------------------------------------------------------------
/Entity/ReferenceClicksRepository.php:
--------------------------------------------------------------------------------
1 | reference;
53 | }
54 |
55 | /**
56 | * @param int $reference
57 | */
58 | public function setReference(int $reference)
59 | {
60 | $this->reference = $reference;
61 | }
62 |
63 | /**
64 | * @return int
65 | */
66 | public function getPositiveVotes(): int
67 | {
68 | return $this->positiveVotes;
69 | }
70 |
71 | /**
72 | * @param int $positiveVotes
73 | */
74 | public function setPositiveVotes(int $positiveVotes)
75 | {
76 | $this->positiveVotes = $positiveVotes;
77 | }
78 |
79 | /**
80 | * @return int
81 | */
82 | public function getNegativeVotes(): int
83 | {
84 | return $this->negativeVotes;
85 | }
86 |
87 | /**
88 | * @param int $negativeVotes
89 | */
90 | public function setNegativeVotes(int $negativeVotes)
91 | {
92 | $this->negativeVotes = $negativeVotes;
93 | }
94 |
95 | /**
96 | * @return int
97 | */
98 | public function getUserVotes(): int
99 | {
100 | return $this->userVotes;
101 | }
102 |
103 | /**
104 | * @param int $userVotes
105 | */
106 | public function setUserVotes(int $userVotes)
107 | {
108 | $this->userVotes = $userVotes;
109 | }
110 |
111 | /**
112 | * @return int
113 | */
114 | public function getAnonymousVotes(): int
115 | {
116 | return $this->anonymousVotes;
117 | }
118 |
119 | /**
120 | * @param int $anonymousVotes
121 | */
122 | public function setAnonymousVotes(int $anonymousVotes)
123 | {
124 | $this->anonymousVotes = $anonymousVotes;
125 | }
126 |
127 | /**
128 | * @param boolean $positive
129 | * @param boolean $anonymous
130 | */
131 | public function addVote(bool $positive, $anonymous = true)
132 | {
133 | if ($positive) {
134 | $this->positiveVotes++;
135 | if ($anonymous) {
136 | $this->anonymousVotes++;
137 | } else {
138 | $this->userVotes++;
139 | }
140 | } else {
141 | $this->negativeVotes++;
142 | }
143 | }
144 |
145 | /**
146 | * @return boolean
147 | */
148 | public function isPublished(): bool
149 | {
150 | return $this->published;
151 | }
152 |
153 | /**
154 | * @param boolean $published
155 | */
156 | public function setPublished(bool $published)
157 | {
158 | $this->published = $published;
159 | }
160 | }
--------------------------------------------------------------------------------
/Entity/ReferenceVotesRepository.php:
--------------------------------------------------------------------------------
1 | id;
45 | }
46 |
47 | /**
48 | * @param int $id
49 | */
50 | public function setId(int $id)
51 | {
52 | $this->id = $id;
53 | }
54 |
55 | /**
56 | * @return string|UserInterface
57 | */
58 | public function getUser()
59 | {
60 | return $this->user;
61 | }
62 |
63 | /**
64 | * @param string|UserInterface $user
65 | */
66 | public function setUser($user)
67 | {
68 | $this->user = $user;
69 | }
70 |
71 | /**
72 | * @return int
73 | */
74 | public function getReference(): int
75 | {
76 | return $this->reference;
77 | }
78 |
79 | /**
80 | * @param int $reference
81 | */
82 | public function setReference(int $reference)
83 | {
84 | $this->reference = $reference;
85 | }
86 |
87 | /**
88 | * @return string|null
89 | */
90 | public function getUserIP(): string
91 | {
92 | return $this->userIP;
93 | }
94 |
95 | /**
96 | * @param string|null $userIP
97 | */
98 | public function setUserIP(string $userIP = null)
99 | {
100 | $this->userIP = $userIP;
101 | }
102 |
103 | public function isPositive()
104 | {
105 | if (get_class($this) === 'Msalsas\VotingBundle\Entity\VotePositive') {
106 | return true;
107 | }
108 |
109 | return false;
110 | }
111 | }
--------------------------------------------------------------------------------
/Entity/VoteNegative.php:
--------------------------------------------------------------------------------
1 | reason;
30 | }
31 |
32 | /**
33 | * @param string $reason
34 | */
35 | public function setReason(string $reason)
36 | {
37 | $this->reason = $reason;
38 | }
39 | }
--------------------------------------------------------------------------------
/Entity/VotePositive.php:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Resources/config/doctrine/ReferenceClicks.orm.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Resources/config/doctrine/ReferenceVotes.orm.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Resources/config/doctrine/VoteNegative.orm.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Resources/config/doctrine/VotePositive.orm.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Resources/config/routing/msalsas_voting.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | \d+
9 | msalsas_voting.controller.vote_positive
10 |
11 |
12 | \d+
13 | msalsas_voting.controller.vote_negative
14 |
15 |
--------------------------------------------------------------------------------
/Resources/config/services.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | %msalsas_voting.anonymous_percent_allowed%
20 | %msalsas_voting.anonymous_min_allowed%
21 | %msalsas_voting.negative_reasons%
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Resources/doc/clicks_or_views.rst:
--------------------------------------------------------------------------------
1 | MsalsasVotingBundle clicks or views
2 | ===================================
3 |
4 | For incrementing the clicks or views of a reference you have to type-hint the ``Clicker`` in a
5 | controller action and call ``addClick`` with the reference id (you will have to configure this route):
6 |
7 |
8 | .. code-block:: php
9 |
10 | addClick($post->getId());
15 |
16 | // ...
17 | }
18 |
19 | The ``addClick`` method will check if the user has already clicked. If it is an anonymous
20 | user, it will check for the client IP.
21 |
22 | If you want to make use of views instead of clicks, just override the clicks translation
23 | and call ``$clicker->addClick($post->getId())`` on the post view controller action.
24 |
25 |
26 | .. code-block:: php
27 |
28 | addClick($post->getId());
33 |
34 | // ...
35 | }
--------------------------------------------------------------------------------
/Resources/doc/configuration_reference.rst:
--------------------------------------------------------------------------------
1 | MsalsasVotingBundle Configuration Reference
2 | ===========================================
3 |
4 | All available configuration options are listed below with their default values.
5 |
6 | .. code-block:: yaml
7 |
8 | msalsas_voting:
9 | user_provider: \App\Entity\User
10 | negative_reasons:
11 | - msalsas_voting.negative_reasons.irrelevant
12 | - msalsas_voting.negative_reasons.old
13 | - msalsas_voting.negative_reasons.tiredness
14 | - msalsas_voting.negative_reasons.sensationalist
15 | - msalsas_voting.negative_reasons.spam
16 | - msalsas_voting.negative_reasons.duplicated
17 | - msalsas_voting.negative_reasons.microblogging
18 | - msalsas_voting.negative_reasons.erroneous
19 | - msalsas_voting.negative_reasons.plagiarism
20 | anonymous_percent_allowed: 50
21 | anonymous_min_allowed: 2
--------------------------------------------------------------------------------
/Resources/doc/index.rst:
--------------------------------------------------------------------------------
1 | Getting Started With MsalsasVotingBundle
2 | ========================================
3 |
4 | This bundle provides a way for voting posts or whatever.
5 |
6 | Prerequisites
7 | -------------
8 |
9 | This version of the bundle requires Symfony 4.0+.
10 |
11 | Translations
12 | ~~~~~~~~~~~~
13 |
14 | If you wish to use default texts provided in this bundle, you have to make
15 | sure you have translator enabled in your config.
16 |
17 | .. code-block:: yaml
18 |
19 | # config/packages/translation.yaml
20 |
21 | framework:
22 | translator: ~
23 |
24 | For more information about translations, check `Symfony documentation`_.
25 |
26 | .. _Symfony documentation: https://symfony.com/doc/current/book/translation.html
27 |
28 |
29 | Installation
30 | ------------
31 |
32 | Installation is a quick 7 step process (4 if you use Flex):
33 |
34 | 1. Download MsalsasVotingBundle using composer
35 | 2. Enable the Bundle
36 | 3. Create your Reference class (post, article or whatever)
37 | 4. Configure the MsalsasVotingBundle
38 | 5. Create MsalsasVotingBundle routing
39 | 6. Update your database schema
40 | 7. Display the widgets
41 |
42 |
43 | Step 1: Download MsalsasVotingBundle using composer
44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45 |
46 | Require the bundle with composer:
47 |
48 | .. code-block:: bash
49 |
50 | $ composer require msalsas/voting-bundle
51 |
52 | Composer will install the bundle to your project's ``vendor/msalsas/voting-bundle`` directory.
53 |
54 |
55 | Step 2: Enable the bundle
56 | ~~~~~~~~~~~~~~~~~~~~~~~~~
57 |
58 | .. note::
59 |
60 | If you're using Flex, this is done automatically
61 |
62 | Enable the bundle in the kernel:
63 |
64 |
166 | {{ msalsas_voting_widget.shakeIt(post.id) }} # Import the voting widget
167 |
172 |
173 | ...
174 |
175 | {{ msalsas_voting_widget.bottomBar(post.id) }} # Import bottom bar widget (includes negative voting form)
176 |
177 |
178 | Also, you have to import `Font Awesome`_ if you want to show the bottom bar icons
179 |
180 |
181 | Instead of using
182 |
183 | ``msalsas_voting_widget.shakeItCSS()``
184 |
185 | ``msalsas_voting_widget.shakeItJS()``
186 |
187 | you can import
188 |
189 | ``vendor/msalsas/voting-bundle/Resources/public/css/msalsas_voting_styles.css``
190 |
191 | ``vendor/msalsas/voting-bundle/Resources/public/js/msalsas_voting_shakeIt.js``
192 |
193 | with your assets.
194 |
195 | If you don't use ``shakeItModal`` errors will be displayed with ``alert``.
196 |
197 | .. _Font Awesome: https://fontawesome.com/how-to-use/on-the-web/setup/getting-started?using=web-fonts-with-css
198 |
199 |
200 | Next Steps
201 | ~~~~~~~~~~
202 |
203 | Now that you have completed the basic installation and configuration of the
204 | MsalsasVotingBundle, you are ready to learn about more advanced features and usages
205 | of the bundle.
206 |
207 | The following documents are available:
208 |
209 | `1. Clicks or views`_.
210 |
211 | `2. Publishing`_.
212 |
213 | `3. Configuration reference`_.
214 |
215 | .. _1. Clicks or views: ./clicks_or_views.rst
216 | .. _2. Publishing: ./publish.rst
217 | .. _3. Configuration reference: ./configuration_reference.rst
218 |
219 |
--------------------------------------------------------------------------------
/Resources/doc/publish.rst:
--------------------------------------------------------------------------------
1 | MsalsasVotingBundle publishing
2 | ==============================
3 |
4 | For displaying the published style for a reference you have to set it to published from a controller
5 | type-hinting the ``Voter`` and calling ``setPublished``:
6 |
7 |
8 | .. code-block:: php
9 |
10 | setPublished($post->getId());
15 |
16 | // ...
17 | }
18 |
19 |
20 | You can also use ``isPublished`` method.
21 |
22 | Let's say you want to show all published posts in a page. You could use the repository to find them:
23 |
24 | .. code-block:: php
25 |
26 | em->getRepository(ReferenceVotes::class)->findBy(array('published' => true));
29 |
30 |
31 | ``$referenceVotes`` will be an array of ``ReferenceVotes``, and you can get the reference id with:
32 |
33 |
34 | .. code-block:: php
35 |
36 | em->getRepository(ReferenceVotes::class)->findBy(array('published' => true));
39 | foreach ($referenceVotes as $referenceVote) {
40 | $id = $referenceVote->getReference();
41 | }
--------------------------------------------------------------------------------
/Resources/doc/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msalsas/MsalsasVotingBundle/41a50b596f3e9e8fc2c829b035162e834efaa03c/Resources/doc/screenshot-1.png
--------------------------------------------------------------------------------
/Resources/public/css/msalsas_voting_styles.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the MsalsasVotingBundle package.
3 | *
4 | * (c) Manolo Salsas
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | .msalsas-voting-widget-wrapper {
11 | display: inline-block;
12 | }
13 | .msalsas-voting-widget {
14 | font-size: 12px;
15 | color: #e35614;
16 | text-align: center;
17 | background-clip: padding-box;
18 | border-radius: 3px;
19 | font-family: 'Open Sans', sans-serif;
20 | width: 67px;
21 | }
22 | .msalsas-voting-shakes {
23 | background-color: #fff;
24 | padding: 6px 0 6px;
25 | border: 1px solid #FF883D;
26 | border-bottom: 0;
27 | line-height: 1.2em;
28 | background-repeat: repeat-x;
29 | background-position: 0 -2px;
30 | background-clip: padding-box;
31 | border-radius: 3px 3px 0 0;
32 | font-weight: bold;
33 |
34 | }
35 | .msalsas-voting-shakes.published {
36 | background-color: #FFE8D8;
37 | border: none;
38 | }
39 | .msalsas-voting-shakes a {
40 | display: block;
41 | color: #e35614;
42 | font-size: 18px;
43 | text-decoration: none;
44 | font-weight: bold;
45 | }
46 | .msalsas-voting-shake-it {
47 | overflow: hidden;
48 | display: block;
49 | height: 25px;
50 | position: relative;
51 | left: -6px;
52 | width: 78px;
53 | }
54 | .msalsas-voting-shake-it a, .msalsas-voting-shake-it span {
55 | background-color: #e35614;
56 | padding-top: 3px;
57 | display: block;
58 | box-sizing: border-box;
59 | height: 25px;
60 | color: #FFF;
61 | text-decoration: none;
62 | font-weight: bold;
63 | border-radius: 3px;
64 | }
65 | .msalsas-voting-shake-it a {
66 | background-image: linear-gradient(180deg, #F5720E 0%, #FE4A00 100%);
67 | box-shadow: 0 1px 2px 0 #C43E0B;
68 | border: 1px solid rgba(122, 47, 11, 0.45);
69 | }
70 | .msalsas-voting-shake-it span {
71 | background-image: none;
72 | border: 1px solid #ff6300;
73 | border-bottom: 1px solid #ff914a;
74 | }
75 | .msalsas-voting-clicks {
76 | background-color: #fff;
77 | padding: 1px 0 2px 0;
78 | border: 1px solid #FF883D;
79 | border-top: 0;
80 | font-size: 10px;
81 | background-repeat: repeat-x;
82 | background-position: bottom;
83 | background-clip: padding-box;
84 | border-radius: 0 0 3px 3px;
85 | font-weight: bold;
86 | }
87 | .msalsas-voting-clicks.published {
88 | background-color: #FFE8D8;
89 | border: none;
90 | }
91 | .msalsas-voting-bottom-bar-wrapper {
92 | font-family: 'Open Sans', sans-serif;
93 | float: right;
94 | margin-right: 50px;
95 | display: inline-block;
96 | padding: 0;
97 | color: #3c3c3c;
98 | border-top: 1px solid #FEE7DB;
99 | border-bottom: 1px solid #FEE7DB;
100 | height: 32px;
101 | }
102 | .msalsas-voting-bottom-bar-wrapper span {
103 | padding-right: 5px;
104 | font-size: 11px;
105 | font-weight: bold;
106 | line-height: 30px;
107 | }
108 | .msalsas-voting-bottom-bar-wrapper span i {
109 | color: #ffa980;
110 | }
111 | .msalsas-voting-bottom-bar-votes-up {
112 | margin-left: 10px;
113 | }
114 | .msalsas-voting-bottom-bar form {
115 | display: inline-block;
116 | margin-left: 10px;
117 | padding: 0;
118 | border-left: 1px solid #D8D8D8;
119 | }
120 | .msalsas-voting-bottom-bar form select {
121 | background: #FFF;
122 | color: #e35614;
123 | border: 0;
124 | font-size: 11px;
125 | width: 75px;
126 | border-radius: 0;
127 | }
128 |
129 | /*Modal*/
130 | #msalsas-modal {
131 | display: none; /* Hidden by default */
132 | position: fixed; /* Stay in place */
133 | z-index: 1; /* Sit on top */
134 | left: 0;
135 | top: 0;
136 | width: 100%;
137 | height: 100%;
138 | overflow: auto;
139 | background-color: rgb(0,0,0);
140 | background-color: rgba(0,0,0,0.4);
141 | }
142 |
143 | /* Modal Content/Box */
144 | .msalsas-modal-content {
145 | background-color: #FFEEC7;
146 | margin: 15% auto;
147 | padding: 20px;
148 | border: 1px solid #e35614;
149 | min-width: 250px;
150 | text-align: center;
151 | width: 25%;
152 | height: 18.5ex;
153 | overflow: hidden;
154 | border-radius: 3px;
155 | }
156 | #msalsas-modal-text {
157 | font-weight: bold;
158 | font-size: 20px;
159 | margin-top: 30px;
160 | text-align: center;
161 | }
162 |
163 | .msalsas-close {
164 | color: #aaa;
165 | float: right;
166 | font-size: 28px;
167 | font-weight: bold;
168 | line-height: 15px;
169 | }
170 |
171 | .msalsas-close:hover,
172 | .msalsas-close:focus {
173 | color: black;
174 | text-decoration: none;
175 | cursor: pointer;
176 | }
--------------------------------------------------------------------------------
/Resources/public/js/msalsas_voting_bottomBar.js:
--------------------------------------------------------------------------------
1 | // This file is part of the MsalsasVotingBundle package.
2 | //
3 | // (c) Manolo Salsas
4 | //
5 | // For the full copyright and license information, please view the LICENSE
6 | // file that was distributed with this source code.
7 |
8 | (function() {
9 | document.addEventListener('DOMContentLoaded', function() {
10 | var voteNegativeForm = document.querySelectorAll('.msalsas-voting-bottom-bar form');
11 | for (var i = 0; i < voteNegativeForm.length; i++) {
12 | if (voteNegativeForm[i].addEventListener) {
13 | voteNegativeForm[i].addEventListener('change', voteNegative, false);
14 | } else {
15 | voteNegativeForm[i].attachEvent('onchange', voteNegative);
16 | }
17 | }
18 | });
19 |
20 | function voteNegative(evt) {
21 | var form = evt.target.parentNode;
22 | var id = form.dataset.id;
23 | var options = form.ratings.options;
24 | window.msalsasVoting_Selected = options[form.ratings.selectedIndex];
25 | var elem = document.getElementById('msalsas-voting-problem-' + id);
26 | var url = elem.dataset.url;
27 | var http = new XMLHttpRequest();
28 | http.open('POST', url, true);
29 | http.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
30 |
31 | http.onreadystatechange = function() {
32 | if(http.readyState == 4 && http.status == 200) {
33 | var downVotes = document.getElementById('msalsas-voting-bottom-bar-votes-down-' + id);
34 | downVotes.innerHTML = document.createTextNode(http.responseText).wholeText;
35 | var buttonElem = document.getElementById('msalsas-voting-a-shake-' + id);
36 | buttonElem.innerHTML = '' + window.msalsasVoting_Selected.text + '';
37 | } else if(http.readyState == 4 && http.status >= 400) {
38 | if (http.responseText.length < 50) {
39 | showModal(http.responseText);
40 | } else {
41 | showModal('Error');
42 | }
43 | }
44 | };
45 | if (window.msalsasVoting_Selected.value !== '0') {
46 | http.send(window.msalsasVoting_Selected.value);
47 | }
48 | }
49 |
50 | function showModal(message) {
51 | message = message.replace (/(^")|("$)/g, '');
52 | var modal = document.getElementById('msalsas-modal');
53 | var span = document.getElementsByClassName("msalsas-close")[0];
54 |
55 | if (!modal || !span) {
56 | alert(message);
57 | return;
58 | }
59 | document.getElementById('msalsas-modal-text').innerText = message;
60 | modal.style.display = "block";
61 |
62 | if (span.addEventListener) {
63 | span.addEventListener('click', closeModal, false);
64 | } else {
65 | span.attachEvent('onclick', closeModal);
66 | }
67 |
68 | if (window.addEventListener) {
69 | window.addEventListener('click', closeModal, false);
70 | } else {
71 | window.attachEvent('onclick', closeModal);
72 | }
73 | }
74 |
75 | function closeModal(event) {
76 | var modal = document.getElementById('msalsas-modal');
77 | var span = document.getElementsByClassName("msalsas-close")[0];
78 | if (event.target === modal || event.target === span) {
79 | modal.style.display = "none";
80 | }
81 | }
82 | })();
--------------------------------------------------------------------------------
/Resources/public/js/msalsas_voting_shakeIt.js:
--------------------------------------------------------------------------------
1 | // This file is part of the MsalsasVotingBundle package.
2 | //
3 | // (c) Manolo Salsas
4 | //
5 | // For the full copyright and license information, please view the LICENSE
6 | // file that was distributed with this source code.
7 |
8 | (function() {
9 | document.addEventListener('DOMContentLoaded', function() {
10 | var shakeItLink = document.querySelectorAll('.msalsas-voting-shake-it a');
11 | for (var i = 0; i < shakeItLink.length; i++) {
12 | if (shakeItLink[i].addEventListener) {
13 | shakeItLink[i].addEventListener('click', shakeIt, false);
14 | } else {
15 | shakeItLink[i].attachEvent('onclick', shakeIt);
16 | }
17 | }
18 | });
19 |
20 | function shakeIt(evt) {
21 | var shakeItButton = evt.target.parentNode;
22 | var id = shakeItButton.dataset.id;
23 | var url = shakeItButton.dataset.url;
24 | var shakenText = shakeItButton.dataset.shakentext;
25 | var http = new XMLHttpRequest();
26 | http.open('POST', url, true);
27 | http.setRequestHeader('Content-type', 'application/json');
28 | http.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
29 |
30 | http.onreadystatechange = function() {
31 | if(http.readyState == 4 && http.status == 200) {
32 | var shakesElem = document.getElementById('msalsas-voting-shakes-' + id);
33 | shakesElem.text = document.createTextNode(http.responseText).wholeText;
34 | var buttonElem = document.getElementById('msalsas-voting-a-shake-' + id);
35 | buttonElem.innerHTML = '' + shakenText + '';
36 | } else if(http.readyState == 4 && http.status >= 400) {
37 | showModal(http.responseText);
38 | }
39 | };
40 | http.send();
41 | }
42 |
43 | function showModal(message) {
44 | message = message.replace (/(^")|("$)/g, '');
45 | var modal = document.getElementById('msalsas-modal');
46 | var span = document.getElementsByClassName("msalsas-close")[0];
47 |
48 | if (!modal || !span) {
49 | alert(message);
50 | return;
51 | }
52 | document.getElementById('msalsas-modal-text').innerText = message;
53 | modal.style.display = "block";
54 |
55 | if (span.addEventListener) {
56 | span.addEventListener('click', closeModal, false);
57 | } else {
58 | span.attachEvent('onclick', closeModal);
59 | }
60 |
61 | if (window.addEventListener) {
62 | window.addEventListener('click', closeModal, false);
63 | } else {
64 | window.attachEvent('onclick', closeModal);
65 | }
66 | }
67 |
68 | function closeModal(event) {
69 | var modal = document.getElementById('msalsas-modal');
70 | var span = document.getElementsByClassName("msalsas-close")[0];
71 | if (event.target === modal || event.target === span) {
72 | modal.style.display = "none";
73 | }
74 | }
75 | })();
--------------------------------------------------------------------------------
/Resources/translations/messages.en.yml:
--------------------------------------------------------------------------------
1 | msalsas_voting:
2 | votes: shakes
3 | shake_it: shake it
4 | shaken: shaken
5 | clicks: "{0} %count% clicks|{1} %count% click|]1,Inf[ %count% clicks"
6 | problem: problem
7 | positive_votes: Positive votes
8 | anonymous_votes: Anonymous votes
9 | negative_votes: Negative votes
10 | negative_reasons:
11 | irrelevant: irrelevant
12 | old: old
13 | tiredness: tiredness
14 | sensationalist: sensationalist
15 | spam: spam
16 | duplicated: duplicated
17 | microblogging: microblogging
18 | erroneous: erroneous
19 | plagiarism: copy/plagiarism
20 | errors:
21 | anon_cannot_vote_negative: 'Anonymous user cannot vote negative.'
22 | ref_does_not_exist: 'Reference %reference% does not exist.'
23 | no_ip_defined_for_anon: 'No IP has been defined for anonymous user.'
24 | already_voted: 'You have already voted.'
25 | already_clicked: 'You have already clicked.'
26 | too_much_anon_votes: 'Too much anonymous votes.'
27 | invalid_reason: 'Invalid reason.'
28 |
--------------------------------------------------------------------------------
/Resources/translations/messages.es.yml:
--------------------------------------------------------------------------------
1 | msalsas_voting:
2 | votes: meneos
3 | shake_it: menéalo
4 | shaken: ¡hecho!
5 | clicks: "{0} %count% clics|{1} %count% clic|]1,Inf[ %count% clics"
6 | problem: problema
7 | positive_votes: Votos positivos
8 | anonymous_votes: Votos anónimos
9 | negative_votes: Votos negativos
10 | negative_reasons:
11 | irrelevant: irrelevante
12 | old: antigua
13 | tiredness: cansina
14 | sensationalist: sensacionalista
15 | spam: spam
16 | duplicated: duplicada
17 | microblogging: microblogging
18 | erroneous: errónea
19 | plagiarism: copia/plagio
20 | errors:
21 | anon_cannot_vote_negative: 'Los usuarios anonimos no pueden votar negativo.'
22 | ref_does_not_exist: 'La referencia %reference% no existe.'
23 | no_ip_defined_for_anon: 'No ha sido definida ninguna IP para el usuario anonimo.'
24 | already_voted: 'Ya has votado.'
25 | already_clicked: 'Ya has hecho clic.'
26 | too_much_anon_votes: 'Demasiados votos anonimos.'
27 | invalid_reason: 'Razon invalida.'
--------------------------------------------------------------------------------
/Resources/views/msalsas_voting_widget.html.twig:
--------------------------------------------------------------------------------
1 | {# This file is part of the MsalsasVotingBundle package.
2 |
3 | (c) Manolo Salsas
4 |
5 | For the full copyright and license information, please view the LICENSE
6 | file that was distributed with this source code. #}
7 |
8 | {% macro shakeIt(id) %}
9 | {% set votes = msalsas_voting_voter.positiveVotes(id) %}
10 | {% set userVote = msalsas_voting_voter.userVote(id) %}
11 | {% set clicks = msalsas_voting_clicker.clicks(id) %}
12 | {% set published = msalsas_voting_voter.published(id) %}
13 |
40 | {% endmacro shakeIt %}
41 |
42 | {% macro bottomBar(id) %}
43 | {% set votes = msalsas_voting_voter.positiveVotes(id) %}
44 | {% set anonymousVotes = msalsas_voting_voter.anonymousVotes(id) %}
45 | {% set userPositiveVotes = msalsas_voting_voter.userPositiveVotes(id) %}
46 | {% set negativeVotes = msalsas_voting_voter.negativeVotes(id) %}
47 | {% set userVote = msalsas_voting_voter.userVote(id) %}
48 | {% set negativeReasons = msalsas_voting_voter.negativeReasons() %}
49 |
50 |
51 | {{ userPositiveVotes|default(0) }}
52 | {{ anonymousVotes|default(0) }}
53 | {{ negativeVotes|default(0) }}
54 |
55 | {% if not userVote and msalsas_voting_voter.userCanVoteNegative(id) %}
56 |
68 | {% endif %}
69 |
70 |
71 | {% endmacro bottomBar %}
72 |
73 | {% macro shakeItModal() %}
74 |
80 | {% endmacro %}
81 |
82 | {% macro shakeItCSS() %}
83 |
84 | {% endmacro shakeItCSS %}
85 |
86 | {% macro shakeItJS() %}
87 |
88 |
89 | {% endmacro shakeItJS %}
90 |
--------------------------------------------------------------------------------
/Service/Clicker.php:
--------------------------------------------------------------------------------
1 | em = $em;
50 | $this->token = $token;
51 | $this->request = $requestStack->getCurrentRequest();
52 | $this->translator = $translator;
53 | }
54 |
55 | public function getClicks($referenceId)
56 | {
57 | /** @var ReferenceClicks|null $referenceClicks */
58 | $referenceClicks = $this->em->getRepository(ReferenceClicks::class)->findOneBy(array('reference' => $referenceId));
59 | if (!$referenceClicks) {
60 | return 0;
61 | }
62 |
63 | return $referenceClicks->getClicks();
64 | }
65 |
66 | public function addClick($referenceId)
67 | {
68 | $user = $this->token->getToken()->getUser();
69 | $user = $user instanceof UserInterface ? $user : null;
70 |
71 | try {
72 | $this->validateClick($user, $referenceId);
73 | } catch (\Exception $e) {
74 | return $this->getClicks($referenceId);
75 | }
76 |
77 | $click = new Click();
78 | $click->setReference($referenceId);
79 | $click->setUser($user);
80 | $click->setUserIP($this->request->getClientIp());
81 |
82 | /** @var \Msalsas\VotingBundle\Entity\ReferenceClicks $referenceClicks */
83 | $referenceClicks = $this->addReferenceClick($referenceId);
84 |
85 | $this->em->persist($click);
86 | $this->em->persist($referenceClicks);
87 | $this->em->flush();
88 |
89 | return $referenceClicks->getClicks();
90 | }
91 |
92 | private function validateClick($user, $referenceId)
93 | {
94 | if (!$user instanceof UserInterface && !$this->request->getClientIp()) {
95 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.no_ip_defined_for_anon'));
96 | }
97 |
98 | if ($this->userHasClicked($user, $referenceId)) {
99 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.already_clicked'));
100 | }
101 | }
102 |
103 | private function userHasClicked($user, $referenceId)
104 | {
105 | $clickRepository = $this->em->getRepository(Click::class);
106 |
107 | if ($user instanceof UserInterface) {
108 | if ($clickRepository->findOneBy(
109 | array(
110 | 'user' => $user,
111 | 'reference' => $referenceId
112 | )
113 | )) {
114 | return true;
115 | }
116 | } else {
117 | if ($clickRepository->findOneBy(
118 | array(
119 | 'user' => null,
120 | 'userIP' => $this->request->getClientIp(),
121 | 'reference' => $referenceId
122 | )
123 | )) {
124 | return true;
125 | }
126 | }
127 |
128 | return false;
129 | }
130 |
131 | private function addReferenceClick($referenceId)
132 | {
133 | /** @var ReferenceClicks|null $referenceClicks */
134 | $referenceClicks = $this->em->getRepository(ReferenceClicks::class)->findOneBy(array('reference' => $referenceId));
135 | if ($referenceClicks) {
136 | $referenceClicks->addClick();
137 | } else {
138 | $referenceClicks = new ReferenceClicks();
139 | $referenceClicks->setReference($referenceId);
140 | $referenceClicks->addClick();
141 | }
142 |
143 | return $referenceClicks;
144 | }
145 | }
--------------------------------------------------------------------------------
/Service/Voter.php:
--------------------------------------------------------------------------------
1 | em = $em;
66 | $this->token = $token;
67 | $this->request = $requestStack->getCurrentRequest();
68 | $this->translator = $translator;
69 | $this->anonPercentAllowed = $anonPercentAllowed;
70 | $this->anonMinAllowed = $anonMinAllowed;
71 | $this->negativeReasons = $negativeReasons;
72 | }
73 |
74 | public function getPositiveVotes($referenceId)
75 | {
76 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
77 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
78 | if (!$referenceVotes) {
79 | $referenceVotes = new ReferenceVotes();
80 | $referenceVotes->setReference($referenceId);
81 | }
82 |
83 | return $referenceVotes->getPositiveVotes();
84 | }
85 |
86 | public function getNegativeVotes($referenceId)
87 | {
88 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
89 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
90 | if (!$referenceVotes) {
91 | $referenceVotes = new ReferenceVotes();
92 | $referenceVotes->setReference($referenceId);
93 | }
94 |
95 | return $referenceVotes->getNegativeVotes();
96 | }
97 |
98 | public function getUserPositiveVotes($referenceId)
99 | {
100 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
101 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
102 | if (!$referenceVotes) {
103 | $referenceVotes = new ReferenceVotes();
104 | $referenceVotes->setReference($referenceId);
105 | }
106 |
107 | return $referenceVotes->getUserVotes();
108 | }
109 |
110 | public function getAnonymousVotes($referenceId)
111 | {
112 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
113 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
114 | if (!$referenceVotes) {
115 | $referenceVotes = new ReferenceVotes();
116 | $referenceVotes->setReference($referenceId);
117 | }
118 |
119 | return $referenceVotes->getAnonymousVotes();
120 | }
121 |
122 | public function votePositive($referenceId)
123 | {
124 | $user = $this->token->getToken() ? $this->token->getToken()->getUser() : null;
125 |
126 | $this->validateVote($user, $referenceId);
127 |
128 | $user = $user instanceof UserInterface ? $user : null;
129 |
130 | $vote = new VotePositive();
131 | $vote->setReference($referenceId);
132 | $vote->setUser($user);
133 | $vote->setUserIP($this->request ? $this->request->getClientIp() : null);
134 |
135 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes $referenceVotes */
136 | $referenceVotes = $this->addReferenceVote($referenceId, true, !$user);
137 |
138 | $this->em->persist($vote);
139 | $this->em->persist($referenceVotes);
140 | $this->em->flush();
141 |
142 | return $referenceVotes->getPositiveVotes();
143 | }
144 |
145 | public function voteNegative($referenceId, $reason)
146 | {
147 | $user = $this->token->getToken() ? $this->token->getToken()->getUser() : null;
148 |
149 | if (!$reason || !is_string($reason) || $reason === '0') {
150 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.invalid_reason'));
151 | }
152 |
153 | $this->validateVote($user, $referenceId);
154 |
155 | if (!$user instanceof UserInterface) {
156 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.anon_cannot_vote_negative'));
157 | }
158 |
159 | $vote = new VoteNegative();
160 | $vote->setReference($referenceId);
161 | $vote->setReason($reason);
162 | $vote->setUser($user);
163 | $vote->setUserIP($this->request->getClientIp());
164 |
165 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes $referenceVotes */
166 | $referenceVotes = $this->addReferenceVote($referenceId, false, !$user);
167 |
168 | $this->em->persist($referenceVotes);
169 | $this->em->persist($vote);
170 | $this->em->flush();
171 |
172 | return $referenceVotes->getNegativeVotes();
173 | }
174 |
175 | public function getUserVote($referenceId)
176 | {
177 | $user = $this->token->getToken()->getUser();
178 | $user = $user instanceof UserInterface ? $user : null;
179 | $votePositiveRepository = $this->em->getRepository(VotePositive::class);
180 | $voteNegativeRepository = $this->em->getRepository(VoteNegative::class);
181 |
182 | if ($user && $vote = $votePositiveRepository->findOneBy(array('user' => $user, 'reference' => $referenceId))) {
183 | return $vote;
184 | } else if (!$user && $vote = $votePositiveRepository->findOneBy(array('user' => $user, 'reference' => $referenceId, 'userIP' => $this->request->getClientIp()))) {
185 | return $vote;
186 | } else if ($vote = $voteNegativeRepository->findOneBy(array('user' => $user, 'reference' => $referenceId))) {
187 | return $vote;
188 | }
189 |
190 | return false;
191 | }
192 |
193 | public function getNegativeReasons()
194 | {
195 | return $this->negativeReasons;
196 | }
197 |
198 | public function userCanVoteNegative($referenceId)
199 | {
200 | $user = $this->token->getToken()->getUser();
201 | if (!$user instanceof UserInterface) {
202 | return false;
203 | }
204 |
205 | return !$this->userHasVoted($user, $referenceId);
206 | }
207 |
208 | public function isPublished($referenceId)
209 | {
210 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
211 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
212 | if (!$referenceVotes) {
213 | return false;
214 | }
215 |
216 | return $referenceVotes->isPublished();
217 | }
218 |
219 | public function setPublished($referenceId)
220 | {
221 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
222 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
223 | if (!$referenceVotes) {
224 | throw new \Exception($this->translator->trans('msalsas_voting.errors.ref_does_not_exist', array('%reference%' => $referenceId)));
225 | }
226 |
227 | $referenceVotes->setPublished(true);
228 | }
229 |
230 | protected function validateVote($user, $referenceId)
231 | {
232 | if (!$user instanceof UserInterface && (!$this->request || !$this->request->getClientIp())) {
233 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.no_ip_defined_for_anon'));
234 | }
235 |
236 | if ($this->userHasVoted($user, $referenceId)) {
237 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.already_voted'));
238 | }
239 |
240 | if (!$user instanceof UserInterface) {
241 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
242 | if ($referenceVotes instanceof ReferenceVotes && !$this->anonymousIsAllowed($referenceVotes)) {
243 | throw new AccessDeniedException($this->translator->trans('msalsas_voting.errors.too_much_anon_votes'));
244 | }
245 | }
246 | }
247 |
248 | protected function userHasVoted($user, $referenceId)
249 | {
250 | $votePositiveRepository = $this->em->getRepository(VotePositive::class);
251 | $voteNegativeRepository = $this->em->getRepository(VoteNegative::class);
252 |
253 | if ($user instanceof UserInterface) {
254 | if ($votePositiveRepository->findOneBy(
255 | array(
256 | 'user' => $user,
257 | 'reference' => $referenceId
258 | )
259 | )) {
260 | return true;
261 | } else if ($voteNegativeRepository->findOneBy(
262 | array(
263 | 'user' => $user,
264 | 'reference' => $referenceId
265 | )
266 | )) {
267 | return true;
268 | }
269 | } else {
270 | if ($votePositiveRepository->findOneBy(
271 | array(
272 | 'user' => null,
273 | 'userIP' => $this->request->getClientIp(),
274 | 'reference' => $referenceId
275 | )
276 | )) {
277 | return true;
278 | }
279 | }
280 |
281 | return false;
282 | }
283 |
284 | protected function addReferenceVote($referenceId, $positive, $anonymous = true)
285 | {
286 | /** @var \Msalsas\VotingBundle\Entity\ReferenceVotes|null $referenceVotes */
287 | $referenceVotes = $this->em->getRepository(ReferenceVotes::class)->findOneBy(array('reference' => $referenceId));
288 | if ($referenceVotes) {
289 | $referenceVotes->addVote($positive, $anonymous);
290 | } else {
291 | $referenceVotes = new ReferenceVotes();
292 | $referenceVotes->setReference($referenceId);
293 | $referenceVotes->addVote($positive, $anonymous);
294 | }
295 |
296 | return $referenceVotes;
297 | }
298 |
299 | protected function anonymousIsAllowed(ReferenceVotes $referenceVotes)
300 | {
301 | $anonVotes = $referenceVotes->getAnonymousVotes();
302 | $userVotes = $referenceVotes->getUserVotes();
303 |
304 | if ($anonVotes < $this->anonMinAllowed) {
305 | return true;
306 | }
307 |
308 | $anonPercent = $anonVotes ? ($anonVotes / ($userVotes + $anonVotes)) * 100 : 0;
309 | if ($anonPercent < $this->anonPercentAllowed) {
310 | return true;
311 | }
312 |
313 | return false;
314 | }
315 | }
--------------------------------------------------------------------------------
/Tests/DependencyInjection/MsalsasVotingExtensionTest.php:
--------------------------------------------------------------------------------
1 | configuration = null;
27 | }
28 |
29 | /**
30 | * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
31 | */
32 | public function testUserLoadThrowsExceptionUnlessUserProviderSet()
33 | {
34 | $this->configuration = new ContainerBuilder();
35 | $loader = new MsalsasVotingExtension();
36 | $config = $this->getEmptyConfig();
37 | unset($config['user_provider']);
38 | $loader->load(array($config), $this->configuration);
39 | }
40 |
41 | /**
42 | * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
43 | */
44 | public function testUserLoadThrowsExceptionUnlessUserProviderIsValid()
45 | {
46 | $this->configuration = new ContainerBuilder();
47 | $loader = new MsalsasVotingExtension();
48 | $config = $this->getEmptyConfig();
49 | $config['user_provider'] = 5;
50 | $loader->load(array($config), $this->configuration);
51 | }
52 |
53 | public function testUserProvider()
54 | {
55 | $this->configuration = new ContainerBuilder();
56 | $loader = new MsalsasVotingExtension();
57 | $config = $this->getFullConfig();
58 | $config['user_provider'] = '\App\Entity\User';
59 | $loader->load(array($config), $this->configuration);
60 |
61 | $this->assertHasDefinition('msalsas_voting.voter');
62 | $this->assertHasDefinition('msalsas_voting.clicker');
63 | $this->assertParameter(50, 'msalsas_voting.anonymous_percent_allowed');
64 | $this->assertParameter(2, 'msalsas_voting.anonymous_min_allowed');
65 | }
66 |
67 | public function testPrependConfig()
68 | {
69 | $this->configuration = new ContainerBuilder();
70 | $loader = new MsalsasVotingExtension();
71 | $config = $this->getFullConfig();
72 | $config['user_provider'] = '\App\Entity\User';
73 |
74 | $this->configuration->prependExtensionConfig('msalsas_voting', $config);
75 | $loader->prepend($this->configuration);
76 |
77 | // Doctrine config
78 | $doctrineConfig = $this->configuration->getExtensionConfig('doctrine');
79 | $this->assertTrue(isset($doctrineConfig) && is_array($doctrineConfig));
80 | $this->assertTrue(isset($doctrineConfig[0]['orm']['resolve_target_entities']['Msalsas\VotingBundle\Entity\Vote\UserInterface']));
81 | $this->assertTrue($doctrineConfig[0]['orm']['resolve_target_entities']['Msalsas\VotingBundle\Entity\Vote\UserInterface'] === '\App\Entity\User');
82 | $this->assertTrue(isset($doctrineConfig[0]['orm']['mappings']));
83 | $mapping = array(
84 | 'name' => 'MsalsasVotingBundle',
85 | 'is_bundle' => true,
86 | 'type' => 'xml',
87 | 'prefix' => 'Msalsas\VotingBundle\Entity'
88 | );
89 | $this->assertTrue(in_array($mapping, $doctrineConfig[0]['orm']['mappings']));
90 |
91 | // Twig config
92 | $twigConfig = $this->configuration->getExtensionConfig('twig');
93 | $this->assertTrue(isset($twigConfig) && is_array($twigConfig));
94 | $this->assertTrue(isset($twigConfig[0]['globals']['msalsas_voting_voter']));
95 | $this->assertTrue($twigConfig[0]['globals']['msalsas_voting_voter'] === "@msalsas_voting.voter");
96 | $this->assertTrue(isset($twigConfig[0]['globals']['msalsas_voting_clicker']));
97 | $this->assertTrue($twigConfig[0]['globals']['msalsas_voting_clicker'] === "@msalsas_voting.clicker");
98 |
99 | $mainDir = substr(__DIR__, 0, strpos(__DIR__, '/Tests/DependencyInjection') );
100 | $this->assertTrue(isset($twigConfig[0]['paths'][$mainDir . '/DependencyInjection/../Resources/views']));
101 | $this->assertTrue($twigConfig[0]['paths'][$mainDir . '/DependencyInjection/../Resources/views'] === "msalsas_voting");
102 | $this->assertTrue(isset($twigConfig[0]['paths'][$mainDir . '/DependencyInjection/../Resources/public']));
103 | $this->assertTrue($twigConfig[0]['paths'][$mainDir . '/DependencyInjection/../Resources/public'] === "msalsas_voting.public");
104 | }
105 |
106 | /**
107 | * getEmptyConfig.
108 | *
109 | * @return array
110 | */
111 | protected function getEmptyConfig()
112 | {
113 | $yaml = <<parse($yaml);
119 | }
120 |
121 | /**
122 | * getFullConfig.
123 | *
124 | * @return array
125 | */
126 | protected function getFullConfig()
127 | {
128 | $yaml = <<parse($yaml);
139 | }
140 |
141 | /**
142 | * @param mixed $value
143 | * @param string $key
144 | */
145 | private function assertParameter($value, $key)
146 | {
147 | $this->assertSame($value, $this->configuration->getParameter($key), sprintf('%s parameter is correct', $key));
148 | }
149 |
150 | /**
151 | * @param string $id
152 | */
153 | private function assertHasDefinition($id)
154 | {
155 | $this->assertTrue(($this->configuration->hasDefinition($id) ?: $this->configuration->hasAlias($id)));
156 | }
157 | }
--------------------------------------------------------------------------------
/Tests/Entity/ClickTest.php:
--------------------------------------------------------------------------------
1 | getMockBuilder(UserMock::class)
14 | ->getMock();
15 | $click = new Click();
16 | $click->setId(1);
17 | $click->setReference(1);
18 | $click->setUser($userMock);
19 | $click->setUserIP('127.0.0.1');
20 |
21 | $this->assertSame(1, $click->getId());
22 | $this->assertSame(1, $click->getReference());
23 | $this->assertSame($userMock, $click->getUser());
24 | $this->assertSame('127.0.0.1', $click->getUserIP());
25 | }
26 | }
--------------------------------------------------------------------------------
/Tests/Entity/ReferenceClicksTest.php:
--------------------------------------------------------------------------------
1 | setReference(1);
14 | $referenceClicks->setClicks(100);
15 |
16 | $this->assertSame(1, $referenceClicks->getReference());
17 | $this->assertSame(100, $referenceClicks->getClicks());
18 | }
19 | }
--------------------------------------------------------------------------------
/Tests/Entity/ReferenceVotesTest.php:
--------------------------------------------------------------------------------
1 | setReference(1);
14 | $referenceVotes->setPositiveVotes(880);
15 | $referenceVotes->setAnonymousVotes(80);
16 | $referenceVotes->setUserVotes(800);
17 | $referenceVotes->setNegativeVotes(8);
18 | $referenceVotes->setPublished(true);
19 |
20 | $this->assertSame(1, $referenceVotes->getReference());
21 | $this->assertSame(880, $referenceVotes->getPositiveVotes());
22 | $this->assertSame(80, $referenceVotes->getAnonymousVotes());
23 | $this->assertSame(800, $referenceVotes->getUserVotes());
24 | $this->assertSame(8, $referenceVotes->getNegativeVotes());
25 | $this->assertSame(true, $referenceVotes->isPublished());
26 | }
27 | }
--------------------------------------------------------------------------------
/Tests/Entity/VoteNegativeTest.php:
--------------------------------------------------------------------------------
1 | getMockBuilder(UserMock::class)
14 | ->getMock();
15 | $votePositive = new VoteNegative();
16 | $votePositive->setId(1);
17 | $votePositive->setReference(1);
18 | $votePositive->setUser($userMock);
19 | $votePositive->setUserIP('127.0.0.1');
20 | $votePositive->setReason('irrelevant');
21 |
22 | $this->assertSame(1, $votePositive->getId());
23 | $this->assertSame(1, $votePositive->getReference());
24 | $this->assertSame($userMock, $votePositive->getUser());
25 | $this->assertSame('127.0.0.1', $votePositive->getUserIP());
26 | $this->assertSame('irrelevant', $votePositive->getReason());
27 | $this->assertSame(false, $votePositive->isPositive());
28 | }
29 | }
--------------------------------------------------------------------------------
/Tests/Entity/VotePositiveTest.php:
--------------------------------------------------------------------------------
1 | getMockBuilder(UserMock::class)
14 | ->getMock();
15 | $votePositive = new VotePositive();
16 | $votePositive->setId(1);
17 | $votePositive->setReference(1);
18 | $votePositive->setUser($userMock);
19 | $votePositive->setUserIP('127.0.0.1');
20 |
21 | $this->assertSame(1, $votePositive->getId());
22 | $this->assertSame(1, $votePositive->getReference());
23 | $this->assertSame($userMock, $votePositive->getUser());
24 | $this->assertSame('127.0.0.1', $votePositive->getUserIP());
25 | $this->assertSame(true, $votePositive->isPositive());
26 | }
27 | }
--------------------------------------------------------------------------------
/Tests/Mock/AnonymousUserMock.php:
--------------------------------------------------------------------------------
1 | user = $user;
23 | $this->userIP = $userIP;
24 | }
25 |
26 | public function getId()
27 | {
28 | return 1;
29 | }
30 |
31 | public function getUser()
32 | {
33 | return $this->user;
34 | }
35 |
36 | public function getReference()
37 | {
38 | return 1;
39 | }
40 |
41 | public function getUserIP()
42 | {
43 | return $this->userIP;
44 | }
45 | }
--------------------------------------------------------------------------------
/Tests/Mock/UserMock.php:
--------------------------------------------------------------------------------
1 | user = $user;
24 | }
25 |
26 | public function getId()
27 | {
28 | return 1;
29 | }
30 |
31 | public function getUser()
32 | {
33 | return $this->user;
34 | }
35 |
36 | public function getReference()
37 | {
38 | return 1;
39 | }
40 |
41 | public function getUserIP()
42 | {
43 | return $this->userIP;
44 | }
45 |
46 | public function isPositive()
47 | {
48 | return true;
49 | }
50 |
51 | public function getReason()
52 | {
53 | return $this->reason;
54 | }
55 | }
--------------------------------------------------------------------------------
/Tests/Mock/VotePositiveMock.php:
--------------------------------------------------------------------------------
1 | user = $user;
23 | }
24 |
25 | public function getId()
26 | {
27 | return 1;
28 | }
29 |
30 | public function getUser()
31 | {
32 | return $this->user;
33 | }
34 |
35 | public function getReference()
36 | {
37 | return 1;
38 | }
39 |
40 | public function getUserIP()
41 | {
42 | return $this->userIP;
43 | }
44 |
45 | public function isPositive()
46 | {
47 | return true;
48 | }
49 | }
--------------------------------------------------------------------------------
/Tests/Service/AbstractServiceTest.php:
--------------------------------------------------------------------------------
1 | setDefaultMocks();
38 | $this->translator = new Translator('en');
39 | }
40 |
41 | protected function setDefaultMocks()
42 | {
43 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
44 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
45 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
46 |
47 | $requestMock = $this->getMockBuilder(Request::class)
48 | ->disableOriginalConstructor()
49 | ->setMethods(array('getClientIp'))
50 | ->getMock();
51 | $requestMock->expects($this->any())
52 | ->method('getClientIp')->willReturn('127.0.0.1');
53 |
54 | $this->requestStackMock = $this->getMockBuilder(RequestStack::class)
55 | ->disableOriginalConstructor()
56 | ->setMethods(array('getCurrentRequest'))
57 | ->getMock();
58 | $this->requestStackMock->expects($this->any())
59 | ->method('getCurrentRequest')->willReturn($requestMock);
60 | }
61 |
62 | protected function setUserMocks()
63 | {
64 | $this->userMock = $this->getMockBuilder(UserMock::class)
65 | ->getMock();
66 |
67 | $tokenMock = $this->getMockBuilder(TokenInterface::class)
68 | ->disableOriginalConstructor()
69 | ->getMock();
70 | $tokenMock->method('getUser')->willReturn($this->userMock);
71 |
72 | $this->tokenStorageMock = $this->getMockBuilder(TokenStorageInterface::class)
73 | ->disableOriginalConstructor()
74 | ->getMock();
75 | $this->tokenStorageMock->method('getToken')->willReturn($tokenMock);
76 | }
77 |
78 | protected function setAnonymousUserMocks()
79 | {
80 | $this->userMock = $this->getMockBuilder(AnonymousUserMock::class)
81 | ->getMock();
82 |
83 | $tokenMock = $this->getMockBuilder(TokenInterface::class)
84 | ->disableOriginalConstructor()
85 | ->getMock();
86 | $tokenMock->method('getUser')->willReturn($this->userMock);
87 |
88 | $this->tokenStorageMock = $this->getMockBuilder(TokenStorageInterface::class)
89 | ->disableOriginalConstructor()
90 | ->getMock();
91 | $this->tokenStorageMock->method('getToken')->willReturn($tokenMock);
92 | }
93 |
94 | protected function getRepositoryMock($classMock)
95 | {
96 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
97 | $emRepositoryMock->method('findOneBy')->willReturn($classMock);
98 |
99 | return $emRepositoryMock;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Tests/Service/ClickerTest.php:
--------------------------------------------------------------------------------
1 | setUserMocks();
29 |
30 | $clicker = new Clicker($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator);
31 |
32 | $this->assertSame(0, $clicker->getClicks(1));
33 |
34 | $clicks = $clicker->addClick(1);
35 |
36 | $this->assertSame(1, $clicks);
37 | }
38 |
39 | public function testClickWithAnonymous()
40 | {
41 | $this->setAnonymousUserMocks();
42 |
43 | $clicker = new Clicker($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator);
44 |
45 | $this->assertSame(0, $clicker->getClicks(1));
46 |
47 | $clicks = $clicker->addClick(1);
48 |
49 | $this->assertSame(1, $clicks);
50 | }
51 |
52 | public function testClickWithAnonymousAndNoIp()
53 | {
54 | $this->setAnonymousUserMocks();
55 |
56 | $requestMock = $this->getMockBuilder(Request::class)
57 | ->disableOriginalConstructor()
58 | ->setMethods(array('getClientIp'))
59 | ->getMock();
60 | $requestMock->expects($this->any())
61 | ->method('getClientIp')->willReturn(null);
62 |
63 | $this->requestStackMock = $this->getMockBuilder(RequestStack::class)
64 | ->disableOriginalConstructor()
65 | ->setMethods(array('getCurrentRequest'))
66 | ->getMock();
67 | $this->requestStackMock->expects($this->any())
68 | ->method('getCurrentRequest')->willReturn($requestMock);
69 |
70 | $clicker = new Clicker($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator);
71 |
72 | $this->assertSame(0, $clicker->getClicks(1));
73 |
74 | $clicks = $clicker->addClick(1);
75 |
76 | $this->assertSame(0, $clicks);
77 | }
78 |
79 | public function testClickWithUserWhoAlreadyClicked()
80 | {
81 | $this->setUserMocks();
82 |
83 | $clickMock = $this->getClickMock($this->userMock);
84 | $referenceClicksMock = $this->getMockBuilder(ReferenceClicks::class)
85 | ->getMock();
86 | $referenceClicksMock->method('getReference')->willReturn(1);
87 | $referenceClicksMock->method('getClicks')->willReturn(2);
88 |
89 | $clickEmRepositoryMock = $this->getRepositoryMock($clickMock);
90 | $referenceClicksEmRepositoryMock = $this->getRepositoryMock($referenceClicksMock);
91 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
92 | $this->emMock->expects($this->exactly(2))->method('getRepository')->withConsecutive([Click::class], [ReferenceClicks::class])
93 | ->willReturnOnConsecutiveCalls($clickEmRepositoryMock, $referenceClicksEmRepositoryMock);
94 |
95 | $clicker = new Clicker($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator);
96 |
97 | $clicks = $clicker->addClick(1);
98 |
99 | $this->assertSame(2, $clicks);
100 | }
101 |
102 |
103 | public function testClickWithUserWhoAlreadyClickedAndNoReference()
104 | {
105 | $this->setUserMocks();
106 |
107 | $referenceClicksMock = $this->getMockBuilder(ReferenceClicks::class)
108 | ->getMock();
109 | $referenceClicksMock->method('getReference')->willReturn(1);
110 |
111 | $clickEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
112 | $referenceClicksEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
113 | $clickEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn(null);
114 | $referenceClicksEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn($referenceClicksMock);
115 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
116 | $this->emMock->expects($this->exactly(2))->method('getRepository')->withConsecutive([Click::class], [ReferenceClicks::class])
117 | ->willReturnOnConsecutiveCalls($clickEmRepositoryMock, $referenceClicksEmRepositoryMock);
118 |
119 | $clicker = new Clicker($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator);
120 |
121 | $clicks = $clicker->addClick(1);
122 |
123 | $this->assertSame(0, $clicks);
124 | }
125 |
126 | public function testClickWithAnonymousWhoAlreadyClicked()
127 | {
128 | $this->setAnonymousUserMocks();
129 |
130 | $clickMock = $this->getClickMock($this->userMock);
131 | $referenceClicksMock = $this->getMockBuilder(ReferenceClicks::class)
132 | ->getMock();
133 | $referenceClicksMock->method('getReference')->willReturn(1);
134 | $referenceClicksMock->method('getClicks')->willReturn(2);
135 |
136 | $clickEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
137 | $referenceClicksEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
138 | $clickEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn($clickMock);
139 | $referenceClicksEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn($referenceClicksMock);
140 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
141 | $this->emMock->expects($this->exactly(2))->method('getRepository')->withConsecutive([Click::class], [ReferenceClicks::class])
142 | ->willReturnOnConsecutiveCalls($clickEmRepositoryMock, $referenceClicksEmRepositoryMock);
143 |
144 | $clicker = new Clicker($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator);
145 |
146 | $clicks = $clicker->addClick(1);
147 |
148 | $this->assertSame(2, $clicks);
149 | }
150 |
151 | private function getClickMock($user, $userIP = '127.0.0.1')
152 | {
153 | return $this->getMockBuilder(ClickMock::class)
154 | ->setConstructorArgs(array($user, $userIP))
155 | ->getMock();
156 | }
157 | }
--------------------------------------------------------------------------------
/Tests/Service/VoterTest.php:
--------------------------------------------------------------------------------
1 | setAnonymousUserMocks();
32 |
33 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
34 |
35 | $this->assertSame(false, $voter->userCanVoteNegative(1));
36 | }
37 |
38 | public function testUserCanVoteNegative()
39 | {
40 | $this->setUserMocks();
41 |
42 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
43 |
44 | $this->assertSame(true, $voter->userCanVoteNegative(1));
45 | }
46 |
47 | public function testUserCannotVoteNegativeVotedPositive()
48 | {
49 | $this->setUserMocks();
50 | $votePositiveMock = $this->getVotePositiveMock($this->userMock);
51 | $emRepositoryMock = $this->getRepositoryMock($votePositiveMock);
52 |
53 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
54 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
55 |
56 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
57 |
58 | $this->assertSame(false, $voter->userCanVoteNegative(1));
59 | }
60 |
61 | public function testUserCannotVoteNegativeVotedNegative()
62 | {
63 | $this->setUserMocks();
64 | $positiveVoteEmRepositoryMock = $this->getRepositoryMock(null);
65 | $voteNegativeMock = $this->getVoteNegativeMock($this->userMock);
66 | $negativeVoteEmRepositoryMock = $this->getRepositoryMock($voteNegativeMock);
67 |
68 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
69 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class])
70 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock);
71 |
72 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
73 |
74 | $this->assertSame(false, $voter->userCanVoteNegative(1));
75 | }
76 |
77 | public function testGetVotes()
78 | {
79 | $this->setUserMocks();
80 |
81 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
82 |
83 | $this->assertSame(0, $voter->getUserPositiveVotes(1));
84 | $this->assertSame(0, $voter->getPositiveVotes(1));
85 | $this->assertSame(0, $voter->getNegativeVotes(1));
86 | $this->assertSame(0, $voter->getAnonymousVotes(1));
87 | $this->assertSame(false, $voter->getUserVote(1));
88 | }
89 |
90 | public function testGetVotesWithExistingReference()
91 | {
92 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
93 | ->getMock();
94 | $referenceVotesMock->method('getReference')->willReturn(1);
95 | $referenceVotesMock->method('isPublished')->willReturn(true);
96 | $referenceVotesMock->method('getPositiveVotes')->willReturn(11);
97 | $referenceVotesMock->method('getUserVotes')->willReturn(6);
98 | $referenceVotesMock->method('getNegativeVotes')->willReturn(3);
99 | $referenceVotesMock->method('getAnonymousVotes')->willReturn(5);
100 | $referenceVotesMock->method('isPublished')->willReturn(true);
101 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
102 | $emRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
103 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
104 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
105 |
106 | $this->setUserMocks();
107 |
108 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
109 |
110 | $this->assertSame($referenceVotesMock, $voter->getUserVote(1));
111 | $this->assertSame(6, $voter->getUserPositiveVotes(1));
112 | $this->assertSame(5, $voter->getAnonymousVotes(1));
113 | $this->assertSame(11, $voter->getPositiveVotes(1));
114 | $this->assertSame(3, $voter->getNegativeVotes(1));
115 | $this->assertSame(['irrelevant'], $voter->getNegativeReasons());
116 | }
117 |
118 | public function testGetUserVoteWhenNegative()
119 | {
120 | $this->setUserMocks();
121 | $positiveVoteEmRepositoryMock = $this->getRepositoryMock(null);
122 | $voteNegativeMock = $this->getVoteNegativeMock($this->userMock);
123 | $negativeVoteEmRepositoryMock = $this->getRepositoryMock($voteNegativeMock);
124 |
125 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
126 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class])
127 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock);
128 |
129 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
130 |
131 | $this->assertSame($voteNegativeMock, $voter->getUserVote(1));
132 | }
133 |
134 | public function testGetAnonymousVoteWithVoteByIP()
135 | {
136 | $this->setAnonymousUserMocks();
137 | $votePositiveMock = $this->getVotePositiveMock($this->userMock);
138 | $positiveVoteEmRepositoryMock = $this->getRepositoryMock($votePositiveMock);
139 | $negativeVoteEmRepositoryMock = $this->getRepositoryMock(null);
140 |
141 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
142 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class])
143 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock);
144 |
145 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
146 |
147 | $this->assertSame($votePositiveMock, $voter->getUserVote(1));
148 | }
149 |
150 | public function testVotePositiveWithUser()
151 | {
152 | $this->setUserMocks();
153 |
154 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
155 |
156 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
157 | $this->assertSame(0, $voter->getPositiveVotes(1));
158 |
159 | $votes = $voter->votePositive(1);
160 |
161 | $this->assertSame(1, $votes);
162 | }
163 |
164 | public function testVotePositiveWithUserAndExistingReference()
165 | {
166 | $this->setUserMocks();
167 |
168 | $positiveVoteEmRepositoryMock = $this->getRepositoryMock(null);
169 | $negativeVoteEmRepositoryMock = $this->getRepositoryMock(null);
170 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
171 | ->getMock();
172 | $referenceVotesMock->method('getReference')->willReturn(1);
173 | $referenceVotesMock->method('isPublished')->willReturn(true);
174 | $referenceVotesMock->method('getPositiveVotes')->willReturn(11);
175 | $referenceVotesMock->method('getUserVotes')->willReturn(6);
176 | $referenceVotesMock->method('getNegativeVotes')->willReturn(3);
177 | $referenceVotesMock->method('getAnonymousVotes')->willReturn(5);
178 | $referenceVotesMock->method('isPublished')->willReturn(true);
179 | $referenceVotesEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
180 | $referenceVotesEmRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
181 |
182 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
183 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class], [ReferenceVotes::class])
184 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock, $referenceVotesEmRepositoryMock);
185 |
186 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
187 |
188 | $votes = $voter->votePositive(1);
189 |
190 | $this->assertSame(11, $votes);
191 | }
192 |
193 | public function testVoteNegativeWithUserAndExistingReference()
194 | {
195 | $this->setUserMocks();
196 |
197 | $positiveVoteEmRepositoryMock = $this->getRepositoryMock(null);
198 | $negativeVoteEmRepositoryMock = $this->getRepositoryMock(null);
199 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
200 | ->getMock();
201 | $referenceVotesMock->method('getReference')->willReturn(1);
202 | $referenceVotesMock->method('isPublished')->willReturn(true);
203 | $referenceVotesMock->method('getPositiveVotes')->willReturn(11);
204 | $referenceVotesMock->method('getUserVotes')->willReturn(6);
205 | $referenceVotesMock->method('getNegativeVotes')->willReturn(3);
206 | $referenceVotesMock->method('getAnonymousVotes')->willReturn(5);
207 | $referenceVotesMock->method('isPublished')->willReturn(true);
208 | $referenceVotesEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
209 | $referenceVotesEmRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
210 |
211 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
212 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class], [ReferenceVotes::class])
213 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock, $referenceVotesEmRepositoryMock);
214 |
215 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
216 |
217 | $votes = $voter->voteNegative(1, 'irrelevant');
218 |
219 | $this->assertSame(3, $votes);
220 | }
221 |
222 | public function testVoteNegativeWithUser()
223 | {
224 | $referenceVotes = new ReferenceVotes();
225 | $referenceVotes->setReference(1);
226 |
227 | $this->setUserMocks();
228 |
229 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
230 |
231 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
232 | $this->assertSame(0, $voter->getNegativeVotes($referenceVotes->getReference()));
233 |
234 | $votes = $voter->voteNegative(1, 'irrelevant');
235 |
236 | $this->assertSame(1, $votes);
237 | }
238 |
239 | /**
240 | * @expectedException \Symfony\Component\Finder\Exception\AccessDeniedException
241 | */
242 | public function testVoteNegativeWithUserWithoutReason()
243 | {
244 | $this->setUserMocks();
245 |
246 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
247 |
248 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
249 | $this->assertSame(0, $voter->getNegativeVotes(1));
250 |
251 | $voter->voteNegative(1, '');
252 | }
253 |
254 | public function testVotePositiveWithAnonymous()
255 | {
256 | $this->setAnonymousUserMocks();
257 |
258 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
259 |
260 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
261 | $this->assertSame(0, $voter->getPositiveVotes(1));
262 |
263 | $votes = $voter->votePositive(1);
264 |
265 | $this->assertSame(1, $votes);
266 | }
267 |
268 | public function testVoteWithAnonymousOneAllowed()
269 | {
270 | $this->setAnonymousUserMocks();
271 |
272 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
273 | ->getMock();
274 | $referenceVotesMock->method('getReference')->willReturn(1);
275 | $referenceVotesMock->method('getPositiveVotes')->willReturn(10);
276 |
277 | $positiveVotesMock = $this->getMockBuilder(VotePositive::class)
278 | ->getMock();
279 | $positiveVotesMock->method('getReference')->willReturn(1);
280 |
281 | $negativeVotesMock = $this->getMockBuilder(VoteNegative::class)
282 | ->getMock();
283 | $negativeVotesMock->method('getReference')->willReturn(1);
284 |
285 | $positiveVoteEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
286 | $negativeVoteEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
287 | $referenceVotesEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
288 | $positiveVoteEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn(null);
289 | $negativeVoteEmRepositoryMock->method('findOneBy')->willReturn($negativeVotesMock);
290 | $referenceVotesEmRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
291 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
292 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class], [ReferenceVotes::class], [ReferenceVotes::class])
293 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock, $referenceVotesEmRepositoryMock, $referenceVotesEmRepositoryMock);
294 |
295 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 1, array('irrelevant'));
296 |
297 | $votes = $voter->votePositive(1);
298 |
299 | $this->assertSame(10, $votes);
300 | }
301 |
302 | public function testVoteWithAnonymousTenPercentAllowed()
303 | {
304 | $this->setAnonymousUserMocks();
305 |
306 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
307 | ->getMock();
308 | $referenceVotesMock->method('getReference')->willReturn(1);
309 | $referenceVotesMock->method('getAnonymousVotes')->willReturn(1);
310 | $referenceVotesMock->method('getUserVotes')->willReturn(100);
311 |
312 | $positiveVotesMock = $this->getMockBuilder(VotePositive::class)
313 | ->getMock();
314 | $positiveVotesMock->method('getReference')->willReturn(1);
315 |
316 | $negativeVotesMock = $this->getMockBuilder(VoteNegative::class)
317 | ->getMock();
318 | $negativeVotesMock->method('getReference')->willReturn(1);
319 |
320 | $positiveVoteEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
321 | $negativeVoteEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
322 | $referenceVotesEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
323 | $positiveVoteEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn(null);
324 | $negativeVoteEmRepositoryMock->method('findOneBy')->willReturn($negativeVotesMock);
325 | $referenceVotesEmRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
326 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
327 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class], [ReferenceVotes::class], [ReferenceVotes::class])
328 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock, $referenceVotesEmRepositoryMock, $referenceVotesEmRepositoryMock);
329 |
330 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 10, 0, array('irrelevant'));
331 |
332 | $voter->votePositive(1);
333 | }
334 |
335 | /**
336 | * @expectedException \Symfony\Component\Finder\Exception\AccessDeniedException
337 | */
338 | public function testVoteWithAnonymousNotAllowed()
339 | {
340 | $this->setAnonymousUserMocks();
341 |
342 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
343 | ->getMock();
344 | $referenceVotesMock->method('getReference')->willReturn(1);
345 | $referenceVotesMock->method('getAnonymousVotes')->willReturn(1);
346 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
347 | $emRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
348 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
349 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
350 |
351 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 0, array('irrelevant'));
352 |
353 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
354 | $this->assertSame(0, $voter->getPositiveVotes(1));
355 |
356 | $voter->votePositive(1);
357 | }
358 |
359 | /**
360 | * @expectedException \Symfony\Component\Finder\Exception\AccessDeniedException
361 | */
362 | public function testVotePositiveWithAnonymousPercentToZero()
363 | {
364 | $this->setAnonymousUserMocks();
365 |
366 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
367 | ->getMock();
368 | $referenceVotesMock->method('getReference')->willReturn(1);
369 | $referenceVotesMock->method('getAnonymousVotes')->willReturn(10);
370 | $referenceVotesMock->method('getUserVotes')->willReturn(1);
371 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
372 | $emRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
373 |
374 | $positiveVotesMock = $this->getMockBuilder(VotePositive::class)
375 | ->getMock();
376 | $positiveVotesMock->method('getReference')->willReturn(1);
377 |
378 | $negativeVotesMock = $this->getMockBuilder(VoteNegative::class)
379 | ->getMock();
380 | $negativeVotesMock->method('getReference')->willReturn(1);
381 |
382 | $positiveVoteEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
383 | $negativeVoteEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
384 | $referenceVotesEmRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
385 | $positiveVoteEmRepositoryMock->expects($this->exactly(1))->method('findOneBy')->willReturn(null);
386 | $negativeVoteEmRepositoryMock->method('findOneBy')->willReturn($negativeVotesMock);
387 | $referenceVotesEmRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
388 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
389 | $this->emMock->method('getRepository')->withConsecutive([VotePositive::class], [VoteNegative::class], [ReferenceVotes::class])
390 | ->willReturnOnConsecutiveCalls($positiveVoteEmRepositoryMock, $negativeVoteEmRepositoryMock, $referenceVotesEmRepositoryMock);
391 |
392 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 0, 0, array('irrelevant'));
393 |
394 | $voter->votePositive(1);
395 | }
396 |
397 | /**
398 | * @expectedException \Symfony\Component\Finder\Exception\AccessDeniedException
399 | */
400 | public function testVoteNegativeWithAnonymous()
401 | {
402 | $referenceVotes = new ReferenceVotes();
403 | $referenceVotes->setReference(1);
404 |
405 | $this->setAnonymousUserMocks();
406 |
407 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
408 |
409 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
410 | $this->assertSame(0, $voter->getNegativeVotes($referenceVotes->getReference()));
411 |
412 | $voter->voteNegative(1, 'irrelevant');
413 | }
414 |
415 | /**
416 | * @expectedException \Symfony\Component\Finder\Exception\AccessDeniedException
417 | */
418 | public function testVotePositiveWithAnonymousAndNoIp()
419 | {
420 | $referenceVotes = new ReferenceVotes();
421 | $referenceVotes->setReference(1);
422 |
423 | $requestMock = $this->getMockBuilder(Request::class)
424 | ->disableOriginalConstructor()
425 | ->setMethods(array('getClientIp'))
426 | ->getMock();
427 | $requestMock->expects($this->any())
428 | ->method('getClientIp')->willReturn(null);
429 |
430 | $this->requestStackMock = $this->getMockBuilder(RequestStack::class)
431 | ->disableOriginalConstructor()
432 | ->setMethods(array('getCurrentRequest'))
433 | ->getMock();
434 | $this->requestStackMock->expects($this->any())
435 | ->method('getCurrentRequest')->willReturn($requestMock);
436 |
437 | $this->setAnonymousUserMocks();
438 |
439 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
440 |
441 | $this->assertSame(array('irrelevant'), $voter->getNegativeReasons());
442 | $this->assertSame(0, $voter->getPositiveVotes($referenceVotes->getReference()));
443 |
444 | $voter->votePositive($referenceVotes->getReference());
445 | }
446 |
447 | public function testPublishReference()
448 | {
449 | $referenceVotesMock = $this->getMockBuilder(ReferenceVotes::class)
450 | ->getMock();
451 | $referenceVotesMock->method('getReference')->willReturn(1);
452 | $referenceVotesMock->method('isPublished')->willReturn(true);
453 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
454 | $emRepositoryMock->method('findOneBy')->willReturn($referenceVotesMock);
455 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
456 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
457 |
458 | $this->setUserMocks();
459 |
460 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
461 |
462 | $voter->setPublished(1);
463 | $this->assertSame(true, $voter->isPublished(1));
464 | }
465 |
466 | /**
467 | * @expectedException \Exception
468 | */
469 | public function testPublishNoReference()
470 | {
471 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
472 | $emRepositoryMock->method('findOneBy')->willReturn(null);
473 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
474 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
475 |
476 | $this->setUserMocks();
477 |
478 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
479 |
480 | $voter->setPublished(1);
481 | }
482 |
483 | public function testIsPublishNoReference()
484 | {
485 | $emRepositoryMock = $this->getMockBuilder(ObjectRepository::class)->getMock();
486 | $emRepositoryMock->method('findOneBy')->willReturn(null);
487 | $this->emMock = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
488 | $this->emMock->method('getRepository')->willReturn($emRepositoryMock);
489 |
490 | $this->setUserMocks();
491 |
492 | $voter = new Voter($this->emMock, $this->tokenStorageMock, $this->requestStackMock, $this->translator, 50, 2, array('irrelevant'));
493 |
494 | $this->assertSame(false, $voter->isPublished(1));
495 | }
496 |
497 | private function getVotePositiveMock($user, $userIP = '127.0.0.1')
498 | {
499 | return $this->getMockBuilder(VotePositiveMock::class)
500 | ->setConstructorArgs(array($user, $userIP))
501 | ->getMock();
502 | }
503 |
504 | private function getVoteNegativeMock($user, $reason = 'irrelevant', $userIP = '127.0.0.1')
505 | {
506 | return $this->getMockBuilder(VoteNegativeMock::class)
507 | ->setConstructorArgs(array($user, $reason, $userIP))
508 | ->getMock();
509 | }
510 |
511 | }
--------------------------------------------------------------------------------
/Tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ./Tests
12 |
13 |
14 |
15 |
16 | ./
17 |
18 | ./MsalsasVotingBundle.php
19 | ./Controller
20 | ./Tests
21 | ./Tests
22 | ./vendor
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------