Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a00ba22
feat:implement_toString_for_result_class
naingaunglwin-dev Nov 3, 2025
20c6a45
feat:implement_toString_for_Result_class (#1)
naingaunglwin-dev Nov 3, 2025
356ba15
feat:implement_stop()_to_replace_deprecated_end()
naingaunglwin-dev Nov 4, 2025
36158ef
feat:implement_stop()_to_replace_deprecated_end() (#2)
naingaunglwin-dev Nov 4, 2025
d8021bd
refactor:replace_ramsey_uuid_with_native_php_functions
naingaunglwin-dev Nov 4, 2025
169e921
refactor:replace_ramsey_uuid_with_native_php_functions (#3)
naingaunglwin-dev Nov 4, 2025
2cb648d
refactor:rename_static_method_from_run()_to_watch()
naingaunglwin-dev Nov 5, 2025
52a5090
refactor:rename_static_method_from_run()_to_watch() (#4)
naingaunglwin-dev Nov 5, 2025
8835ec7
refactor:move_timer_status_to_dedicated_Enum_class (#5)
naingaunglwin-dev Nov 5, 2025
aa0808d
fix:update_timer_status_constant_with_enum_in_test_cases (#6)
naingaunglwin-dev Nov 6, 2025
354eb66
feat:add_new_methods_in_timetracker (#7)
naingaunglwin-dev Nov 6, 2025
f1429b0
fix:add_isStopped_check_in_finally_block_to_prevent_duplicate_stop_ca…
naingaunglwin-dev Nov 10, 2025
68e482e
docs:update_README_to_include_new_methods
naingaunglwin-dev Nov 10, 2025
0efdebc
feat: add new methods in timetracker (#9)
naingaunglwin-dev Dec 9, 2025
98178b2
chore: add phpunit cache and coverage folders to .gitignore
naingaunglwin-dev Dec 9, 2025
91c84d9
chore: add test workflow for master and dev branches (#10)
naingaunglwin-dev Dec 9, 2025
b7d3e0d
refactor: restore run() as deprecated alias for backward compatibilit…
naingaunglwin-dev Dec 9, 2025
e7d046e
docs: add changelog for recent changes (#12)
naingaunglwin-dev Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Tests

on:
push:
branches: [ "master", "dev" ]
pull_request:
branches: [ "master", "dev" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3

- name: Validate composer.json and composer.lock
run: composer validate --strict

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-

- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest

- name: Run test suite
run: composer test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ vendor/
# Ignore PHPUnit configuration file (if you're using phpunit.xml for local customizations)
phpunit.xml

# Ignore PHPUnit test result output files
.phpunit.cache
coverage-report

# Ignore Composer lock file if you don't want to share it (usually, you want to commit composer.lock)
# composer.lock

Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ChangeLog

## v1.1.0 - 2025-12-09
### Added
- Implemented `__toString()` method for the `Result` class, allowing instances to be converted to strings (e.g. `"$result"` now returns the calculated value). (PR #1)
- Added new `stop()` method to the timer, supporting stopping: (PR #2)
- a specific timer by ID
- **or** the **most recently started timer** when no ID is provided.
- Added new `watch()` static method to replace `run()` for executing and timing callbacks. (PR #4)
- Added new timer utility methods `isStarted()`, `isStopped()`, and `getActiveTimers()` in `TimeTracker` to inspect active and completed timers. (PR #7)
- Added new timer utility methods `lap()`, `getLaps()`, `pause()`, `resume()`, and `inspect()` in `TimeTracker`. (PR #9)

### Changed
- Replaced `ramsey/uuid` with native PHP functions (`bin2hex(random_bytes(16))`) for generating random IDs. (PR #3)
- Removed the `ramsey/uuid` dependency as it is no longer required. (PR #3)
- Replaced `STATUS_*` string constants with a dedicated `TimerStatus` enum. (PR #5)

### Fixed
- Prevent duplicate `stop()` calls in `watch()` by adding an `isStopped()` check in the `finally` block. (RP #8)

### Deprecated
- Marked `end()` as deprecated. It still works for backward compatibility but will be removed in a future major release. (PR #2)
- Marked `run()` as deprecated. It still works for backward compatibility but will be removed in a future major release. (PR #4)
115 changes: 77 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,25 @@
- composer

## Installation via Composer
To install, navigate to your project root directory (where `composer.json` is located) and run the following command:
```shell
composer require naingaunglwin-dev/timetracker
> If Composer is not installed, follow the [official guide](https://getcomposer.org/download/).

1. Create a `composer.json` file at your project root directory (if you don't have one):
```json
{
"require": {
"naingaunglwin-dev/timetracker": "^1.0"
}
}
```

- Run the following command in your terminal from the project's root directory:
```bash
composer install
```
- If `composer.json` doesn't exits, run this command first,
```shell
composer init

If you already have `composer.json` file in your project, just run this command in your terminal,
```bash
composer require naingaunglwin-dev/timetracker
```

## Usage
Expand All @@ -40,7 +52,7 @@ $tracker->start('test');
echo 'hello world<br>';
sleep(3);

$tracker->end('test');
$tracker->stop('test');

echo $tracker->calculate('test')
->get();
Expand All @@ -53,18 +65,12 @@ echo $tracker->calculate('test')
### Convert to different unit
- By default, the unit is in seconds (s). You can convert to other predefined units like milliseconds (ms), microseconds (us), and more:
```php
<?php

require 'vendor/autoload.php';

$tracker = new NAL\TimeTracker\TimeTracker();

$tracker->start('test');

echo 'hello world<br>';
sleep(3);

$tracker->end('test');
$tracker->stop('test');

echo $tracker->calculate('test')
->convert('ms')
Expand All @@ -78,18 +84,12 @@ echo $tracker->calculate('test')
### Add custom unit
- You can define custom units based on seconds (for example, converting seconds to custom units):
```php
<?php

require 'vendor/autoload.php';

$tracker = new NAL\TimeTracker\TimeTracker();

$tracker->start('test');

echo 'hello world<br>';
sleep(3);

$tracker->end('test');
$tracker->stop('test');

// Add a custom unit definition (1 second = 10 custom units)
$tracker->addUnitDefinition('testunit', '*', 10);
Expand All @@ -106,18 +106,12 @@ echo $tracker->calculate('test')
### Format output
- You can format the output of the calculated time using placeholders:
```php
<?php

require 'vendor/autoload.php';

$tracker = new NAL\TimeTracker\TimeTracker();

$tracker->start('test');

echo 'hello world<br>';
sleep(3);

$tracker->end('test');
$tracker->stop('test');

echo $tracker->calculate('test')
->convert('ms')
Expand All @@ -132,23 +126,21 @@ echo $tracker->calculate('test')
### Time tracking with callback function
- You can track time for a callback function and get both the execution time and the result:
```php
$result = \NAL\TimeTracker\TimeTracker::run(
function (Conversation $conv, $time) {
sleep(3);
return $conv->greet($time) . '<br>do something at ' . $time;
},
['time' => 'evening'], //parameters variableName => value
'ms' // time unit, default is `s`
);

class Conversation
{
public function greet($time){
return 'good ' . $time;
}
}

var_dump($result);
$watch = \NAL\TimeTracker\TimeTracker::watch(
function (Conversation $conv, $time) {
sleep(3);
return $conv->greet($time) . '<br>do something at ' . $time;
},
['time' => 'evening'], //parameters variableName => value
'ms' // time unit, default is `s`
);
```
- Example output:
```php
Expand All @@ -160,3 +152,50 @@ array (size=4)
'unit' => string 'ms' (length=2)
'output' => string 'good evening, do something at evening' (length=37)
```

### Checking timer states

The following methods help you check timer states and get currently active timers.

#### Check if a timer has started
```php
$tracker->start('download');

if ($tracker->isStarted('download')) {
echo "Download timer is started.";
}

// Output:
// Download timer is started.
```

#### Check if a timer has stopped
```php
$tracker->start('process');

sleep(1);

$tracker->stop('process');

if ($tracker->isStopped('process')) {
echo "Process timer is stopped.";
}

// Output:
// Process timer is stopped.
```

#### Get currently active timers
```php
$tracker->start('task1');
$tracker->start('task2');
$tracker->stop('task1');

print_r($tracker->getActiveTimers());

// Output:
// Array
// (
// [0] => task2
// )
```
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "naingaunglwin-dev/timetracker",
"description": "A lightweight time tracker for php",
"minimum-stability": "stable",
"version": "1.0.0",
"type": "library",
"prefer-stable": true,
"license": "MIT",
Expand All @@ -19,10 +18,12 @@
},
"require": {
"php": ">=8.3",
"ramsey/uuid": "^4.7",
"illuminate/container": "^11.36"
},
"require-dev": {
"phpunit/phpunit": "^11.5"
},
"scripts": {
"test": "vendor/bin/phpunit tests"
}
}
11 changes: 11 additions & 0 deletions src/Exception/NoActivePausedTimerToResume.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace NAL\TimeTracker\Exception;

class NoActivePausedTimerToResume extends \BadMethodCallException
{
public function __construct($id)
{
parent::__construct("The timer with ID '{$id}' has no active pause to resume");
}
}
13 changes: 13 additions & 0 deletions src/Exception/NoActiveTimerToStopException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace NAL\TimeTracker\Exception;

use BadMethodCallException;

class NoActiveTimerToStopException extends BadMethodCallException
{
public function __construct()
{
parent::__construct("No active timer to stop.");
}
}
13 changes: 13 additions & 0 deletions src/Exception/TimerAlreadyPaused.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace NAL\TimeTracker\Exception;

use BadMethodCallException;

class TimerAlreadyPaused extends BadMethodCallException
{
public function __construct($id)
{
parent::__construct("The timer with ID '{$id}' is already paused and not yet resumed");
}
}
13 changes: 13 additions & 0 deletions src/Exception/UnmatchedPauseWithoutResume.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace NAL\TimeTracker\Exception;

use RuntimeException;

class UnmatchedPauseWithoutResume extends RuntimeException
{
public function __construct($id)
{
parent::__construct("Unmatched pause without resume for timer with ID '{$id}'");
}
}
8 changes: 8 additions & 0 deletions src/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,12 @@ private function _convert(float|int $from, float|int $to, string $operator, bool
default => throw new UnsupportedLogic("Unsupported operator '{$operator}' in unit definition."),
};
}

/**
* @return string
*/
public function __toString(): string
{
return $this->calculated;
}
}
Loading