├── .gitignore
├── src
├── NaturalLanguageFacade.php
├── Verdict.php
├── NaturalLanguageServiceProvider.php
├── NaturalLanguageClient.php
└── NaturalLanguage.php
├── phpunit.xml.dist
├── config
└── naturallanguage.php
├── LICENSE.txt
├── google.md
├── .github
└── workflows
│ └── run-tests.yml
├── CHANGELOG.md
├── composer.json
├── README.md
└── tests
└── NaturalLanguageTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.lock
3 | .DS_Store
4 | Thumbs.db
5 | phpunit.xml
6 | /.idea
--------------------------------------------------------------------------------
/src/NaturalLanguageFacade.php:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 | ./tests
12 |
13 |
14 |
15 |
16 | ./src
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/NaturalLanguageServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
12 | __DIR__ . '/../config/naturallanguage.php' => config_path('naturallanguage.php'),
13 | ]);
14 | }
15 |
16 | public function register()
17 | {
18 | $this->mergeConfigFrom(__DIR__ . '/../config/naturallanguage.php', 'naturallanguage');
19 |
20 | $this->app->bind(NaturalLanguageClient::class, function () {
21 | return new NaturalLanguageClient(config('naturallanguage'));
22 | });
23 |
24 | $this->app->bind(NaturalLanguage::class, function () {
25 | $client = app(NaturalLanguageClient::class);
26 |
27 | return new NaturalLanguage($client);
28 | });
29 |
30 | $this->app->alias(NaturalLanguage::class, 'laravel-natural-language');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/config/naturallanguage.php:
--------------------------------------------------------------------------------
1 | env('NATURAL_LANGUAGE_PROJECT_ID', 'sample-12345'),
18 |
19 | /*
20 | |--------------------------------------------------------------------------
21 | | Path to the json file containing the authentication credentials.
22 | |--------------------------------------------------------------------------
23 | */
24 | 'key_file_path' => base_path('composer.json'),
25 | ];
26 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Jogg Inc
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/google.md:
--------------------------------------------------------------------------------
1 | - After logging in the Google Cloud Platform console you will need to enable the Cloud Natural Language API via the API Library section.
2 |
3 | - Now, we first need to create a new project in the Google Cloud Platform console.
4 |
5 | - You will see a screen like this once you click on "New Project" on the dashoard:
6 |
7 |
8 |
9 | - After creating the project, please note down the **Project ID** and add it to the `.env` file for the key `NATURAL_LANGUAGE_PROJECT_ID`.
10 |
11 | - Select the project you have created, and go the "Create Service Account Key" page and in the 'Service Account' section click on 'New Service Account'.
12 |
13 | - Enter the name & select the Role as 'Owner' for the project.
14 |
15 | - Then click on create to have the JSON credentials file downloaded automatically.
16 |
17 | - Add that json file in your laravel project root & add it to `.gitignore`.
18 |
19 | - Set the path to that file as the value for the key `key_file_path` in the `config/naturallanguage.php` (config file published by this package).
--------------------------------------------------------------------------------
/.github/workflows/run-tests.yml:
--------------------------------------------------------------------------------
1 | name: "Run Tests"
2 |
3 | on: [push]
4 |
5 | jobs:
6 | test:
7 |
8 | runs-on: ubuntu-latest
9 | strategy:
10 | fail-fast: true
11 | matrix:
12 | php: [8.1]
13 | laravel: [10.*]
14 | dependency-version: [prefer-lowest, prefer-stable]
15 |
16 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }}
17 |
18 | steps:
19 | - name: Checkout code
20 | uses: actions/checkout@v2
21 |
22 | - name: Cache dependencies
23 | uses: actions/cache@v2
24 | with:
25 | path: ~/.composer/cache/files
26 | key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
27 |
28 | - name: Setup PHP
29 | uses: shivammathur/setup-php@v2
30 | with:
31 | php-version: ${{ matrix.php }}
32 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
33 | coverage: none
34 |
35 | - name: Install dependencies
36 | run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest
37 |
38 | - name: Execute tests
39 | run: vendor/bin/phpunit
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | All the notable changes to the Laravel Natural Language package are documented in this file:
2 |
3 | ## v7.0.0 (11-02-2022)
4 | - Added Laravel 9 support and dropped support for Laravel 7 and 8, and PHP 7.
5 |
6 | ## v6.0.1 (06-01-2021)
7 | - Add PHP 8 support.
8 |
9 | ## v6.0.0 (28-09-2020)
10 | - Updated the underlying google cloud language sdk
11 |
12 | ## v5.0.0 (10-09-2020)
13 | - Added Laravel v8.x support.
14 | - Dropped Laravel v6 & PHPUnit v8 support.
15 |
16 | ## v4.0.0 (03-03-2020)
17 | - Added Laravel v7.x support.
18 | - Dropped PHP v7.2 support, now PHP v7.3 is the minimum requirement.
19 |
20 | ## v3.0.1 (14-01-2020)
21 | - Added Github Actions workflow
22 |
23 | ## v3.0.0 (04-09-2019)
24 | - Now supports Laravel v6.0
25 | - Support for Laravel v5.8 will be dropped in v3.1
26 |
27 | ## v2.1.0 (20-08-2019)
28 | - Update google-cloud-language sdk
29 |
30 | ## v2.0.1 (27-02-2019)
31 | - Remove phpunit deprications
32 |
33 | ## v2.0.0 (27-02-2019)
34 | - Now supports Laravel v5.8
35 |
36 | ## v1.0.2 (13-10-2018)
37 | - [Refactor](https://github.com/JoggApp/laravel-natural-language/pull/3)
38 | - Thanks to [Sven](https://github.com/svenluijten) for the PR :smile:
39 |
40 | ## v1.0.1 (12-10-2018)
41 | - [Typo fix](https://github.com/JoggApp/laravel-natural-language/pull/1)
42 |
43 | ## v1.0.0 (11-10-2018)
44 | - Initial release
45 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "joggapp/laravel-natural-language",
3 | "description": "Laravel package for the Google Natural language API",
4 | "keywords": [
5 | "laravel",
6 | "package",
7 | "google",
8 | "natural language",
9 | "api"
10 | ],
11 | "license": "MIT",
12 | "authors": [
13 | {
14 | "name": "Harish Toshniwal",
15 | "email": "harish@jogg.co"
16 | }
17 | ],
18 | "autoload": {
19 | "psr-4": {
20 | "JoggApp\\NaturalLanguage\\": "src"
21 | }
22 | },
23 | "autoload-dev": {
24 | "psr-4": {
25 | "JoggApp\\NaturalLanguage\\Tests\\": "tests"
26 | }
27 | },
28 | "require": {
29 | "php": "^8.1",
30 | "google/cloud-language": "^0.28.0",
31 | "illuminate/support": "10.*"
32 | },
33 | "require-dev": {
34 | "mockery/mockery": "^1.1",
35 | "orchestra/testbench" : "8.*",
36 | "phpunit/phpunit": "^9.0"
37 | },
38 | "extra": {
39 | "laravel": {
40 | "providers": [
41 | "JoggApp\\NaturalLanguage\\NaturalLanguageServiceProvider"
42 | ],
43 | "aliases":{
44 | "NaturalLanguage": "JoggApp\\NaturalLanguage\\NaturalLanguageFacade"
45 | }
46 | }
47 | },
48 | "config": {
49 | "sort-packages": true
50 | },
51 | "minimum-stability": "dev",
52 | "prefer-stable": true
53 | }
54 |
--------------------------------------------------------------------------------
/src/NaturalLanguageClient.php:
--------------------------------------------------------------------------------
1 | checkForInvalidConfiguration($config);
15 |
16 | $this->language = new LanguageClient([
17 | 'keyFilePath' => $config['key_file_path'],
18 | 'projectId' => $config['project_id']
19 | ]);
20 | }
21 |
22 | public function sentiment(string $text)
23 | {
24 | return $this->language
25 | ->analyzeSentiment($text)
26 | ->sentiment();
27 | }
28 |
29 | public function entities(string $text)
30 | {
31 | return $this->language
32 | ->analyzeEntities($text)
33 | ->entities();
34 | }
35 |
36 | public function entitySentiment(string $text)
37 | {
38 | return $this->language
39 | ->analyzeEntitySentiment($text)
40 | ->entities();
41 | }
42 |
43 | public function syntax(string $text)
44 | {
45 | return $this
46 | ->language
47 | ->analyzeSyntax($text);
48 | }
49 |
50 | public function categories(string $text)
51 | {
52 | return $this->language
53 | ->classifyText($text)
54 | ->categories();
55 | }
56 |
57 | public function annotateText(string $text, array $features = [])
58 | {
59 | return empty($features)
60 | ? $this->language->annotateText($text)
61 | : $this->language->annotateText($text, ['features' => $features]);
62 | }
63 |
64 | private function checkForInvalidConfiguration(array $config)
65 | {
66 | if (!file_exists($config['key_file_path'])) {
67 | throw new Exception('The json file does not exist at the given path');
68 | }
69 |
70 | if ((!is_string($config['project_id'])) || empty($config['project_id'])) {
71 | throw new Exception('Please set a valid project id');
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/NaturalLanguage.php:
--------------------------------------------------------------------------------
1 | languageClient = $client;
12 | }
13 |
14 | public function sentiment(string $text): array
15 | {
16 | $sentiment = $this
17 | ->languageClient
18 | ->sentiment($text);
19 |
20 | $verdict = $this->prepareVerdict($sentiment['score'], $sentiment['magnitude']);
21 |
22 | return [
23 | 'text' => $text,
24 | 'verdict' => $verdict,
25 | 'score' => $sentiment['score'],
26 | 'magnitude' => $sentiment['magnitude']
27 | ];
28 | }
29 |
30 | public function entities(string $text): array
31 | {
32 | $entities = $this
33 | ->languageClient
34 | ->entities($text);
35 |
36 | return [
37 | 'text' => $text,
38 | 'entities' => $entities
39 | ];
40 | }
41 |
42 | public function entitySentiment(string $text): array
43 | {
44 | $entities = $this
45 | ->languageClient
46 | ->entitySentiment($text);
47 |
48 | return [
49 | 'text' => $text,
50 | 'entities' => $entities
51 | ];
52 | }
53 |
54 | public function syntax(string $text): array
55 | {
56 | $syntax = $this
57 | ->languageClient
58 | ->syntax($text);
59 |
60 | return [
61 | 'text' => $text,
62 | 'sentences' => method_exists($syntax, 'sentences') ? $syntax->sentences() : null,
63 | 'tokens' => method_exists($syntax, 'tokens') ? $syntax->tokens() : null,
64 | 'language' => method_exists($syntax, 'language') ? $syntax->language() : null
65 | ];
66 | }
67 |
68 | public function categories(string $text): array
69 | {
70 | $categories = $this
71 | ->languageClient
72 | ->categories($text);
73 |
74 | return [
75 | 'text' => $text,
76 | 'categories' => $categories
77 | ];
78 | }
79 |
80 | public function annotateText(string $text, array $features = []): array
81 | {
82 | $annotation = $this
83 | ->languageClient
84 | ->annotateText($text, $features);
85 |
86 | if (is_null($annotation)) {
87 | return [
88 | 'text' => $text,
89 | 'sentences' => null,
90 | 'tokens' => null,
91 | 'entities' => null,
92 | 'sentiment' => null,
93 | 'categories' => null,
94 | 'language' => null,
95 | ];
96 | }
97 |
98 | return [
99 | 'text' => $text,
100 | 'sentences' => method_exists($annotation, 'sentences') ? $annotation->sentences() : null,
101 | 'tokens' => method_exists($annotation, 'tokens') ? $annotation->tokens() : null,
102 | 'entities' => method_exists($annotation, 'entities') ? $annotation->entities() : null,
103 | 'sentiment' => method_exists($annotation, 'sentiment') ? $annotation->sentiment() : null,
104 | 'categories' => method_exists($annotation, 'categories') ? $annotation->categories() : null,
105 | 'language' => method_exists($annotation, 'language') ? $annotation->language() : null,
106 | ];
107 | }
108 |
109 | public function prepareVerdict(float $score, float $magnitude): string
110 | {
111 | if (in_array($score, range(-1.0, -0.25, 0.01))) {
112 | if (in_array($magnitude, range(1.0, 100.0, 0.01))) {
113 | return Verdict::VERY_NEGATIVE;
114 | }
115 |
116 | return Verdict::MOSTLY_NEGATIVE;
117 | }
118 |
119 | if (in_array($score, range(0.25, 1.0, 0.01))) {
120 | if (in_array($magnitude, range(1.0, 100.0, 0.01))) {
121 | return Verdict::VERY_POSITIVE;
122 | }
123 |
124 | return Verdict::MOSTLY_POSITIVE;
125 | }
126 |
127 | return Verdict::MIXED_AND_NEUTRAL;
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # THIS PACKAGE IS NO LONGER ACTIVELY MAINTAINED. USERS ARE ADVISED TO REPLACE IT WITH ALTERNATIVES.
2 |
3 | # Laravel package for the Google Natural language API
4 |
5 | [](https://github.com/JoggApp/laravel-natural-language/releases)
6 | 
7 | [](https://packagist.org/packages/JoggApp/laravel-natural-language)
8 |
9 | This package makes using the Google Natural API in your laravel app a breeze with minimum to no configuration, clean syntax and a consistent package API. All methods accept a string and return an array: [Docs below.](https://github.com/JoggApp/laravel-natural-language/#how-to-use)
10 |
11 | 
12 |
13 | ## Installation
14 |
15 | - You can install this package via composer using this command:
16 |
17 | ```bash
18 | composer require joggapp/laravel-natural-language
19 | ```
20 |
21 | - The package will automatically register itself.
22 |
23 | - We have documented how to setup the project and get the necessary configurations from the Google Cloud Platform console in a step by step detailed manner [over here.](https://github.com/JoggApp/laravel-natural-language/blob/master/google.md)
24 |
25 | - You can publish the config file using the following command:
26 |
27 | ```bash
28 | php artisan vendor:publish --provider="JoggApp\NaturalLanguage\NaturalLanguageServiceProvider"
29 | ```
30 |
31 | This will create the package's config file called `naturallanguage.php` in the `config` directory. These are the contents of the published config file:
32 |
33 | ```php
34 | return [
35 | /*
36 | |--------------------------------------------------------------------------
37 | | The id of project created in the Google Cloud Platform console.
38 | |--------------------------------------------------------------------------
39 | */
40 | 'project_id' => env('NATURAL_LANGUAGE_PROJECT_ID', 'sample-12345'),
41 |
42 | /*
43 | |--------------------------------------------------------------------------
44 | | Path to the json file containing the authentication credentials.
45 | |--------------------------------------------------------------------------
46 | */
47 | 'key_file_path' => base_path('composer.json'),
48 | ];
49 | ```
50 |
51 | ## How to use
52 |
53 | - After setting up the config file values you are all set to use the following methods :smile:
54 |
55 | - Detect the Sentiment: Accepts a string and returns an array.
56 |
57 | ```php
58 | NaturalLanguage::sentiment(string $text): array
59 | ```
60 |
61 | - Detect the Entities: Accepts a string and returns an array.
62 |
63 | ```php
64 | NaturalLanguage::entities(string $text): array
65 | ```
66 |
67 | - Detect the Sentiment per entity basis: Accepts a string and returns an array.
68 |
69 | ```php
70 | NaturalLanguage::entitySentiment(string $text): array
71 | ```
72 |
73 | - Detect the syntax: Accepts a string and returns an array.
74 |
75 | ```php
76 | NaturalLanguage::syntax(string $text): array
77 | ```
78 |
79 | - Detect the categories: Accepts a string and returns an array.
80 |
81 | ```php
82 | NaturalLanguage::categories(string $text): array
83 | ```
84 |
85 | - Annotate text: Accepts a string and an optional `features` array & returns an array.
86 |
87 | ```php
88 | NaturalLanguage::annotateText(string $text, array $features = ['sentiment', 'syntax']): array
89 | ```
90 |
91 | ## Testing
92 |
93 | You can run the tests with:
94 |
95 | ```bash
96 | vendor/bin/phpunit
97 | ```
98 |
99 | ## Changelog
100 |
101 | Please see the [CHANGELOG](CHANGELOG.md) for more information about what has changed recently.
102 |
103 | ## Security
104 |
105 | If you discover any security related issues, please email them to [harish@jogg.co](mailto:harish@jogg.co) instead of using the issue tracker.
106 |
107 | ## Credits
108 |
109 | - [Harish Toshniwal](https://github.com/introwit)
110 | - [All Contributors](../../contributors)
111 |
112 | ## License
113 |
114 | The MIT License (MIT). Please see the [License File](LICENSE.txt) for more information.
115 |
--------------------------------------------------------------------------------
/tests/NaturalLanguageTest.php:
--------------------------------------------------------------------------------
1 | languageClient = Mockery::mock(NaturalLanguageClient::class);
25 |
26 | $this->language = new NaturalLanguage($this->languageClient);
27 | }
28 |
29 | public function tearDown(): void
30 | {
31 | Mockery::close();
32 | }
33 |
34 | /** @test */
35 | public function it_can_detect_the_sentiment_of_string_passed_to_it()
36 | {
37 | $this->languageClient
38 | ->shouldReceive('sentiment')->with($this->testString)
39 | ->once()
40 | ->andReturn(['score' => 0.8, 'magnitude' => 0.8]);
41 |
42 | $response = $this->language->sentiment($this->testString);
43 |
44 | $this->assertIsArray($response);
45 |
46 | $this->assertArrayHasKey('text', $response);
47 | $this->assertArrayHasKey('verdict', $response);
48 | $this->assertArrayHasKey('score', $response);
49 | $this->assertArrayHasKey('magnitude', $response);
50 | }
51 |
52 | /** @test */
53 | public function it_gives_the_correct_verdict_based_on_the_score_and_magnitude_of_the_sentiment_of_a_string()
54 | {
55 | $verdict = $this->language->prepareVerdict(0.8, 10);
56 | $this->assertEquals(Verdict::VERY_POSITIVE, $verdict);
57 |
58 | $verdict = $this->language->prepareVerdict(-0.8, 10);
59 | $this->assertEquals(Verdict::VERY_NEGATIVE, $verdict);
60 |
61 | $verdict = $this->language->prepareVerdict(0.8, 0.10);
62 | $this->assertEquals(Verdict::MOSTLY_POSITIVE, $verdict);
63 |
64 | $verdict = $this->language->prepareVerdict(-0.8, 0.10);
65 | $this->assertEquals(Verdict::MOSTLY_NEGATIVE, $verdict);
66 |
67 | $verdict = $this->language->prepareVerdict(0.0, 0.0);
68 | $this->assertEquals(Verdict::MIXED_AND_NEUTRAL, $verdict);
69 | }
70 |
71 | /** @test */
72 | public function it_can_detect_the_entities_from_the_string_passed_to_it()
73 | {
74 | $this->languageClient
75 | ->shouldReceive('entities')->with($this->testString)
76 | ->once()
77 | ->andReturn([]);
78 |
79 | $response = $this->language->entities($this->testString);
80 |
81 | $this->assertIsArray($response);
82 |
83 | $this->assertArrayHasKey('text', $response);
84 | $this->assertArrayHasKey('entities', $response);
85 | }
86 |
87 | /** @test */
88 | public function it_can_detect_the_sentiment_per_entity_from_the_string_passed_to_it()
89 | {
90 | $this->languageClient
91 | ->shouldReceive('entitySentiment')->with($this->testString)
92 | ->once()
93 | ->andReturn([]);
94 |
95 | $response = $this->language->entitySentiment($this->testString);
96 |
97 | $this->assertIsArray($response);
98 |
99 | $this->assertArrayHasKey('text', $response);
100 | $this->assertArrayHasKey('entities', $response);
101 | }
102 |
103 | /** @test */
104 | public function it_can_detect_the_syntax_from_the_string_passed_to_it()
105 | {
106 | $this->languageClient
107 | ->shouldReceive('syntax')->with($this->testString)
108 | ->once()
109 | ->andReturn((new Annotation));
110 |
111 | $response = $this->language->syntax($this->testString);
112 |
113 | $this->assertIsArray($response);
114 |
115 | $this->assertArrayHasKey('text', $response);
116 | $this->assertArrayHasKey('sentences', $response);
117 | $this->assertArrayHasKey('tokens', $response);
118 | $this->assertArrayHasKey('language', $response);
119 | }
120 |
121 | /** @test */
122 | public function it_can_detect_the_categories_from_the_string_passed_to_it()
123 | {
124 | $this->languageClient
125 | ->shouldReceive('categories')->with($this->testString)
126 | ->once()
127 | ->andReturn([]);
128 |
129 | $response = $this->language->categories($this->testString);
130 |
131 | $this->assertIsArray($response);
132 |
133 | $this->assertArrayHasKey('text', $response);
134 | $this->assertArrayHasKey('categories', $response);
135 | }
136 |
137 | /** @test */
138 | public function it_can_annotate_the_string_passed_to_it()
139 | {
140 | $this->languageClient
141 | ->shouldReceive('annotateText')->withArgs([$this->testString, []])
142 | ->once()
143 | ->andReturn();
144 |
145 | $response = $this->language->annotateText($this->testString);
146 |
147 | $this->assertIsArray($response);
148 |
149 | $this->assertArrayHasKey('text', $response);
150 | $this->assertArrayHasKey('sentences', $response);
151 | $this->assertArrayHasKey('tokens', $response);
152 | $this->assertArrayHasKey('entities', $response);
153 | $this->assertArrayHasKey('sentiment', $response);
154 | $this->assertArrayHasKey('categories', $response);
155 | $this->assertArrayHasKey('language', $response);
156 | }
157 | }
158 |
--------------------------------------------------------------------------------