stephpy/timeline-bundle

Get Component By Id

Closed this issue · 12 comments

Hello again.
I continue with the same functionality.

A user can creates a state and I show it in his timeline.
When a user views his state He can delete it, so I delete the object State and I want to also delete the action of my timeline.

To do this I have to use the method of TimeLineManager removeAll, sending as a parameter ComponentInterface from the template.

Then I need to retrieve the component by its id, but in the ActionManager there is only the function findComponentWithHash ($ hash) and I can't send the hash by url.

I need create the funciont findComponentWithId($id) ?? or I want to do wrong?

If I need create the funciont findComponentWithId I can do a pull request.

Hi

You could do:

$this->get('doctrine.orm.entity_manager')->getRepository('AcmeBundle:Component')->find($id);

I'm not sure it's useful to add this on ActionManager because we should supports this method on other drivers, and this method will not be used on TimelineBundle.

Ok, but...

So TimelineBundle allows delete a action of the timeline?

For example: Chuck norris is kicking Walter , but Chuck Norris was wrong and He want to kick to Vic Mac Key.

how is it managed by TimeLineBundle?

Because the functions REMOVE() delete the row of Timeline but it doesnt delete the row spy_timeline_action_component ....

Además it must delete of all timelines of his friends...

is it allows in TimeLineBundle?

Thanks !!

You should remove the action entry and not the timeline.

By default, on documentation there is no cascade on delete action for Timeline table but you can add this ;)

By this way, when you'll delete an action, it'll delete Timelines and ActionComponents associateds ;)

In Timeline

<?php

namespace Yo\UrBundle\Entity;

use Spy\TimelineBundle\Entity\Timeline as BaseTimeline;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="spy_timeline")
 */
class Timeline extends BaseTimeline
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Yo\UrlBundle\Entity\Action")
     * @ORM\JoinColumn(name="action_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $action;

    /**
     * @ORM\ManyToOne(targetEntity="Yo\UrlBundle\Entity\Component")
     * @ORM\JoinColumn(name="subject_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $subject;
}

If you want to delete a timeline and not the action, just remove the timeline entry and let action.

I want delete all, the entry and timeline.

i.e. I want anyone to know that Chuck Norris kicked Walter. jejeje You understand me ?

The functions to delete are: Remove() and RemoveAll() of TimeLineManager, doesnt it ?

I do:

/**
     * @Rest\View(statusCode=204)
     */
    public function deleteAction($id){
        $em = $this->get('doctrine')->getEntityManager();
        $e = $em->getRepository('SocialBundle:State')->find($id);

        if (!$e) {
            throw $this->createNotFoundException('No se ha encontrado el estado que se quiere borrar por la id '.$id);
        }
        else {          
            $u = $this->get('security.context')->getToken()->getUser();
            $actionManager   = $this->get('spy_timeline.action_manager');
            $subject         = $actionManager->findOrCreateComponent($u);
            $this->get('spy_timeline.timeline_manager.orm')->removeAll($subject);
            $this->get('spy_timeline.timeline_manager.orm')->flush();
            $em->remove($e);
            $em->flush();               
        }
    }

I also use the method remove.. but the actions persist in the database, only it delete the row spy_timeline.

I included the cascade and updated the database

My timeline is:

<?php

namespace ant\SocialBundle\Entity;

use Spy\TimelineBundle\Entity\Timeline as BaseTimeline;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="spy_timeline")
 */
class Timeline extends BaseTimeline
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="ant\SocialBundle\Entity\Action")
     * @ORM\JoinColumn(name="action_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $action;

    /**
     * @ORM\ManyToOne(targetEntity="ant\SocialBundle\Entity\Component")
     * @ORM\JoinColumn(name="subject_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $subject;
}

It's normal.

TimelineManager->removeAll removes Timeline entries, you have to remove Action entries and it'll cascade on Timelines and TimelineActions, it's a mysql behavior.

You can create your own method to delete them.

Since DELETE from mysql does not support joins, you'll have to:

  • Delete actions in two steps, retrieve them and delete them.
  • Create a SQL command which do the first point.

For the first point, you can do:

$em       = $this->get('doctrine.orm.entity_manager');
$actions =  $actionManager->getSubjectActions($component);
foreach ($actions as $action) {
    $em->remove($action);
}
$em->flush();

Problem, it'll only delete actions which has status published, sure, you can create your own request to fetch ALL subject actions, take reference on this

And if you delete Actions, it'll may stay some timeline for the user, you have to delete them too ...

To re-explain the concept:

Action 1: User1 comments photo1
Action 2: User2 comments photo1
Action 3: User3 comments photo1

Timeline of User1: [Action1, Action2]
Timeline of User2: [Action1, Action2, Action3]
Timeline of User3: [Action3]

In this example, if you delete actions of user 1, it'll stay timeline entries for User1.

I'm not sure to get what you expect to do.

Do you want to delete ALL traces from the components ?

Exactly @stephpy .

I want to delete ALL traces, i.e. if User1 delete his comment, I understand that User2 and User3 can not see it.
User1 deleted one comment is for nobody to see it, I understand this it.

For example, User1 wrote: This photo was on April 6 at 8:00 with User2 in Paris.

But User1 was wrong and the date was April 16 at 8:00 in New York.

So Timeline of User2 can not to have this comment.

Thanks for your time!

I think I see the problem, but let me know if I'm wrong trying to explain it:
Action: User 1 commented on Photo 1
User 2's timeline: User 1 commented on Photo 1
User 3's timeline: User 1 commented on Photo 1

then Photo 1 gets deleted, so there's no photo to be referenced anymore, so it needs to be deleted from all actions and timelines.

exactly @Nemesisprime

That is the question. : )

@Chrysweel DataHydrator allow to filter actions which contains a deleted components. Here, if you remove the Photo1 and having action which referers to it, theses actions will be filtered. If you are using ORM:

spy_timeline:
    filters:
        data_hydrator:
            filter_unresolved:    true
            locators:
                - spy_timeline.filter.data_hydrator.locator.doctrine_orm

Ok It solved

Ok it solved.

I included this function.

public function getQueryBuilderForComponent(ComponentInterface $component){
        return $this->objectManager
             ->getRepository($this->actionClass)
             ->createQueryBuilder('a')
             ->innerJoin('a.actionComponents', 'ac2', Expr\Join::WITH, '(ac2.action = a AND ac2.component = :component)')
             ->leftJoin('a.actionComponents', 'ac')
             ->setParameter('component', $component)
             ->getQuery()->getSingleResult()
        ;
    }

And in my controller deletePhotoAction...

$u = $this->get('security.context')->getToken()->getUser();
$actionManager   = $this->get('spy_timeline.action_manager');
$subject  = $actionManager->findOrCreateComponent($u);
$photoObject = $actionManager->findOrCreateComponent($photo);
$action = $actionManager->getQueryBuilderForComponent($photoObject);
$em->remove($action);
$em->remove($photoObject);

So in my database, there are not nothing data of this action

Thank You very much!