• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

php-coveralls / php-coveralls / 3826244124

pending completion
3826244124

push

github

Dariusz Ruminski
CS

1562 of 1648 relevant lines covered (94.78%)

10.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.51
/src/Bundle/CoverallsBundle/Entity/JsonFile.php
1
<?php
2

3
namespace PhpCoveralls\Bundle\CoverallsBundle\Entity;
4

5
use PhpCoveralls\Bundle\CoverallsBundle\Entity\Exception\RequirementsNotSatisfiedException;
6
use PhpCoveralls\Bundle\CoverallsBundle\Entity\Git\Git;
7
use PhpCoveralls\Bundle\CoverallsBundle\Version;
8

9
/**
10
 * Data represents "json_file" of Coveralls API.
11
 *
12
 * @author Kitamura Satoshi <with.no.parachute@gmail.com>
13
 *
14
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
15
 */
16
class JsonFile extends Coveralls
17
{
18
    /**
19
     * Service name.
20
     *
21
     * @var null|string
22
     */
23
    protected $serviceName;
24

25
    /**
26
     * Service job id.
27
     *
28
     * @var null|string
29
     */
30
    protected $serviceJobId;
31

32
    /**
33
     * Service number (not documented).
34
     *
35
     * @var string
36
     */
37
    protected $serviceNumber;
38

39
    /**
40
     * Service event type (not documented).
41
     *
42
     * @var string
43
     */
44
    protected $serviceEventType;
45

46
    /**
47
     * Build URL of the project (not documented).
48
     *
49
     * @var string
50
     */
51
    protected $serviceBuildUrl;
52

53
    /**
54
     * Branch name (not documented).
55
     *
56
     * @var string
57
     */
58
    protected $serviceBranch;
59

60
    /**
61
     * Pull request info (not documented).
62
     *
63
     * @var string
64
     */
65
    protected $servicePullRequest;
66

67
    /**
68
     * Repository token.
69
     *
70
     * @var null|string
71
     */
72
    protected $repoToken;
73

74
    /**
75
     * Source files.
76
     *
77
     * @var \PhpCoveralls\Bundle\CoverallsBundle\Entity\SourceFile[]
78
     */
79
    protected $sourceFiles = [];
80

81
    /**
82
     * Git data.
83
     *
84
     * @var null|Git
85
     */
86
    protected $git;
87

88
    /**
89
     * A timestamp when the job ran. Must be parsable by Ruby.
90
     *
91
     * "2013-02-18 00:52:48 -0800"
92
     *
93
     * @var null|string
94
     */
95
    protected $runAt;
96

97
    /**
98
     * Metrics.
99
     *
100
     * @var Metrics
101
     */
102
    protected $metrics;
103

104
    /**
105
     * If this is set, the build will not be considered done until a webhook has
106
     * been sent to https://coveralls.io/webhook?repo_token=….
107
     *
108
     * @var bool
109
     */
110
    protected $parallel;
111

112
    /**
113
     * If this is set, the job being reported will be named in the view and have
114
     * it’s own independent status reported to your VCS provider.
115
     *
116
     * @var string
117
     */
118
    protected $flagName;
119

120
    // API
121

122
    /**
123
     * {@inheritdoc}
124
     *
125
     * @see \PhpCoveralls\Bundle\CoverallsBundle\Entity\ArrayConvertable::toArray()
126
     */
127
    public function toArray()
128
    {
129
        $array = [];
16✔
130

131
        $arrayMap = [
8✔
132
            // json key => property name
133
            'service_name' => 'serviceName',
16✔
134
            'service_job_id' => 'serviceJobId',
16✔
135
            'service_number' => 'serviceNumber',
16✔
136
            'service_build_url' => 'serviceBuildUrl',
16✔
137
            'service_branch' => 'serviceBranch',
16✔
138
            'service_pull_request' => 'servicePullRequest',
16✔
139
            'service_event_type' => 'serviceEventType',
16✔
140
            'repo_token' => 'repoToken',
16✔
141
            'parallel' => 'parallel',
16✔
142
            'flag_name' => 'flagName',
16✔
143
            'git' => 'git',
16✔
144
            'run_at' => 'runAt',
16✔
145
            'source_files' => 'sourceFiles',
16✔
146
        ];
16✔
147

148
        foreach ($arrayMap as $jsonKey => $propName) {
16✔
149
            if (isset($this->$propName)) {
16✔
150
                $array[$jsonKey] = $this->toJsonProperty($this->$propName);
16✔
151
            }
8✔
152
        }
8✔
153

154
        $array['environment'] = [
16✔
155
            'packagist_version' => Version::VERSION,
16✔
156
        ];
8✔
157

158
        return $array;
16✔
159
    }
160

161
    /**
162
     * Fill environment variables.
163
     *
164
     * @param array $env $_SERVER environment
165
     *
166
     * @return $this
167
     *
168
     * @throws \RuntimeException
169
     */
170
    public function fillJobs(array $env)
171
    {
172
        return $this
16✔
173
            ->fillStandardizedEnvVars($env)
16✔
174
            ->ensureJobs()
16✔
175
        ;
14✔
176
    }
177

178
    /**
179
     * Exclude source files that have no executable statements.
180
     */
181
    public function excludeNoStatementsFiles()
182
    {
183
        $this->sourceFiles = array_filter(
2✔
184
            $this->sourceFiles,
2✔
185
            function (SourceFile $sourceFile) {
1✔
186
                return $sourceFile->getMetrics()->hasStatements();
2✔
187
            }
1✔
188
        );
2✔
189
    }
1✔
190

191
    /**
192
     * Sort source files by path.
193
     */
194
    public function sortSourceFiles()
195
    {
196
        ksort($this->sourceFiles);
2✔
197
    }
1✔
198

199
    /**
200
     * Return line coverage.
201
     *
202
     * @return float
203
     */
204
    public function reportLineCoverage()
205
    {
206
        $metrics = $this->getMetrics();
2✔
207

208
        foreach ($this->sourceFiles as $sourceFile) {
2✔
209
            /* @var $sourceFile \PhpCoveralls\Bundle\CoverallsBundle\Entity\SourceFile */
210
            $metrics->merge($sourceFile->getMetrics());
2✔
211
        }
1✔
212

213
        return $metrics->getLineCoverage();
2✔
214
    }
215

216
    // accessor
217

218
    /**
219
     * Return whether the json file has source file.
220
     *
221
     * @param string $path absolute path to source file
222
     *
223
     * @return bool
224
     */
225
    public function hasSourceFile($path)
226
    {
227
        return isset($this->sourceFiles[$path]);
22✔
228
    }
229

230
    /**
231
     * Return source file.
232
     *
233
     * @param string $path absolute path to source file
234
     *
235
     * @return null|\PhpCoveralls\Bundle\CoverallsBundle\Entity\SourceFile
236
     */
237
    public function getSourceFile($path)
238
    {
239
        if ($this->hasSourceFile($path)) {
4✔
240
            return $this->sourceFiles[$path];
2✔
241
        }
242
    }
1✔
243

244
    /**
245
     * Add source file.
246
     */
247
    public function addSourceFile(SourceFile $sourceFile)
248
    {
249
        $this->sourceFiles[$sourceFile->getPath()] = $sourceFile;
22✔
250
    }
11✔
251

252
    /**
253
     * Return whether the json file has a source file.
254
     *
255
     * @return bool
256
     */
257
    public function hasSourceFiles()
258
    {
259
        return \count($this->sourceFiles) > 0;
20✔
260
    }
261

262
    /**
263
     * Return source files.
264
     *
265
     * @return \PhpCoveralls\Bundle\CoverallsBundle\Entity\SourceFile[]
266
     */
267
    public function getSourceFiles()
268
    {
269
        return $this->sourceFiles;
6✔
270
    }
271

272
    /**
273
     * Set service name.
274
     *
275
     * @param string $serviceName service name
276
     *
277
     * @return $this
278
     */
279
    public function setServiceName($serviceName)
280
    {
281
        $this->serviceName = $serviceName;
2✔
282

283
        return $this;
2✔
284
    }
285

286
    /**
287
     * Return service name.
288
     *
289
     * @return null|string
290
     */
291
    public function getServiceName()
292
    {
293
        return $this->serviceName;
14✔
294
    }
295

296
    /**
297
     * Set repository token.
298
     *
299
     * @param string $repoToken repository token
300
     *
301
     * @return $this
302
     */
303
    public function setRepoToken($repoToken)
304
    {
305
        $this->repoToken = $repoToken;
2✔
306

307
        return $this;
2✔
308
    }
309

310
    /**
311
     * Return repository token.
312
     *
313
     * @return null|string
314
     */
315
    public function getRepoToken()
316
    {
317
        return $this->repoToken;
12✔
318
    }
319

320
    /**
321
     * Set parallel.
322
     *
323
     * @param string $parallel parallel
324
     *
325
     * @return $this
326
     */
327
    public function setParallel($parallel)
328
    {
329
        $this->parallel = $parallel;
2✔
330

331
        return $this;
2✔
332
    }
333

334
    /**
335
     * Return parallel.
336
     *
337
     * @return null|bool
338
     */
339
    public function getParallel()
340
    {
341
        return $this->parallel;
4✔
342
    }
343

344
    /**
345
     * Set flag name.
346
     *
347
     * @param string $flagName flag name
348
     *
349
     * @return $this
350
     */
351
    public function setFlagName($flagName)
352
    {
353
        $this->flagName = $flagName;
2✔
354

355
        return $this;
2✔
356
    }
357

358
    /**
359
     * Return flag name.
360
     *
361
     * @return null|string
362
     */
363
    public function getFlagName()
364
    {
365
        return $this->flagName;
2✔
366
    }
367

368
    /**
369
     * Set service job id.
370
     *
371
     * @param string $serviceJobId service job id
372
     *
373
     * @return $this
374
     */
375
    public function setServiceJobId($serviceJobId)
376
    {
377
        $this->serviceJobId = $serviceJobId;
2✔
378

379
        return $this;
2✔
380
    }
381

382
    /**
383
     * Return service job id.
384
     *
385
     * @return null|string
386
     */
387
    public function getServiceJobId()
388
    {
389
        return $this->serviceJobId;
10✔
390
    }
391

392
    /**
393
     * Return service number.
394
     *
395
     * @return string
396
     */
397
    public function getServiceNumber()
398
    {
399
        return $this->serviceNumber;
8✔
400
    }
401

402
    /**
403
     * Return service event type.
404
     *
405
     * @return string
406
     */
407
    public function getServiceEventType()
408
    {
409
        return $this->serviceEventType;
4✔
410
    }
411

412
    /**
413
     * Return build URL of the project.
414
     *
415
     * @return string
416
     */
417
    public function getServiceBuildUrl()
418
    {
419
        return $this->serviceBuildUrl;
4✔
420
    }
421

422
    /**
423
     * Return branch name.
424
     *
425
     * @return string
426
     */
427
    public function getServiceBranch()
428
    {
429
        return $this->serviceBranch;
4✔
430
    }
431

432
    /**
433
     * Return pull request info.
434
     *
435
     * @return string
436
     */
437
    public function getServicePullRequest()
438
    {
439
        return $this->servicePullRequest;
4✔
440
    }
441

442
    /**
443
     * Set git data.
444
     *
445
     * @param Git $git git data
446
     *
447
     * @return $this
448
     */
449
    public function setGit(Git $git)
450
    {
451
        $this->git = $git;
2✔
452

453
        return $this;
2✔
454
    }
455

456
    /**
457
     * Return git data.
458
     *
459
     * @return null|Git
460
     */
461
    public function getGit()
462
    {
463
        return $this->git;
4✔
464
    }
465

466
    /**
467
     * Set timestamp when the job ran.
468
     *
469
     * @param string $runAt timestamp
470
     *
471
     * @return $this
472
     */
473
    public function setRunAt($runAt)
474
    {
475
        $this->runAt = $runAt;
22✔
476

477
        return $this;
22✔
478
    }
479

480
    /**
481
     * Return timestamp when the job ran.
482
     *
483
     * @return null|string
484
     */
485
    public function getRunAt()
486
    {
487
        return $this->runAt;
4✔
488
    }
489

490
    /**
491
     * Return metrics.
492
     *
493
     * @return \PhpCoveralls\Bundle\CoverallsBundle\Entity\Metrics
494
     */
495
    public function getMetrics()
496
    {
497
        if ($this->metrics === null) {
4✔
498
            $this->metrics = new Metrics();
4✔
499
        }
2✔
500

501
        return $this->metrics;
4✔
502
    }
503

504
    // internal method
505

506
    /**
507
     * Convert to json property.
508
     *
509
     * @param mixed $prop
510
     *
511
     * @return mixed
512
     */
513
    protected function toJsonProperty($prop)
514
    {
515
        if ($prop instanceof Coveralls) {
16✔
516
            return $prop->toArray();
4✔
517
        }
518

519
        if (\is_array($prop)) {
16✔
520
            return $this->toJsonPropertyArray($prop);
16✔
521
        }
522

523
        return $prop;
10✔
524
    }
525

526
    /**
527
     * Convert to array as json property.
528
     *
529
     * @return array
530
     */
531
    protected function toJsonPropertyArray(array $propArray)
532
    {
533
        $array = [];
16✔
534

535
        foreach ($propArray as $prop) {
16✔
536
            $array[] = $this->toJsonProperty($prop);
2✔
537
        }
8✔
538

539
        return $array;
16✔
540
    }
541

542
    /**
543
     * Fill standardized environment variables.
544
     *
545
     * "CI_NAME", "CI_BUILD_NUMBER" must be set.
546
     *
547
     * Env vars are:
548
     *
549
     * * CI_NAME
550
     * * CI_BUILD_NUMBER
551
     * * CI_BUILD_URL
552
     * * CI_BRANCH
553
     * * CI_PULL_REQUEST
554
     *
555
     * These vars are supported by Codeship.
556
     *
557
     * @param array $env $_SERVER environment
558
     *
559
     * @return $this
560
     */
561
    protected function fillStandardizedEnvVars(array $env)
562
    {
563
        $map = [
8✔
564
            // defined in Ruby lib
565
            'serviceName' => 'CI_NAME',
16✔
566
            'serviceNumber' => 'CI_BUILD_NUMBER',
16✔
567
            'serviceBuildUrl' => 'CI_BUILD_URL',
16✔
568
            'serviceBranch' => 'CI_BRANCH',
16✔
569
            'servicePullRequest' => 'CI_PULL_REQUEST',
16✔
570

571
            // extends by php-coveralls
572
            'serviceJobId' => 'CI_JOB_ID',
16✔
573
            'serviceEventType' => 'COVERALLS_EVENT_TYPE',
16✔
574
            'repoToken' => 'COVERALLS_REPO_TOKEN',
16✔
575
            'parallel' => 'COVERALLS_PARALLEL',
16✔
576
            'flagName' => 'COVERALLS_FLAG_NAME',
16✔
577
        ];
16✔
578

579
        foreach ($map as $propName => $envName) {
16✔
580
            if (isset($env[$envName])) {
16✔
581
                $this->$propName = $env[$envName];
12✔
582
            }
6✔
583
        }
8✔
584

585
        return $this;
16✔
586
    }
587

588
    /**
589
     * Ensure data consistency for jobs API.
590
     *
591
     * @return $this
592
     *
593
     * @throws \RuntimeException
594
     */
595
    protected function ensureJobs()
596
    {
597
        if (!$this->hasSourceFiles()) {
16✔
598
            throw new \RuntimeException('source_files must be set');
2✔
599
        }
600

601
        if ($this->requireServiceJobId()) {
14✔
602
            return $this;
2✔
603
        }
604

605
        if ($this->requireServiceNumber()) {
12✔
606
            return $this;
4✔
607
        }
608

609
        if ($this->requireServiceEventType()) {
8✔
610
            return $this;
2✔
611
        }
612

613
        if ($this->requireRepoToken()) {
6✔
614
            return $this;
×
615
        }
616

617
        if ($this->requireGithubActions()) {
6✔
618
            return $this;
2✔
619
        }
620

621
        if ($this->isUnsupportedServiceJob()) {
4✔
622
            return $this;
2✔
623
        }
624

625
        throw new RequirementsNotSatisfiedException();
2✔
626
    }
627

628
    /**
629
     * Return whether the job requires "service_job_id" (for Travis CI).
630
     *
631
     * @return bool
632
     */
633
    protected function requireServiceJobId()
634
    {
635
        return $this->serviceName !== null
14✔
636
            && $this->serviceNumber !== null
14✔
637
            && $this->serviceJobId !== null
14✔
638
            && $this->repoToken === null;
14✔
639
    }
640

641
    /**
642
     * Return whether the job requires "service_number" (for CircleCI, Jenkins, Codeship or other CIs).
643
     *
644
     * @return bool
645
     */
646
    protected function requireServiceNumber()
647
    {
648
        return $this->serviceName !== null
12✔
649
            && $this->serviceNumber !== null
12✔
650
            && $this->repoToken !== null;
12✔
651
    }
652

653
    /**
654
     * Return whether the job requires "service_event_type" (for local environment).
655
     *
656
     * @return bool
657
     */
658
    protected function requireServiceEventType()
659
    {
660
        return $this->serviceName !== null
8✔
661
            && $this->serviceEventType !== null
8✔
662
            && $this->repoToken !== null;
8✔
663
    }
664

665
    /**
666
     * Return whether the job requires "repo_token" (for Travis PRO).
667
     *
668
     * @return bool
669
     */
670
    protected function requireRepoToken()
671
    {
672
        return $this->serviceName === 'travis-pro'
6✔
673
            && $this->repoToken !== null;
6✔
674
    }
675

676
    /**
677
     * Return whether the job requires "service_number", "service_job_id" and "repo_token" (for GithubActions).
678
     *
679
     * @return bool
680
     */
681
    protected function requireGithubActions()
682
    {
683
        return $this->serviceName === 'github' && $this->serviceJobId !== null && $this->repoToken !== null;
6✔
684
    }
685

686
    /**
687
     * Return whether the job is running on unsupported service.
688
     *
689
     * @return bool
690
     */
691
    protected function isUnsupportedServiceJob()
692
    {
693
        return $this->serviceJobId === null
4✔
694
            && $this->serviceNumber === null
4✔
695
            && $this->serviceEventType === null
4✔
696
            && $this->repoToken !== null;
4✔
697
    }
698

699
    protected function onJsonError()
700
    {
701
        $array = $this->toArray();
×
702

703
        if (!empty($array['git'])) {
×
704
            $this->throwWhenInvalidJson($array['git'], '[git]');
×
705
        }
706

707
        $sourceFiles = empty($array['source_files']) ? [] : $array['source_files'];
×
708

709
        foreach ($sourceFiles as $item) {
×
710
            $this->throwWhenInvalidJson($item, '[source_files]: ' . $item['name']);
×
711
        }
712
    }
713

714
    /**
715
     * @param string $source
716
     */
717
    private function throwWhenInvalidJson(array $item, $source)
718
    {
719
        json_encode($item);
×
720

721
        if (json_last_error() !== JSON_ERROR_NONE) {
×
722
            throw new \UnexpectedValueException(sprintf(
×
723
                'Can not encode to JSON, error: "%s" in "%s".',
×
724
                json_last_error_msg(),
×
725
                $source
726
            ));
×
727
        }
728
    }
729
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc