Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds reporter support, value objects, chunks table #119

Merged
merged 15 commits into from
Sep 20, 2019
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"php": ">=7.2",
"ext-sqlite3": "*",
"ext-pdo_sqlite": "*",
"lesstif/php-jira-rest-client": "^1.35"
"lesstif/php-jira-rest-client": "^1.35",
"morningtrain/toggl-api": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "~6",
Expand Down
52 changes: 50 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
<rule ref="Drupal.Commenting.FunctionComment.Missing">
<exclude-pattern>Repository.php</exclude-pattern>
</rule>
<rule ref="Drupal.Commenting.FunctionComment.IncorrectTypeHint">
<exclude-pattern>Chunk.php</exclude-pattern>
<exclude-pattern>DbRepository.php</exclude-pattern>
</rule>
<rule ref="Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase">
<exclude-pattern>Schema.php</exclude-pattern>
</rule>
Expand Down
14 changes: 12 additions & 2 deletions services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,26 @@ services:
http_client:
class: GuzzleHttp\Client
cache:
class: Doctrine\Common\Cache\FileSystemCache
class: Doctrine\Common\Cache\FilesystemCache
factory: [Larowlan\Tl\CacheFactory, create]
repository:
class: Larowlan\Tl\Repository\DbRepository
arguments: ["@connection"]
connector:
class: Larowlan\Tl\Connector\Manager
arguments: ['@container', '@cache', '%config%', '%version%']
arguments: ['@container', '@cache', '%config%', '%version%', '@reporter']
tags:
- { name: configurable }
reporter:
class: Larowlan\Tl\Reporter\Manager
arguments: ['@container', '@cache', '%config%', '%version%']
tags:
- { name: configurable }
reporter.toggl:
class: Larowlan\Tl\Reporter\Toggl
arguments: ['%config%', '@cache', '%version%']
tags:
- { name: reporter }
connector.redmine:
class: Larowlan\Tl\Connector\RedmineConnector
arguments: ['@http_client', '@cache', '%config%', '%version%']
Expand Down
100 changes: 100 additions & 0 deletions src/Chunk.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace Larowlan\Tl;

/**
* Defines a class for modelling a chunk of spent time.
*/
class Chunk {

/**
* Chunk ID.
*
* @var int
*/
protected $id;

/**
* Start timestamp.
*
* @var int
*/
protected $start;

/**
* End timestamp.
*
* @var int
*/
protected $end;

/**
* Constructs a new Chunk.
*
* @param int $id
* ID.
* @param int $start
* Start.
* @param int $end
* End.
*/
public function __construct(int $id, int $start, ?int $end) {
$this->id = $id;
$this->start = $start;
$this->end = $end;
}

/**
* Gets value of Start.
*
* @return int
* Value of Start.
*/
public function getStart(): int {
return $this->start;
}

/**
* Gets value of End.
*
* @return int
* Value of End.
*/
public function getEnd(): ?int {
return $this->end;
}

/**
* Gets value of Id.
*
* @return int
* Value of Id.
*/
public function getId(): int {
return $this->id;
}

/**
* Sets value of End.
*
* @param int $end
* Value for End.
*
* @return $this
*/
public function setEnd(int $end): Chunk {
$this->end = $end;
return $this;
}

/**
* Gets duration.
*
* @return int
* Duration.
*/
public function getDuration() : int {
return ($this->end ?: time()) - $this->start;
}

}
7 changes: 4 additions & 3 deletions src/Commands/Bitbar.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,17 @@ protected function configure() {
*/
protected function execute(InputInterface $input, OutputInterface $output) {
if ($open = $this->repository->getActive()) {
$text = $open->tid . ': ' . Formatter::formatDuration(time() - $open->start) . ' ';
$text = $open->getTicketId() . ': ' . Formatter::formatDuration($open->getDuration()) . ' ';
}
else {
$text = 'Inactive ';
}
$total = 0;
/** @var \Larowlan\Tl\Slot $data */
foreach ($this->repository->review(Total::ALL) as $data) {
$total += $data->duration;
$total += $data->getDuration(FALSE, TRUE);
}
$text .= '(' . $total . 'h)';
$text .= '(' . $total / 3600 . 'h)';
$output->writeln($text);
}

Expand Down
37 changes: 13 additions & 24 deletions src/Commands/Combine.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,13 @@ protected function configure() {
protected function execute(InputInterface $input, OutputInterface $output) {
$slot1 = $input->getArgument('slot1');
$slot2 = $input->getArgument('slot2');
list($entry1, $entry2) = $this->validateSlots($slot1, $slot2, $output);

// Create a new combined entry and then remove fields we don't want to keep
// around in the new entry.
$combined_entry = clone $entry1;
unset($combined_entry->id, $combined_entry->category, $combined_entry->comment, $combined_entry->teid, $combined_entry->connector_id);
$combined_entry->connector_id = ':connector_id';

// Extend the entry date by the amount of time logged in the second entry.
$combined_entry->end = $entry1->end + ($entry2->end - $entry2->start);

// Insert the new entry, if all is well delete the two existing ones.
if ($new_slot = $this->repository->insert((array) $combined_entry, [':connector_id' => $entry1->connector_id])) {
$this->repository->delete($entry1->id);
$this->repository->delete($entry2->id);
/** @var \Larowlan\Tl\Slot $entry1 */
/** @var \Larowlan\Tl\Slot $entry2 */
list($entry1, $entry2) = $this->validateSlots($slot1, $slot2, $output);
$this->repository->combine($entry1, $entry2);

$output->writeln(sprintf('Combined %s and %s into new slot %s', $slot1, $slot2, $new_slot));
}
$output->writeln(sprintf('Combined %s and %s into new slot %s', $slot1, $slot2, $slot1));
}

/**
Expand All @@ -92,15 +81,15 @@ protected function validateSlots($slot1, $slot2, OutputInterface $output) {
if (!$entry2 = $this->repository->slot($slot2)) {
throw new \InvalidArgumentException(sprintf('Invalid slot id %s', $slot2));
}
if ($entry1->connector_id !== $entry2->connector_id) {
throw new \InvalidArgumentException(sprintf('You cannot combine slots from %s backend with slots from %s backend', Manager::formatConnectorId($entry2->connector_id), Manager::formatConnectorId($entry1->connector_id)));
if ($entry1->getConnectorId() !== $entry2->getConnectorId()) {
throw new \InvalidArgumentException(sprintf('You cannot combine slots from %s backend with slots from %s backend', Manager::formatConnectorId($entry2->getConnectorId()), Manager::formatConnectorId($entry1->getConnectorId())));
}
// Ensure we've not already sent the slots.
if (!empty($entry1->teid) || !empty($entry1->teid)) {
if (!empty($entry1->getRemoteEntryId()) || !empty($entry1->getRemoteEntryId())) {
throw new \InvalidArgumentException('You cannot combine entries that have already been sent.');
}
// Ensure the slots are both against the same job.
if ($entry1->tid != $entry2->tid) {
if ($entry1->getTicketId() != $entry2->getTicketId()) {
throw new \InvalidArgumentException('You cannot combine entries from separate issues.');
}
return [$entry1, $entry2];
Expand All @@ -111,12 +100,12 @@ protected function validateSlots($slot1, $slot2, OutputInterface $output) {
*/
protected function stopTicket($slot_id, OutputInterface $output) {
if ($stop = $this->repository->stop($slot_id)) {
$stopped = $this->connector->ticketDetails($stop->tid, $stop->connector_id);
$stopped = $this->connector->ticketDetails($stop->getTicketId(), $stop->getConnectorId());
$output->writeln(sprintf('Closed slot <comment>%d</comment> against ticket <info>%d</info>: %s, duration <info>%s</info>',
$stop->id,
$stop->tid,
$stop->getId(),
$stop->getTicketId(),
$stopped->getTitle(),
Formatter::formatDuration($stop->duration)
Formatter::formatDuration($stop->getDuration())
));
}
}
Expand Down
13 changes: 7 additions & 6 deletions src/Commands/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,24 @@ protected function execute(InputInterface $input, OutputInterface $output) {
$entries = $this->repository->review(Review::ALL, !$input->getOption('recomment'));
$helper = $this->getHelper('question');
$last = FALSE;
/** @var \Larowlan\Tl\Slot $entry */
foreach ($entries as $entry) {
if ($entry->comment && !$input->getOption('recomment')) {
if ($entry->getComment() && !$input->getOption('recomment')) {
continue;
}
$title = $this->connector->ticketDetails($entry->tid, $entry->connector_id);
$title = $this->connector->ticketDetails($entry->getTicketId(), $entry->getConnectorId());
$question = new Question(
sprintf('Enter comment for slot <comment>%d</comment> [<info>%d</info>]: %s [<info>%s h</info>] [%s]',
$entry->id,
$entry->tid,
$entry->getId(),
$entry->getTicketId(),
$title->getTitle(),
$entry->duration,
$entry->getDuration(FALSE, TRUE) / 3600,
$last ?: static::DEFAULT_COMMENT
),
$last ?: static::DEFAULT_COMMENT
);
$comment = $helper->ask($input, $output, $question);
$this->repository->comment($entry->id, $comment);
$this->repository->comment($entry->getId(), $comment);
$last = $comment;
}
if (!$last) {
Expand Down
13 changes: 7 additions & 6 deletions src/Commands/Continues.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ protected function configure() {
*/
protected function execute(InputInterface $input, OutputInterface $output) {
if ($slot_id = $input->getArgument('slot_id')) {
$this->repository->stop();
$slot = $this->repository->slot($slot_id);
}
else {
$slot = $this->repository->latest();
$slot = $this->repository->stop() ?: $this->repository->latest();
}
if ($slot) {
$details = $this->connector->ticketDetails($slot->tid, $slot->connector_id);
list($slot_id, $continued) = $this->repository->start($slot->tid, $slot->connector_id, $slot->comment, $slot->id);
$details = $this->connector->ticketDetails($slot->getTicketId(), $slot->getConnectorId());
$start = $this->repository->start($slot->getTicketId(), $slot->getConnectorId(), $slot->getComment(), $slot->getId());
$output->writeln(sprintf('<bg=blue;fg=white;options=bold>[%s]</> <comment>%s</comment> entry for <info>%d</info>: %s [slot:<comment>%d</comment>]',
(new \DateTime())->format('h:i'),
$continued ? 'Continued' : 'Started new',
$slot->tid,
$start->isContinued() ? 'Continued' : 'Started new',
$slot->getTicketId(),
$details->getTitle(),
$slot_id
$slot->getId()
));

return;
Expand Down
8 changes: 4 additions & 4 deletions src/Commands/Delete.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ protected function execute(InputInterface $input, OutputInterface $output) {

$confirm = NULL;
if (($slot = $this->repository->slot($slot_id)) && ($confirm = ($input->getOption('confirm') || $helper->ask($input, $output, $question))) && $this->repository->delete($slot_id)) {
$deleted = $this->connector->ticketDetails($slot->tid, $slot->connector_id);
$deleted = $this->connector->ticketDetails($slot->getTicketId(), $slot->getConnectorId());
$output->writeln(sprintf('Deleted slot <comment>%d</comment> against ticket <info>%d</info>: %s, duration <info>%s</info>',
$slot->id,
$slot->tid,
$slot->getId(),
$slot->getTicketId(),
$deleted->getTitle(),
Formatter::formatDuration($slot->end - $slot->start)
Formatter::formatDuration($slot->getDuration())
));
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/Edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected function execute(InputInterface $input, OutputInterface $output) {
$slot_id = $input->getArgument('slot_id');
$duration = $input->getArgument('duration');
$slot = $this->repository->slot($slot_id);
if (isset($slot->teid)) {
if ($slot->getRemoteEntryId()) {
$output->writeln('<error>You cannot edit a slot that has been sent to the backend</error>');
return 1;
}
Expand Down
Loading