Skip to content

Instantly share code, notes, and snippets.

@sameg14
Created April 29, 2016 20:04
Show Gist options
  • Save sameg14/e23238bba8f34ac1144086f8567fa697 to your computer and use it in GitHub Desktop.
Save sameg14/e23238bba8f34ac1144086f8567fa697 to your computer and use it in GitHub Desktop.
<?php
namespace Tib\CoreBundle\Service;
use Tib\CoreBundle\Db\DBCommon;
use Tib\CoreBundle\Model\Mix;
use Tib\CoreBundle\Model\User;
use Tib\CoreBundle\Model\MixComment;
use Tib\CoreBundle\Util\Inflect;
use Tib\CoreBundle\Util\FilterOutput;
use Tib\CoreBundle\Util\RemoteAddress;
use Tib\CoreBundle\Exception\SpamException;
use Tib\CoreBundle\Exception\MissingDataException;
use Tib\CoreBundle\Exception\InvalidDataException;
use Tib\CoreBundle\Exception\MissingPropertyException;
use Symfony\Component\HttpFoundation\Session\Session;
use \Swift_Mailer;
use \stdClass;
use Aws\S3\Exception\S3Exception;
/**
* Class MixHydrate deals with the business of creating Mix objects
* @package Tib\CoreBundle\Service
*/
class MixService extends AbstractService
{
/**
* @var Mix[]
*/
protected $popularMixes;
/**
* Handles processing mix images and such
*
* @var MixImageService
*/
protected $mixImageService;
/**
* @var Mix
*/
protected $mixModel;
/**
* MixService constructor.
* @param DBCommon $db
* @param Session $session
* @param Swift_Mailer $mailer
* @param MixImageService $mixImage
* @param S3Service $s3
* @param UserService $user
* @param RemoteAddress $remoteAddress
* @param Mix $mixModel
*/
public function __construct(DBCommon $db, Session $session, Swift_Mailer $mailer, MixImageService $mixImage, S3Service $s3, UserService $user, RemoteAddress $remoteAddress, Mix $mixModel)
{
$this->setDb($db);
$this->setSession($session);
$this->setMailer($mailer);
$this->setMixImageService($mixImage);
$this->setS3Service($s3);
$this->setUserService($user);
$this->setRemoteAddress($remoteAddress);
$this->setMixModel($mixModel);
}
/**
* Get a bunch of Mix objects back from these Ids
* @param array $mixIds Array of mixIds from the DB
* @return Mix[] | null
*/
public function getMixes($mixIds)
{
$mixRows = $this->getMixModel()->getMixes($mixIds);
$mixObjects = $this->createMixObjects($mixRows);
return array_reverse($mixObjects);
}
/**
* Get all the latest mixes that have been uploaded
* @param int $limit The number of latest mixes to get
* @return Mix[]
*/
public function getLatestMixes($limit = 20)
{
$mixRows = $this->mixModel->getLatestMixes($limit);
return $this->createMixObjects($mixRows);
}
/**
* Get popular mixes
* @param int $limit The number of top mixes to get
* @return Mix[]|null
*/
public function getPopularMixes($limit = 10)
{
if (isset($this->popularMixes)) {
return $this->popularMixes;
}
$popularMixRows = $this->mixModel->getPopularMixes($limit);
if (empty($popularMixRows)) {
return $this->getPopularMixes();
}
return $this->popularMixes = $this->createMixObjects($popularMixRows);
}
/**
* Get an array of mixIds from the genre and subGenre
* @param string $genre Genre SEF name
* @param string $subGenre Sub-Genre SEF name
* @return array
*/
public function getMixesByGenreAndSubGenreSlug($genre, $subGenre)
{
$mixRows = $this->mixModel->getMixesByGenreAndSubGenreSlug($genre, $subGenre);
return $this->createMixObjects($mixRows);
}
/**
* Get a mix by its SEF slug
* @param string $slug mix slug
* @return Mix
*/
public function getBySlug($slug)
{
$mixRows = $this->mixModel->getBySlug($slug);
if (empty($mixRows)) {
return null;
}
$mixArray = $this->createMixObjects($mixRows);
if (empty($mixArray)) {
return null;
}
return array_pop($mixArray);
}
/**
* Get all mixes for this user
* @param string $userSlug SEF Slug for this user
* @return Mix[]|null
*/
public function getMixesByUserSlug($userSlug)
{
$rows = $this->mixModel->getMixesByUserSlug($userSlug);
return $this->createMixObjects($rows);
}
/**
* Get an array of mix names and slugs
* @return stdClass[]
*/
public function getMixNamesForUser()
{
$userId = $this->session->get('userId');
return $this->mixModel->getMixNamesForUser($userId);
}
/**
* @param MixImageService $mixImageService
*/
public function setMixImageService($mixImageService)
{
$this->mixImageService = $mixImageService;
}
/**
* Add a comment to this mix
* @param string $mixSlug SEF Slug for this mix
* @param string $name Name of the person writing the comment
* @param string $location Where the person is located
* @param string $comment The comment itself
* @throws MissingDataException
* @throws SpamException
* @return array|null
* @todo: refactor this out to the model
*/
public function processComment($mixSlug, $name, $location, $comment)
{
if (empty($mixSlug)) {
throw new MissingDataException('Mix not found!');
}
if (empty($name)) {
throw new MissingDataException('Please enter your name');
}
if (empty($location)) {
throw new MissingDataException('Please enter a location');
}
if (empty($comment)) {
throw new MissingDataException('Your comment cannot be empty');
}
if ($location == 'New York') {
throw new SpamException();
}
// If this user is determined to be a known spammer, throw a SpamException
$this->userService->blacklistCheck();
$name = $this->db->quote(FilterOutput::cleanText($name));
$location = $this->db->quote(FilterOutput::cleanText($location));
$comment = $this->db->quote(FilterOutput::cleanText($comment));
$ip = $this->db->quote($this->remoteAddress->getIpAddress());
$query
= '
select
m.mixid,
m.name as mix_name,
u.email
from
' . Mix::TABLE_NAME . ' m
inner join ' . User::TABLE_NAME . ' u on (u.id = m.userid)
where
m.slug="' . $this->db->quote($mixSlug) . '"';
$this->db->setQuery($query);
$obj = $this->db->loadObject();
if (empty($obj)) {
throw new MissingDataException('mixId cannot be determined!');
}
$mixId = $obj->mixid;
$email = $obj->email;
$mixName = $obj->mix_name;
if (empty($mixId)) {
throw new MissingDataException('mixId cannot be determined!');
}
if (empty($email)) {
throw new MissingDataException('Email cannot be determined from this mix');
}
$hash = sha1($mixId . $email . $mixName . strtotime('now'));
$query = 'replace into '
. MixComment::TABLE_NAME
. ' set name="' . $name
. '", location ="' . $location
. '", comment = "' . $comment
. '", mixId = "' . $mixId
. '", hash = "' . $hash
. '", source_ip = "' . $ip . '"';
$this->db->setQuery($query);
if (!$this->db->query()) {
return false;
}
return array(
'mixName' => $mixName,
'email' => $email,
'hash' => $hash
);
}
/**
* Delete a mix
* @param int $userId The user who owns this mix
* @param int $mixId PK for this mix to get nixed
* @throws MissingDataException
* @throws S3Exception
* @throws InvalidDataException
* @return bool
* @todo: fire off a job for this API call
*/
public function deleteMix($userId, $mixId)
{
if (empty($userId)) {
throw new MissingDataException('Invalid user operation');
}
if (empty($mixId)) {
throw new MissingDataException('Invalid mix');
}
$user = $this->userService->getUserById($userId);
if (empty($user)) {
throw new InvalidDataException('Invalid user');
}
$mixes = $this->getMixes(array($mixId));
if (empty($mixes)) {
throw new InvalidDataException('Invalid Mix cannot be retrieved');
}
/** @var Mix $mix */
$mix = array_pop($mixes);
$s3MixStatus = $this->s3Service->deleteMix($user->getSlug(), $mix->getFileName());
if (!$s3MixStatus) {
throw new S3Exception('Cannot delete mix from S3');
}
$s3ImageStatus = $this->s3Service->deleteMixImages(
$user->getSlug(), $mix->getS3ImageFilename(), $mix->getS3ThumbFilename()
);
if (!$s3ImageStatus) {
throw new S3Exception('Cannot delete images from S3');
}
return $mix->delete();
}
/**
* Get the current play position, if possible
* @param int $mixId PK from ill_mixes
* @param int $userId If the user is logged in, get their Id
* @param string $sessionId Current string sessionId
* @return float
*/
public function getPlayPosition($mixId, $userId, $sessionId)
{
$positionId = $this->discoverPositionId($mixId, $userId, $sessionId);
if (!empty($positionId)) {
$query = 'select position from ill_position where id = "' . $this->db->quote($positionId) . '"';
$this->db->setQuery($query);
return (float) $this->db->loadResult();
}
return 0.00;
}
/**
* Update the currently playing position of this mix
* @param int $mixId PK from ill_mixes
* @param int $userId If the user is logged in, get their Id
* @param float $position Currently playing track position in seconds
* @param string $sessionId Current string sessionId
* @return bool
*/
public function updatePosition($mixId, $userId, $position, $sessionId)
{
$mixId = $this->db->quote($mixId);
$userId = $this->db->quote($userId);
$position = $this->db->quote($position);
$sessionId = $this->db->quote($sessionId);
// Try to get one with a user record first
$id = $this->discoverPositionId($mixId, $userId, $sessionId);
// Create one
if (empty($id)) {
$query = '
insert into ill_position
(sessid, userid, mixid, position)
values
("' . $sessionId . '", "' . $userId . '", "' . $mixId . '", "' . $position . '")';
$this->db->setQuery($query);
return $this->db->query();
}
$query = 'update ill_position set position = "' . $position . '" where id = "' . $id . '"';
$this->db->setQuery($query);
return $this->db->query();
}
/**
* Process a moderated mix comment
* @param string $hash Hash to identify unique mix_comment
* @param string $shouldApprove Will be either [approve, deny]
* @throws InvalidDataException
* @return stdClass
*/
public function processCommentModeration($hash, $shouldApprove)
{
if (empty($hash) || empty($shouldApprove)) {
throw new InvalidDataException('Invalid request');
}
$query = '
select
m.name as mix_name,
u.email,
mc.name as comment_name,
mc.location as comment_location,
mc.comment as comment_text,
mc.source_ip as source_ip
from
mix_comments mc
inner join ill_mixes m on (m.mixid = mc.mixId)
inner join jos_users u on (u.id = m.userid)
where
mc.hash = "' . $hash . '"';
$this->db->setQuery($query);
$data = $this->db->loadObject();
if (empty($data)) {
throw new InvalidDataException('Invalid hash');
}
// Spam, don't even bother sending an email
if ($shouldApprove == 'deny') {
// Nix the comment
$query = 'delete from mix_comments where hash = "' . $hash . '"';
$this->db->setQuery($query);
$this->db->query();
// Blacklist the IP
$this->userService->blacklistSpammer($data->source_ip);
}
return $data;
}
/**
* Create mix objects from raw mix rows from the DB
* @param stdClass[] $mixRows from query
* @throws MissingPropertyException
* @return Mix[]
*/
protected function createMixObjects($mixRows)
{
/** @var Mix[] $mixes */
$mixes = [];
if (empty($mixRows)) {
return null;
}
foreach ($mixRows as $mixRow) {
$mix = clone($this->getMixModel());
foreach ($mixRow as $k => $v) {
$setter = 'set' . Inflect::underscoreToProper($k);
// If we don't have a slug, set one explicitly
if ($k == 'slug' && empty($v)) {
$v = Inflect::titleToSef($mix->getName());
}
if (method_exists($mix, $setter)) {
$mix->$setter($v);
} else {
throw new MissingPropertyException(get_class($mix) . ' is missing a setter "' . $setter . '"');
}
}
array_push($mixes, $mix);
}
return $mixes;
}
/**
* Attempt to discover a positionId for a given mix
* @param int $mixId PK from ill_mixes
* @param int $userId If the user is logged in, get their Id
* @param string $sessionId Current string sessionId
* @return mixed
*/
protected function discoverPositionId($mixId, $userId, $sessionId)
{
// Try to get one with a user record first
$query = 'select id from ill_position where userid = "' . $userId . '" and mixid = "' . $mixId . '"';
$this->db->setQuery($query);
$id = $this->db->loadResult();
// Try to get it via session
if (empty($id)) {
$query = 'select id from ill_position where sessid = "' . $sessionId . '" and mixid = "' . $mixId . '"';
$this->db->setQuery($query);
$id = $this->db->loadResult();
}
return $id;
}
/**
* @return Mix
*/
public function getMixModel()
{
return $this->mixModel;
}
/**
* @param Mix $mixModel
*/
public function setMixModel($mixModel)
{
$this->mixModel = $mixModel;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment